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