From 24673283ebaa2b2cd865204649e86bc36260d87e Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Tue, 1 Jun 2010 18:01:13 +0100 Subject: [PATCH] Major change to the way the Image class works, making it use value semantics and internally shared data (see the forum notes for more info on this). Also minor changes to win32 browser plugin object ref counting and linux millisecond timers. --- amalgamation/juce_amalgamated_template.cpp | 2 +- .../model/Drawable/jucer_DrawableDocument.cpp | 4 +- .../model/Drawable/jucer_DrawableDocument.h | 4 +- .../Source/model/Project/jucer_Project.cpp | 2 +- .../Source/model/Project/jucer_Project.h | 2 +- .../jucer_ComponentEditorTreeView.h | 10 +- .../jucer_DrawableEditorTreeView.h | 2 +- .../ui/Editor Base/jucer_EditorCanvas.cpp | 17 +- .../Source/ui/Editor Base/jucer_EditorPanel.h | 5 +- .../jucer_GroupInformationComponent.cpp | 13 +- .../jucer_ItemPreviewComponent.cpp | 15 +- .../jucer_ItemPreviewComponent.h | 2 +- .../jucer_ProjectInformationComponent.cpp | 5 +- .../jucer_ProjectTreeViewBase.h | 2 +- .../Source/ui/jucer_JucerTreeViewBase.cpp | 12 +- .../Source/ui/jucer_JucerTreeViewBase.h | 2 +- .../utility/jucer_FillTypePropertyComponent.h | 2 +- .../Source/utility/jucer_StoredSettings.cpp | 4 +- .../Source/utility/jucer_StoredSettings.h | 4 +- .../wrapper/juce_ActiveX_GlueCode.cpp | 2 +- extras/juce demo/Source/demos/CameraDemo.cpp | 18 +- extras/juce demo/Source/demos/OpenGLDemo.cpp | 17 +- .../Source/demos/RenderingTestComponent.cpp | 27 +- extras/juce demo/Source/demos/WidgetsDemo.cpp | 7 +- .../components/jucer_ImageButtonHandler.h | 8 +- .../src/model/jucer_BinaryResources.cpp | 4 +- .../src/model/jucer_BinaryResources.h | 2 +- .../src/model/jucer_GeneratedCode.cpp | 5 +- .../model/paintelements/jucer_FillType.cpp | 40 +- .../src/model/paintelements/jucer_FillType.h | 2 +- .../src/ui/jucer_ComponentLayoutEditor.cpp | 4 +- .../src/ui/jucer_ComponentLayoutEditor.h | 2 +- .../src/ui/jucer_ComponentLayoutPanel.cpp | 2 +- .../src/ui/jucer_ComponentLayoutPanel.h | 2 +- .../src/ui/jucer_JucerDocumentHolder.cpp | 4 +- .../src/ui/jucer_JucerDocumentHolder.h | 2 +- .../src/ui/jucer_PaintRoutineEditor.cpp | 21 +- .../src/ui/jucer_PaintRoutineEditor.h | 2 +- extras/the jucer/src/ui/jucer_PrefsPanel.cpp | 3 +- .../src/ui/jucer_SnapGridPainter.cpp | 15 +- .../the jucer/src/ui/jucer_SnapGridPainter.h | 2 +- juce_amalgamated.cpp | 1894 ++++++++--------- juce_amalgamated.h | 1240 ++++++----- src/containers/juce_Identifier.cpp | 22 +- src/containers/juce_Identifier.h | 4 +- src/cryptography/juce_RSAKey.cpp | 10 + src/cryptography/juce_RSAKey.h | 3 + .../components/buttons/juce_ImageButton.cpp | 57 +- src/gui/components/buttons/juce_ImageButton.h | 41 +- .../components/buttons/juce_ToolbarButton.cpp | 11 +- src/gui/components/controls/juce_ListBox.cpp | 10 +- src/gui/components/controls/juce_ListBox.h | 2 +- .../controls/juce_TableHeaderComponent.cpp | 7 +- .../controls/juce_ToolbarItemComponent.cpp | 2 +- src/gui/components/controls/juce_TreeView.cpp | 6 +- .../filebrowser/juce_FileListComponent.cpp | 24 +- .../filebrowser/juce_FileTreeComponent.cpp | 20 +- .../juce_ImagePreviewComponent.cpp | 16 +- .../filebrowser/juce_ImagePreviewComponent.h | 2 +- src/gui/components/juce_Component.cpp | 48 +- src/gui/components/juce_Component.h | 9 +- .../lookandfeel/juce_LookAndFeel.cpp | 29 +- .../components/lookandfeel/juce_LookAndFeel.h | 4 +- src/gui/components/menus/juce_PopupMenu.cpp | 33 +- src/gui/components/menus/juce_PopupMenu.h | 8 +- .../mouse/juce_DragAndDropContainer.cpp | 40 +- .../mouse/juce_DragAndDropContainer.h | 8 +- .../special/juce_ColourSelector.cpp | 19 +- .../components/special/juce_DropShadower.cpp | 77 +- .../components/special/juce_DropShadower.h | 4 +- .../special/juce_MagnifierComponent.cpp | 2 +- .../special/juce_PreferencesPanel.cpp | 8 +- .../special/juce_PreferencesPanel.h | 2 +- .../windows/juce_DocumentWindow.cpp | 6 +- .../components/windows/juce_DocumentWindow.h | 4 +- .../components/windows/juce_SplashScreen.cpp | 25 +- .../components/windows/juce_SplashScreen.h | 4 +- src/gui/graphics/contexts/juce_FillType.cpp | 8 +- src/gui/graphics/contexts/juce_FillType.h | 12 +- src/gui/graphics/contexts/juce_Graphics.cpp | 42 +- src/gui/graphics/contexts/juce_Graphics.h | 13 +- .../contexts/juce_LowLevelGraphicsContext.h | 1 + .../juce_LowLevelGraphicsSoftwareRenderer.cpp | 6 +- .../juce_LowLevelGraphicsSoftwareRenderer.h | 6 +- src/gui/graphics/drawables/juce_Drawable.cpp | 6 +- src/gui/graphics/drawables/juce_Drawable.h | 4 +- .../drawables/juce_DrawableComposite.cpp | 2 +- .../graphics/drawables/juce_DrawableImage.cpp | 73 +- .../graphics/drawables/juce_DrawableImage.h | 29 +- .../graphics/drawables/juce_DrawablePath.h | 1 + .../effects/juce_DropShadowEffect.cpp | 4 +- src/gui/graphics/effects/juce_GlowEffect.cpp | 6 +- .../effects/juce_ReduceOpacityEffect.cpp | 2 +- .../geometry/juce_RelativeCoordinate.cpp | 23 +- .../geometry/juce_RelativeCoordinate.h | 2 +- .../image_file_formats/juce_GIFLoader.cpp | 8 +- .../image_file_formats/juce_GIFLoader.h | 4 +- .../image_file_formats/juce_JPEGLoader.cpp | 10 +- .../image_file_formats/juce_PNGLoader.cpp | 14 +- src/gui/graphics/imaging/juce_CameraDevice.h | 2 +- src/gui/graphics/imaging/juce_Image.cpp | 359 ++-- src/gui/graphics/imaging/juce_Image.h | 252 ++- src/gui/graphics/imaging/juce_ImageCache.cpp | 242 +-- src/gui/graphics/imaging/juce_ImageCache.h | 93 +- .../imaging/juce_ImageConvolutionKernel.cpp | 23 +- .../imaging/juce_ImageConvolutionKernel.h | 9 +- .../graphics/imaging/juce_ImageFileFormat.cpp | 14 +- .../graphics/imaging/juce_ImageFileFormat.h | 26 +- src/io/files/juce_File.cpp | 2 +- src/io/network/juce_URL.cpp | 1 - src/native/linux/juce_linux_Network.cpp | 2 +- src/native/linux/juce_linux_SystemStats.cpp | 46 +- src/native/linux/juce_linux_Windowing.cpp | 97 +- .../mac/juce_iphone_UIViewComponentPeer.mm | 4 +- src/native/mac/juce_mac_CameraDevice.mm | 8 +- .../mac/juce_mac_CoreGraphicsContext.mm | 60 +- src/native/mac/juce_mac_MouseCursor.mm | 6 +- .../mac/juce_mac_NSViewComponentPeer.mm | 4 +- src/native/mac/juce_mac_Network.mm | 6 +- .../windows/juce_win32_CameraDevice.cpp | 21 +- src/native/windows/juce_win32_Windowing.cpp | 139 +- 121 files changed, 2763 insertions(+), 2930 deletions(-) diff --git a/amalgamation/juce_amalgamated_template.cpp b/amalgamation/juce_amalgamated_template.cpp index 0548658fe6..608d7f346d 100644 --- a/amalgamation/juce_amalgamated_template.cpp +++ b/amalgamation/juce_amalgamated_template.cpp @@ -144,6 +144,7 @@ #include "../src/threads/juce_Thread.cpp" #include "../src/threads/juce_ThreadPool.cpp" #include "../src/threads/juce_TimeSliceThread.cpp" + #include "../src/utilities/juce_DeletedAtShutdown.cpp" #endif #if JUCE_BUILD_MISC @@ -154,7 +155,6 @@ #include "../src/application/juce_ApplicationCommandManager.cpp" #include "../src/application/juce_ApplicationCommandTarget.cpp" #include "../src/application/juce_ApplicationProperties.cpp" - #include "../src/utilities/juce_DeletedAtShutdown.cpp" #include "../src/utilities/juce_PropertiesFile.cpp" #include "../src/utilities/juce_FileBasedDocument.cpp" #include "../src/utilities/juce_RecentlyOpenedFilesList.cpp" diff --git a/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.cpp b/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.cpp index 370756f969..3f70c6e926 100644 --- a/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.cpp +++ b/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.cpp @@ -275,12 +275,12 @@ const ValueTree DrawableDocument::performNewItemMenuItem (int menuResultCode) } //============================================================================== -Image* DrawableDocument::getImageForIdentifier (const var& imageIdentifier) +const Image DrawableDocument::getImageForIdentifier (const var& imageIdentifier) { return ImageCache::getFromMemory (BinaryData::juce_icon_png, BinaryData::juce_icon_pngSize); } -const var DrawableDocument::getIdentifierForImage (Image* image) +const var DrawableDocument::getIdentifierForImage (const Image& image) { return var::null; //xxx todo } diff --git a/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.h b/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.h index 7fbd6e75bc..2aaa84b41f 100644 --- a/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.h +++ b/extras/Jucer (experimental)/Source/model/Drawable/jucer_DrawableDocument.h @@ -97,8 +97,8 @@ public: const String getNonexistentMarkerName (const String& name); void renameAnchor (const String& oldName, const String& newName); - Image* getImageForIdentifier (const var& imageIdentifier); - const var getIdentifierForImage (Image* image); + const Image getImageForIdentifier (const var& imageIdentifier); + const var getIdentifierForImage (const Image& image); //============================================================================== void valueTreePropertyChanged (ValueTree& tree, const Identifier& name); diff --git a/extras/Jucer (experimental)/Source/model/Project/jucer_Project.cpp b/extras/Jucer (experimental)/Source/model/Project/jucer_Project.cpp index 0f8d796316..756879c7a3 100644 --- a/extras/Jucer (experimental)/Source/model/Project/jucer_Project.cpp +++ b/extras/Jucer (experimental)/Source/model/Project/jucer_Project.cpp @@ -661,7 +661,7 @@ bool Project::Item::addFile (const File& file, int insertIndex) return true; } -Image* Project::Item::getIcon() const +const Image Project::Item::getIcon() const { if (isFile()) return LookAndFeel::getDefaultLookAndFeel().getDefaultDocumentFileImage(); diff --git a/extras/Jucer (experimental)/Source/model/Project/jucer_Project.h b/extras/Jucer (experimental)/Source/model/Project/jucer_Project.h index 37b4da5f3d..ca30c391ad 100644 --- a/extras/Jucer (experimental)/Source/model/Project/jucer_Project.h +++ b/extras/Jucer (experimental)/Source/model/Project/jucer_Project.h @@ -192,7 +192,7 @@ public: Item getParent() const; - Image* getIcon() const; + const Image getIcon() const; private: //============================================================================== diff --git a/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditorTreeView.h b/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditorTreeView.h index 3602e97015..7e0599283b 100644 --- a/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditorTreeView.h +++ b/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditorTreeView.h @@ -124,7 +124,7 @@ namespace ComponentEditorTreeView const String getDisplayName() const { return getRenamingName(); } const String getRenamingName() const { return componentState [ComponentDocument::memberNameProperty]; } - Image* getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultDocumentFileImage(); } + const Image getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultDocumentFileImage(); } const String getDragSourceDescription() { return getDragIdFor (editor); } @@ -179,7 +179,7 @@ namespace ComponentEditorTreeView const String getDisplayName() const { return getRenamingName(); } const String getRenamingName() const { return "Components"; } - Image* getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultFolderImage(); } + const Image getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultFolderImage(); } const String getDragSourceDescription() { return String::empty; } bool isInterestedInDragSource (const String& sourceDescription, Component* sourceComponent) @@ -299,7 +299,7 @@ namespace ComponentEditorTreeView const String getDisplayName() const { return getRenamingName(); } const String getRenamingName() const { return markerState [MarkerListBase::getMarkerNameProperty()]; } - Image* getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultDocumentFileImage(); } + const Image getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultDocumentFileImage(); } const String getDragSourceDescription() { return String::empty; } @@ -354,7 +354,7 @@ namespace ComponentEditorTreeView const String getDisplayName() const { return getRenamingName(); } const String getRenamingName() const { return isX ? "Markers (X-axis)" : "Markers (Y-axis)"; } - Image* getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultFolderImage(); } + const Image getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultFolderImage(); } const String getDragSourceDescription() { return String::empty; } private: @@ -388,7 +388,7 @@ namespace ComponentEditorTreeView const String getDisplayName() const { return getRenamingName(); } const String getRenamingName() const { return editor.getDocument().getClassName().toString(); } - Image* getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultFolderImage(); } + const Image getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultFolderImage(); } const String getDragSourceDescription() { return String::empty; } }; } diff --git a/extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorTreeView.h b/extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorTreeView.h index 53b5d1fc3a..8d17a29f16 100644 --- a/extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorTreeView.h +++ b/extras/Jucer (experimental)/Source/ui/Drawable Editor/jucer_DrawableEditorTreeView.h @@ -124,7 +124,7 @@ public: bool isMissing() { return false; } - Image* getIcon() const + const Image getIcon() const { return LookAndFeel::getDefaultLookAndFeel().getDefaultDocumentFileImage(); } diff --git a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp index ce536eeca1..7b6e5c40c9 100644 --- a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp +++ b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp @@ -454,9 +454,15 @@ public: { lasso->dragLasso (e); } - else if (mouseDownCompUID.isNotEmpty() && (! e.mouseWasClicked()) && (! e.mods.isPopupMenu())) + else { - if (! isDraggingClickedComp) + if ((! isDraggingClickedComp) + && mouseDownCompUID.isNotEmpty() + && (! e.mouseWasClicked()) + && (! e.mods.isPopupMenu()) + && e.getDistanceFromDragStart() > 7) // whenever this drag occurs, it's selecting the object + // and beginning a drag, so allow for more wobble than + // when when dragging an already-selected object { isDraggingClickedComp = true; canvas->enableResizingMode(); @@ -464,8 +470,11 @@ public: canvas->beginDrag (e.withNewPosition (e.getMouseDownPosition()), ResizableBorderComponent::Zone (ResizableBorderComponent::Zone::centre)); } - canvas->continueDrag (e); - showSizeGuides(); + if (isDraggingClickedComp) + { + canvas->continueDrag (e); + showSizeGuides(); + } } autoScrollForMouseEvent (e); diff --git a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorPanel.h b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorPanel.h index ef3c5b1e7d..e41d754704 100644 --- a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorPanel.h +++ b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorPanel.h @@ -190,10 +190,9 @@ private: void paint (Graphics& g) { - Image* im = ImageCache::getFromMemory (BinaryData::brushed_aluminium_png, BinaryData::brushed_aluminium_pngSize); - g.setTiledImageFill (*im, 0, 0, 1.0f); + g.setTiledImageFill (ImageCache::getFromMemory (BinaryData::brushed_aluminium_png, BinaryData::brushed_aluminium_pngSize), + 0, 0, 1.0f); g.fillAll(); - ImageCache::release (im); } void paintOverChildren (Graphics& g) diff --git a/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_GroupInformationComponent.cpp b/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_GroupInformationComponent.cpp index cd8ecd049a..fb3675ed67 100644 --- a/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_GroupInformationComponent.cpp +++ b/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_GroupInformationComponent.cpp @@ -97,16 +97,9 @@ public: void paint (Graphics& g) { int x = getHeight() + 6; - Image* icon = item.getIcon(); - - if (icon != 0) - { - g.drawImageWithin (icon, 2, 2, x - 4, getHeight() - 4, - RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, - false); - - ImageCache::release (icon); - } + g.drawImageWithin (item.getIcon(), 2, 2, x - 4, getHeight() - 4, + RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, + false); g.setColour (Colours::black); g.setFont (getHeight() * 0.6f); diff --git a/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ItemPreviewComponent.cpp b/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ItemPreviewComponent.cpp index 11079f9c90..cdab7c0388 100644 --- a/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ItemPreviewComponent.cpp +++ b/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ItemPreviewComponent.cpp @@ -61,8 +61,8 @@ void ItemPreviewComponent::tryToLoadImage (InputStream* in) image = ImageFileFormat::loadFrom (*input); - if (image != 0) - facts.add (String (image->getWidth()) + " x " + String (image->getHeight()) + formatName); + if (image.isValid()) + facts.add (String (image.getWidth()) + " x " + String (image.getHeight()) + formatName); const int64 totalSize = input->getTotalLength(); @@ -73,19 +73,14 @@ void ItemPreviewComponent::tryToLoadImage (InputStream* in) void ItemPreviewComponent::paint (Graphics& g) { - if (image != 0) - { - g.drawImageWithin (image, - 2, 22, getWidth() - 4, getHeight() - 24, - RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, - false); - } + g.drawImageWithin (image, 2, 22, getWidth() - 4, getHeight() - 24, + RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, + false); g.setFont (15.0f, Font::bold); g.setColour (Colours::white); g.drawMultiLineText (facts.joinIntoString ("\n"), 10, 15, getWidth() - 16); - } void ItemPreviewComponent::resized() diff --git a/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ItemPreviewComponent.h b/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ItemPreviewComponent.h index 03231c47dc..54e5eaeed1 100644 --- a/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ItemPreviewComponent.h +++ b/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ItemPreviewComponent.h @@ -48,7 +48,7 @@ public: private: StringArray facts; File file; - ScopedPointer image; + Image image; void tryToLoadImage (InputStream* input); }; diff --git a/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectInformationComponent.cpp b/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectInformationComponent.cpp index c0db24f7a5..46aa39d980 100644 --- a/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectInformationComponent.cpp +++ b/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectInformationComponent.cpp @@ -175,10 +175,9 @@ ProjectInformationComponent::~ProjectInformationComponent() void ProjectInformationComponent::paint (Graphics& g) { //[UserPrePaint] Add your own custom painting code here.. - Image* im = ImageCache::getFromMemory (BinaryData::brushed_aluminium_png, BinaryData::brushed_aluminium_pngSize); - g.setTiledImageFill (*im, 0, 0, 1.0f); + g.setTiledImageFill (ImageCache::getFromMemory (BinaryData::brushed_aluminium_png, BinaryData::brushed_aluminium_pngSize), + 0, 0, 1.0f); g.fillAll(); - ImageCache::release (im); drawRecessedShadows (g, getWidth(), getHeight(), 14); //[/UserPrePaint] diff --git a/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectTreeViewBase.h b/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectTreeViewBase.h index 14bd610492..ce2678331d 100644 --- a/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectTreeViewBase.h +++ b/extras/Jucer (experimental)/Source/ui/Project Editor/jucer_ProjectTreeViewBase.h @@ -104,7 +104,7 @@ protected: //============================================================================== virtual void addSubItems(); virtual ProjectTreeViewBase* createSubItem (const Project::Item& node) = 0; - Image* getIcon() const { return item.getIcon(); } + const Image getIcon() const { return item.getIcon(); } //============================================================================== void triggerAsyncRename (const Project::Item& itemToRename); diff --git a/extras/Jucer (experimental)/Source/ui/jucer_JucerTreeViewBase.cpp b/extras/Jucer (experimental)/Source/ui/jucer_JucerTreeViewBase.cpp index f2d405a102..66c5f2030a 100644 --- a/extras/Jucer (experimental)/Source/ui/jucer_JucerTreeViewBase.cpp +++ b/extras/Jucer (experimental)/Source/ui/jucer_JucerTreeViewBase.cpp @@ -54,16 +54,10 @@ void JucerTreeViewBase::paintItem (Graphics& g, int width, int height) const int x = getTextX(); g.setColour (isMissing() ? Colours::red : Colours::black); - Image* icon = getIcon(); - if (icon != 0) - { - g.drawImageWithin (icon, 2, 2, x - 4, height - 4, - RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, - false); - - ImageCache::release (icon); - } + g.drawImageWithin (getIcon(), 2, 2, x - 4, height - 4, + RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, + false); g.setFont (getFont()); g.drawFittedText (getDisplayName(), x, 0, width - x, height, Justification::centredLeft, 1, 0.8f); diff --git a/extras/Jucer (experimental)/Source/ui/jucer_JucerTreeViewBase.h b/extras/Jucer (experimental)/Source/ui/jucer_JucerTreeViewBase.h index e665d08633..2a70435ed3 100644 --- a/extras/Jucer (experimental)/Source/ui/jucer_JucerTreeViewBase.h +++ b/extras/Jucer (experimental)/Source/ui/jucer_JucerTreeViewBase.h @@ -52,7 +52,7 @@ public: virtual const String getDisplayName() const = 0; virtual void setName (const String& newName) = 0; virtual bool isMissing() = 0; - virtual Image* getIcon() const = 0; + virtual const Image getIcon() const = 0; virtual void showRenameBox(); diff --git a/extras/Jucer (experimental)/Source/utility/jucer_FillTypePropertyComponent.h b/extras/Jucer (experimental)/Source/utility/jucer_FillTypePropertyComponent.h index bb6ce907c2..c47a73c358 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_FillTypePropertyComponent.h +++ b/extras/Jucer (experimental)/Source/utility/jucer_FillTypePropertyComponent.h @@ -130,7 +130,7 @@ public: else if (b == &imageButton) { if (! currentFill.isTiledImage()) - setFillType (FillType (*StoredSettings::getInstance()->getFallbackImage(), + setFillType (FillType (StoredSettings::getInstance()->getFallbackImage(), AffineTransform::identity)); } } diff --git a/extras/Jucer (experimental)/Source/utility/jucer_StoredSettings.cpp b/extras/Jucer (experimental)/Source/utility/jucer_StoredSettings.cpp index db67ac9a62..a1e83cd6eb 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_StoredSettings.cpp +++ b/extras/Jucer (experimental)/Source/utility/jucer_StoredSettings.cpp @@ -135,9 +135,9 @@ const StringArray& StoredSettings::getFontNames() return fontNames; } -Image* StoredSettings::getFallbackImage() +const Image StoredSettings::getFallbackImage() { - if (fallbackImage == 0) + if (fallbackImage.isNull()) fallbackImage = ImageFileFormat::loadFrom (BinaryData::juce_icon_png, BinaryData::juce_icon_pngSize); return fallbackImage; diff --git a/extras/Jucer (experimental)/Source/utility/jucer_StoredSettings.h b/extras/Jucer (experimental)/Source/utility/jucer_StoredSettings.h index 9acf11e7c1..ff8dfb09e8 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_StoredSettings.h +++ b/extras/Jucer (experimental)/Source/utility/jucer_StoredSettings.h @@ -69,7 +69,7 @@ public: }; - Image* getFallbackImage(); + const Image getFallbackImage(); //============================================================================== juce_UseDebuggingNewOperator @@ -78,7 +78,7 @@ private: ScopedPointer props; StringArray fontNames; - ScopedPointer fallbackImage; + Image fallbackImage; }; diff --git a/extras/browser plugins/wrapper/juce_ActiveX_GlueCode.cpp b/extras/browser plugins/wrapper/juce_ActiveX_GlueCode.cpp index ed6e074c78..6a0b8a16d4 100644 --- a/extras/browser plugins/wrapper/juce_ActiveX_GlueCode.cpp +++ b/extras/browser plugins/wrapper/juce_ActiveX_GlueCode.cpp @@ -164,7 +164,7 @@ class IDispatchWrappingDynamicObject : public IDispatch public: IDispatchWrappingDynamicObject (const var& object_) : object (object_), - refCount (0) + refCount (1) { DBG ("num Juce wrapper objs: " + String (++numJuceSO)); } diff --git a/extras/juce demo/Source/demos/CameraDemo.cpp b/extras/juce demo/Source/demos/CameraDemo.cpp index 3d29731330..6cf056968a 100644 --- a/extras/juce demo/Source/demos/CameraDemo.cpp +++ b/extras/juce demo/Source/demos/CameraDemo.cpp @@ -42,7 +42,6 @@ public: cameraDevice = 0; cameraPreviewComp = 0; - lastSnapshot = 0; recordingMovie = false; addAndMakeVisible (cameraSelectorComboBox = new ComboBox (T("Camera"))); @@ -65,16 +64,14 @@ public: { deleteAllChildren(); delete cameraDevice; - delete lastSnapshot; } void paint (Graphics& g) { - if (lastSnapshot != 0) - g.drawImageWithin (lastSnapshot, - getWidth() / 2 + 10, 40, - getWidth() / 2 - 20, getHeight() - 50, - RectanglePlacement::centred, false); + g.drawImageWithin (lastSnapshot, + getWidth() / 2 + 10, 40, + getWidth() / 2 - 20, getHeight() - 50, + RectanglePlacement::centred, false); } void resized() @@ -160,7 +157,7 @@ public: } // This is called by the camera device when a new image arrives - void imageReceived (Image& image) + void imageReceived (const Image& image) { // In this app we just want to take one image, so as soon as this happens, // we'll unregister ourselves as a listener. @@ -170,8 +167,7 @@ public: // This callback won't be on the message thread, so need to lock it before using // data that may already be in use.. const MessageManagerLock mm; - deleteAndZero (lastSnapshot); - lastSnapshot = image.createCopy(); + lastSnapshot = image; repaint(); } @@ -185,7 +181,7 @@ private: Component* cameraPreviewComp; bool recordingMovie; - Image* lastSnapshot; + Image lastSnapshot; }; diff --git a/extras/juce demo/Source/demos/OpenGLDemo.cpp b/extras/juce demo/Source/demos/OpenGLDemo.cpp index 4b1558fbc8..8e03cc5098 100644 --- a/extras/juce demo/Source/demos/OpenGLDemo.cpp +++ b/extras/juce demo/Source/demos/OpenGLDemo.cpp @@ -56,7 +56,7 @@ class DemoOpenGLCanvas : public OpenGLComponent, public Timer { float rotation, delta; - Image* image; + Image image; public: DemoOpenGLCanvas() @@ -69,12 +69,12 @@ public: rotation = 0.0f; delta = 1.0f; - Image* im = ImageFileFormat::loadFrom (BinaryData::juce_png, BinaryData::juce_pngSize); - image = new Image (Image::RGB, 512, 512, true); - Graphics g (*image); + image = Image (Image::RGB, 512, 512, true, Image::SoftwareImage); + Graphics g (image); + g.fillAll (Colours::white); - g.drawImage (im, 0, 0, 512, 512, 0, 0, im->getWidth(), im->getHeight()); - delete im; + g.drawImageWithin (ImageFileFormat::loadFrom (BinaryData::juce_png, BinaryData::juce_pngSize), + 0, 0, 512, 512, RectanglePlacement::stretchToFit); startTimer (20); @@ -107,7 +107,6 @@ public: ~DemoOpenGLCanvas() { - delete image; } // when the component creates a new internal context, this is called, and @@ -133,9 +132,9 @@ public: glPixelStorei (GL_UNPACK_ALIGNMENT, 4); - Image::BitmapData srcData (*image, 0, 0, image->getWidth(), image->getHeight()); + Image::BitmapData srcData (image, 0, 0, image.getWidth(), image.getHeight()); - glTexImage2D (GL_TEXTURE_2D, 0, 4, image->getWidth(), image->getHeight(), + glTexImage2D (GL_TEXTURE_2D, 0, 4, image.getWidth(), image.getHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, srcData.data); diff --git a/extras/juce demo/Source/demos/RenderingTestComponent.cpp b/extras/juce demo/Source/demos/RenderingTestComponent.cpp index 0b6b7492f7..10dd10c861 100644 --- a/extras/juce demo/Source/demos/RenderingTestComponent.cpp +++ b/extras/juce demo/Source/demos/RenderingTestComponent.cpp @@ -68,8 +68,6 @@ public: ~RenderingTestCanvas() { - delete rgbImage; - delete argbImage; delete svgDrawable; } @@ -151,8 +149,7 @@ private: RenderingTestComponent& owner; double averageTime; - Image* rgbImage; - Image* argbImage; + Image rgbImage, argbImage; DrawableComposite* svgDrawable; GlyphArrangement glyphs; ColourGradient linearGradient, radialGradient; @@ -191,12 +188,12 @@ private: void clipToImage (Graphics& g) { - AffineTransform transform (AffineTransform::translation (argbImage->getWidth() / -2.0f, argbImage->getHeight() / -2.0f) + AffineTransform transform (AffineTransform::translation (argbImage.getWidth() / -2.0f, argbImage.getHeight() / -2.0f) .rotated (bouncingNumber[3]) .scaled (bouncingNumber[2] + 4.0f, bouncingNumber[2] + 4.0f) .translated (bouncingPointX[2], bouncingPointY[2])); - g.reduceClipRegion (*argbImage, - Rectangle (0, 0, argbImage->getWidth(), argbImage->getHeight()), + g.reduceClipRegion (argbImage, + Rectangle (0, 0, argbImage.getWidth(), argbImage.getHeight()), transform); } @@ -264,24 +261,24 @@ private: g.strokePath (p, stroke, AffineTransform::identity); } - void drawImages (Graphics& g, Image* image) + void drawImages (Graphics& g, const Image& image) { - AffineTransform transform (AffineTransform::translation ((float) (image->getWidth() / -2), - (float) (image->getHeight() / -2)) + AffineTransform transform (AffineTransform::translation ((float) (image.getWidth() / -2), + (float) (image.getHeight() / -2)) .followedBy (getTransform())); g.setOpacity ((float) owner.opacitySlider->getValue()); - g.drawImageTransformed (image, image->getBounds(), + g.drawImageTransformed (image, image.getBounds(), transform, false); } - void drawTiling (Graphics& g, Image* image) + void drawTiling (Graphics& g, const Image& image) { - AffineTransform transform (AffineTransform::translation ((float) (image->getWidth() / -2), - (float) (image->getHeight() / -2)) + AffineTransform transform (AffineTransform::translation ((float) (image.getWidth() / -2), + (float) (image.getHeight() / -2)) .followedBy (getTransform())); - FillType fill (*image, transform); + FillType fill (image, transform); fill.setOpacity ((float) owner.opacitySlider->getValue()); g.setFillType (fill); g.fillAll(); diff --git a/extras/juce demo/Source/demos/WidgetsDemo.cpp b/extras/juce demo/Source/demos/WidgetsDemo.cpp index aa5a7653e4..80f6252de2 100644 --- a/extras/juce demo/Source/demos/WidgetsDemo.cpp +++ b/extras/juce demo/Source/demos/WidgetsDemo.cpp @@ -512,7 +512,7 @@ public: over.setStrokeThickness (5.0f); DrawableImage down; - down.setImage (ImageCache::getFromMemory (BinaryData::juce_png, BinaryData::juce_pngSize), true); + down.setImage (ImageCache::getFromMemory (BinaryData::juce_png, BinaryData::juce_pngSize)); down.setOverlayColour (Colours::black.withAlpha (0.3f)); //============================================================================== @@ -567,10 +567,7 @@ public: ImageButton* imageButton = new ImageButton ("imagebutton"); addAndMakeVisible (imageButton); - Image* juceImage = ImageCache::getFromMemory (BinaryData::juce_png, BinaryData::juce_pngSize); - ImageCache::incReferenceCount (juceImage); - ImageCache::incReferenceCount (juceImage); - + Image juceImage = ImageCache::getFromMemory (BinaryData::juce_png, BinaryData::juce_pngSize); imageButton->setImages (true, true, true, juceImage, 0.7f, Colours::transparentBlack, juceImage, 1.0f, Colours::transparentBlack, diff --git a/extras/the jucer/src/model/components/jucer_ImageButtonHandler.h b/extras/the jucer/src/model/components/jucer_ImageButtonHandler.h index 17fffb2f3d..3ed7ba0fc3 100644 --- a/extras/the jucer/src/model/components/jucer_ImageButtonHandler.h +++ b/extras/the jucer/src/model/components/jucer_ImageButtonHandler.h @@ -166,7 +166,7 @@ public: const String resName (getImageResource (ib, role)); if (resName.isEmpty()) - return "0"; + return "Image()"; return "ImageCache::getFromMemory (" + resName + ", " + resName + "Size)"; } @@ -522,9 +522,9 @@ public: //============================================================================== static void updateButtonImages (JucerDocument& document, ImageButton* const ib) { - Image* norm = document.getResources().getImageFromCache (getImageResource (ib, normalImage)); - Image* over = document.getResources().getImageFromCache (getImageResource (ib, overImage)); - Image* down = document.getResources().getImageFromCache (getImageResource (ib, downImage)); + Image norm = document.getResources().getImageFromCache (getImageResource (ib, normalImage)); + Image over = document.getResources().getImageFromCache (getImageResource (ib, overImage)); + Image down = document.getResources().getImageFromCache (getImageResource (ib, downImage)); ib->setImages (false, true, doesImageKeepProportions (ib), norm, diff --git a/extras/the jucer/src/model/jucer_BinaryResources.cpp b/extras/the jucer/src/model/jucer_BinaryResources.cpp index 8666d4ff9e..30413fe056 100644 --- a/extras/the jucer/src/model/jucer_BinaryResources.cpp +++ b/extras/the jucer/src/model/jucer_BinaryResources.cpp @@ -199,14 +199,14 @@ const Drawable* BinaryResources::getDrawable (const String& name) const return res->drawable; } -Image* BinaryResources::getImageFromCache (const String& name) const +const Image BinaryResources::getImageFromCache (const String& name) const { const BinaryResources::BinaryResource* const res = getResource (name); if (res != 0 && res->data.getSize() > 0) return ImageCache::getFromMemory (res->data.getData(), (int) res->data.getSize()); - return 0; + return Image(); } void BinaryResources::loadFromCpp (const File& cppFileLocation, const String& cppFile) diff --git a/extras/the jucer/src/model/jucer_BinaryResources.h b/extras/the jucer/src/model/jucer_BinaryResources.h index efa1e8b6d6..69bc4602d6 100644 --- a/extras/the jucer/src/model/jucer_BinaryResources.h +++ b/extras/the jucer/src/model/jucer_BinaryResources.h @@ -76,7 +76,7 @@ public: const StringArray getResourceNames() const; const Drawable* getDrawable (const String& name) const; - Image* getImageFromCache (const String& name) const; + const Image getImageFromCache (const String& name) const; template void sort (ElementComparator& sorter) diff --git a/extras/the jucer/src/model/jucer_GeneratedCode.cpp b/extras/the jucer/src/model/jucer_GeneratedCode.cpp index b54db33bd9..e040748edd 100644 --- a/extras/the jucer/src/model/jucer_GeneratedCode.cpp +++ b/extras/the jucer/src/model/jucer_GeneratedCode.cpp @@ -98,16 +98,13 @@ void GeneratedCode::addImageResourceLoader (const String& imageMemberName, const initialisers.add (initialiser); privateMemberDeclarations - << "Image* " << imageMemberName << ";\n"; + << "Image " << imageMemberName << ";\n"; if (resourceName.isNotEmpty()) { constructorCode << imageMemberName << " = ImageCache::getFromMemory (" << resourceName << ", " << resourceName << "Size);\n"; - - destructorCode - << "ImageCache::release (" << imageMemberName << ");\n"; } } } diff --git a/extras/the jucer/src/model/paintelements/jucer_FillType.cpp b/extras/the jucer/src/model/paintelements/jucer_FillType.cpp index a73fe9d2e7..2314c71aeb 100644 --- a/extras/the jucer/src/model/paintelements/jucer_FillType.cpp +++ b/extras/the jucer/src/model/paintelements/jucer_FillType.cpp @@ -36,7 +36,7 @@ JucerFillType::JucerFillType() JucerFillType::JucerFillType (const JucerFillType& other) { - image = 0; + image = Image(); mode = other.mode; colour = other.colour; gradCol1 = other.gradCol1; @@ -50,9 +50,7 @@ JucerFillType::JucerFillType (const JucerFillType& other) JucerFillType& JucerFillType::operator= (const JucerFillType& other) { - ImageCache::release (image); - image = 0; - + image = Image(); mode = other.mode; colour = other.colour; gradCol1 = other.gradCol1; @@ -68,7 +66,6 @@ JucerFillType& JucerFillType::operator= (const JucerFillType& other) JucerFillType::~JucerFillType() { - ImageCache::release (image); } bool JucerFillType::operator== (const JucerFillType& other) const throw() @@ -91,9 +88,7 @@ bool JucerFillType::operator!= (const JucerFillType& other) const throw() void JucerFillType::reset() { - ImageCache::release (image); - image = 0; - + image = Image(); mode = solidColour; colour = Colours::brown.withHue (Random::getSystemRandom().nextFloat()); gradCol1 = Colours::red; @@ -114,9 +109,7 @@ void JucerFillType::setFillType (Graphics& g, JucerDocument* const document, con { if (mode == solidColour) { - ImageCache::release (image); - image = 0; - + image = Image(); g.setColour (colour); } else if (mode == imageBrush) @@ -125,12 +118,11 @@ void JucerFillType::setFillType (Graphics& g, JucerDocument* const document, con Rectangle r (imageAnchor.getRectangle (parentArea, document->getComponentLayout())); - g.setTiledImageFill (*image, r.getX(), r.getY(), (float) imageOpacity); + g.setTiledImageFill (image, r.getX(), r.getY(), (float) imageOpacity); } else { - ImageCache::release (image); - image = 0; + image = Image(); Rectangle r1 (gradPos1.getRectangle (parentArea, document->getComponentLayout())); Rectangle r2 (gradPos2.getRectangle (parentArea, document->getComponentLayout())); @@ -285,9 +277,9 @@ bool JucerFillType::isOpaque() const return gradCol1.isOpaque() && gradCol1.isOpaque(); case imageBrush: - return image != 0 + return image.isValid() && imageOpacity >= 1.0f - && ! image->hasAlphaChannel(); + && ! image.hasAlphaChannel(); default: jassertfalse @@ -321,28 +313,28 @@ bool JucerFillType::isInvisible() const void JucerFillType::loadImage (JucerDocument* const document) { - if (image == 0) + if (image.isNull()) { if (document != 0) image = document->getResources().getImageFromCache (imageResourceName); - if (image == 0) + if (image.isNull()) { const int hashCode = 0x3437856f; image = ImageCache::getFromHashCode (hashCode); - if (image == 0) + if (image.isNull()) { - image = new Image (Image::RGB, 100, 100, true); + image = Image (Image::RGB, 100, 100, true); - Graphics g (*image); - g.fillCheckerBoard (0, 0, image->getWidth(), image->getHeight(), - image->getWidth() / 2, image->getHeight() / 2, + Graphics g (image); + g.fillCheckerBoard (0, 0, image.getWidth(), image.getHeight(), + image.getWidth() / 2, image.getHeight() / 2, Colours::white, Colours::lightgrey); g.setFont (12.0f); g.setColour (Colours::grey); - g.drawText (T("(image missing)"), 0, 0, image->getWidth(), image->getHeight() / 2, Justification::centred, true); + g.drawText (T("(image missing)"), 0, 0, image.getWidth(), image.getHeight() / 2, Justification::centred, true); ImageCache::addImageToCache (image, hashCode); } diff --git a/extras/the jucer/src/model/paintelements/jucer_FillType.h b/extras/the jucer/src/model/paintelements/jucer_FillType.h index b63723e006..0f6a071c51 100644 --- a/extras/the jucer/src/model/paintelements/jucer_FillType.h +++ b/extras/the jucer/src/model/paintelements/jucer_FillType.h @@ -78,7 +78,7 @@ public: //============================================================================== private: - Image* image; + Image image; void reset(); void loadImage (JucerDocument* const document); diff --git a/extras/the jucer/src/ui/jucer_ComponentLayoutEditor.cpp b/extras/the jucer/src/ui/jucer_ComponentLayoutEditor.cpp index 25c9102cfd..824077d80f 100644 --- a/extras/the jucer/src/ui/jucer_ComponentLayoutEditor.cpp +++ b/extras/the jucer/src/ui/jucer_ComponentLayoutEditor.cpp @@ -184,10 +184,10 @@ const Rectangle ComponentLayoutEditor::getComponentArea() const } } -Image* ComponentLayoutEditor::createComponentLayerSnapshot() const +const Image ComponentLayoutEditor::createComponentLayerSnapshot() const { ((SubComponentHolderComp*) subCompHolder)->dontFillBackground = true; - Image* const im = subCompHolder->createComponentSnapshot (Rectangle (0, 0, subCompHolder->getWidth(), subCompHolder->getHeight())); + Image im = subCompHolder->createComponentSnapshot (Rectangle (0, 0, subCompHolder->getWidth(), subCompHolder->getHeight())); ((SubComponentHolderComp*) subCompHolder)->dontFillBackground = false; return im; diff --git a/extras/the jucer/src/ui/jucer_ComponentLayoutEditor.h b/extras/the jucer/src/ui/jucer_ComponentLayoutEditor.h index 37b47ff239..4950baa3d3 100644 --- a/extras/the jucer/src/ui/jucer_ComponentLayoutEditor.h +++ b/extras/the jucer/src/ui/jucer_ComponentLayoutEditor.h @@ -72,7 +72,7 @@ public: const Rectangle getComponentArea() const; - Image* createComponentLayerSnapshot() const; + const Image createComponentLayerSnapshot() const; //============================================================================== juce_UseDebuggingNewOperator diff --git a/extras/the jucer/src/ui/jucer_ComponentLayoutPanel.cpp b/extras/the jucer/src/ui/jucer_ComponentLayoutPanel.cpp index 2580ac8b72..0858d46340 100644 --- a/extras/the jucer/src/ui/jucer_ComponentLayoutPanel.cpp +++ b/extras/the jucer/src/ui/jucer_ComponentLayoutPanel.cpp @@ -120,7 +120,7 @@ const Rectangle ComponentLayoutPanel::getComponentArea() const return ((ComponentLayoutEditor*) editor)->getComponentArea(); } -Image* ComponentLayoutPanel::createComponentSnapshot() const +const Image ComponentLayoutPanel::createComponentSnapshot() const { return ((ComponentLayoutEditor*) editor)->createComponentLayerSnapshot(); } diff --git a/extras/the jucer/src/ui/jucer_ComponentLayoutPanel.h b/extras/the jucer/src/ui/jucer_ComponentLayoutPanel.h index 4606053d85..f7027424c6 100644 --- a/extras/the jucer/src/ui/jucer_ComponentLayoutPanel.h +++ b/extras/the jucer/src/ui/jucer_ComponentLayoutPanel.h @@ -45,7 +45,7 @@ public: void updatePropertiesList(); const Rectangle getComponentArea() const; - Image* createComponentSnapshot() const; + const Image createComponentSnapshot() const; //============================================================================== juce_UseDebuggingNewOperator diff --git a/extras/the jucer/src/ui/jucer_JucerDocumentHolder.cpp b/extras/the jucer/src/ui/jucer_JucerDocumentHolder.cpp index 877bec114b..0bcb134ffc 100644 --- a/extras/the jucer/src/ui/jucer_JucerDocumentHolder.cpp +++ b/extras/the jucer/src/ui/jucer_JucerDocumentHolder.cpp @@ -1300,10 +1300,10 @@ JucerDocumentHolder* JucerDocumentHolder::getActiveDocumentHolder() return dynamic_cast (target); } -Image* JucerDocumentHolder::createComponentLayerSnapshot() const +const Image JucerDocumentHolder::createComponentLayerSnapshot() const { if (compLayoutPanel != 0) return compLayoutPanel->createComponentSnapshot(); - return 0; + return Image(); } diff --git a/extras/the jucer/src/ui/jucer_JucerDocumentHolder.h b/extras/the jucer/src/ui/jucer_JucerDocumentHolder.h index ae605cb8e2..af67e7e13c 100644 --- a/extras/the jucer/src/ui/jucer_JucerDocumentHolder.h +++ b/extras/the jucer/src/ui/jucer_JucerDocumentHolder.h @@ -57,7 +57,7 @@ public: void setViewportToLastPos (Viewport* vp); void storeLastViewportPos (Viewport* vp); - Image* createComponentLayerSnapshot() const; + const Image createComponentLayerSnapshot() const; //============================================================================== void paint (Graphics& g); diff --git a/extras/the jucer/src/ui/jucer_PaintRoutineEditor.cpp b/extras/the jucer/src/ui/jucer_PaintRoutineEditor.cpp index c1e189051b..3f7411d107 100644 --- a/extras/the jucer/src/ui/jucer_PaintRoutineEditor.cpp +++ b/extras/the jucer/src/ui/jucer_PaintRoutineEditor.cpp @@ -53,8 +53,6 @@ PaintRoutineEditor::~PaintRoutineEditor() removeChildComponent (&lassoComp); deleteAllChildren(); - - delete componentOverlay; } void PaintRoutineEditor::removeAllElementComps() @@ -99,10 +97,10 @@ void PaintRoutineEditor::paint (Graphics& g) void PaintRoutineEditor::paintOverChildren (Graphics& g) { - if (componentOverlay == 0 && document.getComponentOverlayOpacity() > 0.0f) + if (componentOverlay.isNull() && document.getComponentOverlayOpacity() > 0.0f) updateComponentOverlay(); - if (componentOverlay != 0) + if (componentOverlay.isValid()) { const Rectangle clip (getComponentArea()); g.drawImageAt (componentOverlay, clip.getX(), clip.getY()); @@ -113,7 +111,7 @@ void PaintRoutineEditor::resized() { if (getWidth() > 0 && getHeight() > 0) { - deleteAndZero (componentOverlay); + componentOverlay = Image(); refreshAllElements(); } } @@ -133,11 +131,10 @@ void PaintRoutineEditor::updateChildBounds() void PaintRoutineEditor::updateComponentOverlay() { - if (componentOverlay != 0) + if (componentOverlay.isValid()) repaint(); - deleteAndZero (componentOverlay); - + componentOverlay = Image(); componentOverlayOpacity = document.getComponentOverlayOpacity(); if (componentOverlayOpacity > 0.0f) @@ -145,9 +142,9 @@ void PaintRoutineEditor::updateComponentOverlay() if (documentHolder != 0) componentOverlay = documentHolder->createComponentLayerSnapshot(); - if (componentOverlay != 0) + if (componentOverlay.isValid()) { - componentOverlay->multiplyAllAlphas (componentOverlayOpacity); + componentOverlay.multiplyAllAlphas (componentOverlayOpacity); repaint(); } } @@ -165,7 +162,7 @@ void PaintRoutineEditor::visibilityChanged() else { document.removeChangeListener (this); - deleteAndZero (componentOverlay); + componentOverlay = Image(); } } @@ -210,7 +207,7 @@ void PaintRoutineEditor::refreshAllElements() if (componentOverlayOpacity != document.getComponentOverlayOpacity()) { - deleteAndZero (componentOverlay); + componentOverlay = Image(); componentOverlayOpacity = document.getComponentOverlayOpacity(); repaint(); } diff --git a/extras/the jucer/src/ui/jucer_PaintRoutineEditor.h b/extras/the jucer/src/ui/jucer_PaintRoutineEditor.h index 3f7a968efa..cee752d3cd 100644 --- a/extras/the jucer/src/ui/jucer_PaintRoutineEditor.h +++ b/extras/the jucer/src/ui/jucer_PaintRoutineEditor.h @@ -79,7 +79,7 @@ private: JucerDocumentHolder* const documentHolder; LassoComponent lassoComp; SnapGridPainter grid; - Image* componentOverlay; + Image componentOverlay; float componentOverlayOpacity; Colour currentBackgroundColour; diff --git a/extras/the jucer/src/ui/jucer_PrefsPanel.cpp b/extras/the jucer/src/ui/jucer_PrefsPanel.cpp index a0e38d9df1..0490955d4b 100644 --- a/extras/the jucer/src/ui/jucer_PrefsPanel.cpp +++ b/extras/the jucer/src/ui/jucer_PrefsPanel.cpp @@ -64,7 +64,7 @@ public: class AboutPage : public Component { HyperlinkButton* link; - Image* logo; + Image logo; TextLayout text1, text2; public: @@ -89,7 +89,6 @@ public: ~AboutPage() { deleteAllChildren(); - ImageCache::release (logo); } void paint (Graphics& g) diff --git a/extras/the jucer/src/ui/jucer_SnapGridPainter.cpp b/extras/the jucer/src/ui/jucer_SnapGridPainter.cpp index 58547bcc5b..8bfb226dbd 100644 --- a/extras/the jucer/src/ui/jucer_SnapGridPainter.cpp +++ b/extras/the jucer/src/ui/jucer_SnapGridPainter.cpp @@ -37,7 +37,6 @@ SnapGridPainter::SnapGridPainter() SnapGridPainter::~SnapGridPainter() { - delete backgroundFill; } bool SnapGridPainter::updateFromDesign (JucerDocument& design) @@ -48,7 +47,7 @@ bool SnapGridPainter::updateFromDesign (JucerDocument& design) snapGridSize = design.getSnappingGridSize(); snapShown = design.isSnapShown() && design.isSnapActive (false); - deleteAndZero (backgroundFill); + backgroundFill = Image(); return true; } @@ -57,16 +56,16 @@ bool SnapGridPainter::updateFromDesign (JucerDocument& design) void SnapGridPainter::updateColour() { - deleteAndZero (backgroundFill); + backgroundFill = Image(); } void SnapGridPainter::draw (Graphics& g, PaintRoutine* backgroundGraphics) { - if (backgroundFill == 0 && snapShown) + if (backgroundFill.isNull() && snapShown) { - backgroundFill = new Image (Image::ARGB, snapGridSize, snapGridSize, true); + backgroundFill = Image (Image::ARGB, snapGridSize, snapGridSize, true); - Graphics g (*backgroundFill); + Graphics g (backgroundFill); Colour col (Colours::black); @@ -83,9 +82,9 @@ void SnapGridPainter::draw (Graphics& g, PaintRoutine* backgroundGraphics) g.setPixel (0, 0); } - if (backgroundFill != 0) + if (backgroundFill.isValid()) { - g.setTiledImageFill (*backgroundFill, 0, 0, 1.0f); + g.setTiledImageFill (backgroundFill, 0, 0, 1.0f); g.fillAll(); } } diff --git a/extras/the jucer/src/ui/jucer_SnapGridPainter.h b/extras/the jucer/src/ui/jucer_SnapGridPainter.h index a79476064b..c2a655675f 100644 --- a/extras/the jucer/src/ui/jucer_SnapGridPainter.h +++ b/extras/the jucer/src/ui/jucer_SnapGridPainter.h @@ -52,7 +52,7 @@ public: private: int snapGridSize; bool snapShown; - Image* backgroundFill; + Image backgroundFill; }; diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 480693849d..3ab325567a 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -3882,18 +3882,7 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_Identifier.cpp ***/ BEGIN_JUCE_NAMESPACE -class Identifier::Pool : public DeletedAtShutdown -{ -public: - Pool() {} - ~Pool() { clearSingletonInstance(); } - - StringPool pool; - - juce_DeclareSingleton_SingleThreaded_Minimal (Pool); -}; - -juce_ImplementSingleton_SingleThreaded (Identifier::Pool); +StringPool Identifier::pool; Identifier::Identifier() throw() : name (0) @@ -3912,7 +3901,7 @@ Identifier& Identifier::operator= (const Identifier& other) throw() } Identifier::Identifier (const String& name_) - : name (Identifier::Pool::getInstance()->pool.getPooledString (name_)) + : name (Identifier::pool.getPooledString (name_)) { /* An Identifier string must be suitable for use as a script variable or XML attribute, so it can only contain this limited set of characters.. */ @@ -3920,7 +3909,7 @@ Identifier::Identifier (const String& name_) } Identifier::Identifier (const char* const name_) - : name (Identifier::Pool::getInstance()->pool.getPooledString (name_)) + : name (Identifier::pool.getPooledString (name_)) { /* An Identifier string must be suitable for use as a script variable or XML attribute, so it can only contain this limited set of characters.. */ @@ -5238,6 +5227,16 @@ RSAKey::~RSAKey() { } +bool RSAKey::operator== (const RSAKey& other) const throw() +{ + return part1 == other.part1 && part2 == other.part2; +} + +bool RSAKey::operator!= (const RSAKey& other) const throw() +{ + return ! operator== (other); +} + const String RSAKey::toString() const { return part1.toString (16) + "," + part2.toString (16); @@ -6205,7 +6204,7 @@ const String File::getPathUpToLastSlash() const const File File::getParentDirectory() const { - return File (getPathUpToLastSlash()); + return File (getPathUpToLastSlash(), (int) 0); } const String File::getFileName() const @@ -15972,6 +15971,73 @@ void TimeSliceThread::run() END_JUCE_NAMESPACE /*** End of inlined file: juce_TimeSliceThread.cpp ***/ + +/*** Start of inlined file: juce_DeletedAtShutdown.cpp ***/ +BEGIN_JUCE_NAMESPACE + +DeletedAtShutdown::DeletedAtShutdown() +{ + const ScopedLock sl (getLock()); + getObjects().add (this); +} + +DeletedAtShutdown::~DeletedAtShutdown() +{ + const ScopedLock sl (getLock()); + getObjects().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. + Array localCopy; + + { + const ScopedLock sl (getLock()); + localCopy = getObjects(); + } + + for (int i = localCopy.size(); --i >= 0;) + { + JUCE_TRY + { + DeletedAtShutdown* deletee = localCopy.getUnchecked(i); + + // double-check that it's not already been deleted during another object's destructor. + { + const ScopedLock sl (getLock()); + if (! getObjects().contains (deletee)) + deletee = 0; + } + + delete deletee; + } + JUCE_CATCH_EXCEPTION + } + + // if no objects got re-created during shutdown, this should have been emptied by their + // destructors + jassert (getObjects().size() == 0); + + getObjects().clear(); // just to make sure the array doesn't have any memory still allocated +} + +CriticalSection& DeletedAtShutdown::getLock() +{ + static CriticalSection lock; + return lock; +} + +Array & DeletedAtShutdown::getObjects() +{ + static Array objects; + return objects; +} + +END_JUCE_NAMESPACE +/*** End of inlined file: juce_DeletedAtShutdown.cpp ***/ + #endif #if JUCE_BUILD_MISC @@ -17995,73 +18061,6 @@ END_JUCE_NAMESPACE /*** End of inlined file: juce_ApplicationProperties.cpp ***/ -/*** Start of inlined file: juce_DeletedAtShutdown.cpp ***/ -BEGIN_JUCE_NAMESPACE - -DeletedAtShutdown::DeletedAtShutdown() -{ - const ScopedLock sl (getLock()); - getObjects().add (this); -} - -DeletedAtShutdown::~DeletedAtShutdown() -{ - const ScopedLock sl (getLock()); - getObjects().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. - Array localCopy; - - { - const ScopedLock sl (getLock()); - localCopy = getObjects(); - } - - for (int i = localCopy.size(); --i >= 0;) - { - JUCE_TRY - { - DeletedAtShutdown* deletee = localCopy.getUnchecked(i); - - // double-check that it's not already been deleted during another object's destructor. - { - const ScopedLock sl (getLock()); - if (! getObjects().contains (deletee)) - deletee = 0; - } - - delete deletee; - } - JUCE_CATCH_EXCEPTION - } - - // if no objects got re-created during shutdown, this should have been emptied by their - // destructors - jassert (getObjects().size() == 0); - - getObjects().clear(); // just to make sure the array doesn't have any memory still allocated -} - -CriticalSection& DeletedAtShutdown::getLock() -{ - static CriticalSection lock; - return lock; -} - -Array & DeletedAtShutdown::getObjects() -{ - static Array objects; - return objects; -} - -END_JUCE_NAMESPACE -/*** End of inlined file: juce_DeletedAtShutdown.cpp ***/ - - /*** Start of inlined file: juce_PropertiesFile.cpp ***/ BEGIN_JUCE_NAMESPACE @@ -38559,7 +38558,6 @@ Component::~Component() for (int i = childComponentList_.size(); --i >= 0;) childComponentList_.getUnchecked(i)->parentComponent_ = 0; - delete bufferedImage_; delete mouseListeners_; delete keyListeners_; } @@ -38704,7 +38702,6 @@ public: ~FadeOutProxyComponent() { - delete image; } void paint (Graphics& g) @@ -38713,7 +38710,7 @@ public: g.drawImage (image, 0, 0, getWidth(), getHeight(), - 0, 0, image->getWidth(), image->getHeight()); + 0, 0, image.getWidth(), image.getHeight()); } void timerCallback() @@ -38736,8 +38733,8 @@ public: centreY += yChangePerMs * msPassed; scale += scaleChangePerMs * msPassed; - const int w = roundToInt (image->getWidth() * scale); - const int h = roundToInt (image->getHeight() * scale); + const int w = roundToInt (image.getWidth() * scale); + const int h = roundToInt (image.getHeight() * scale); setBounds (roundToInt (centreX) - w / 2, roundToInt (centreY) - h / 2, @@ -38755,7 +38752,7 @@ public: juce_UseDebuggingNewOperator private: - Image* image; + Image image; uint32 lastTime; float alpha, alphaChangePerMs; float centreX, xChangePerMs; @@ -38952,7 +38949,7 @@ void Component::setBufferedToImage (const bool shouldBeBuffered) { if (shouldBeBuffered != flags.bufferToImageFlag) { - deleteAndZero (bufferedImage_); + bufferedImage_ = Image(); flags.bufferToImageFlag = shouldBeBuffered; } } @@ -39977,7 +39974,7 @@ void Component::repaint() void Component::repaint (const int x, const int y, const int w, const int h) { - deleteAndZero (bufferedImage_); + bufferedImage_ = Image(); if (flags.visibleFlag) internalRepaint (x, y, w, h); @@ -40046,12 +40043,12 @@ void Component::renderComponent (Graphics& g) { if (flags.bufferToImageFlag) { - if (bufferedImage_ == 0) + if (bufferedImage_.isNull()) { - bufferedImage_ = Image::createNativeImage (flags.opaqueFlag ? Image::RGB : Image::ARGB, - getWidth(), getHeight(), ! flags.opaqueFlag); + bufferedImage_ = Image (flags.opaqueFlag ? Image::RGB : Image::ARGB, + getWidth(), getHeight(), ! flags.opaqueFlag, Image::NativeImage); - Graphics imG (*bufferedImage_); + Graphics imG (bufferedImage_); paint (imG); } @@ -40111,15 +40108,15 @@ void Component::paintEntireComponent (Graphics& g) if (effect_ != 0) { - ScopedPointer effectImage (Image::createNativeImage (flags.opaqueFlag ? Image::RGB : Image::ARGB, - getWidth(), getHeight(), - ! flags.opaqueFlag)); + Image effectImage (flags.opaqueFlag ? Image::RGB : Image::ARGB, + getWidth(), getHeight(), + ! flags.opaqueFlag, Image::NativeImage); { - Graphics g2 (*effectImage); + Graphics g2 (effectImage); renderComponent (g2); } - effect_->applyEffect (*effectImage, g); + effect_->applyEffect (effectImage, g); } else { @@ -40131,24 +40128,24 @@ void Component::paintEntireComponent (Graphics& g) #endif } -Image* Component::createComponentSnapshot (const Rectangle& areaToGrab, - const bool clipImageToComponentBounds) +const Image Component::createComponentSnapshot (const Rectangle& areaToGrab, + const bool clipImageToComponentBounds) { Rectangle r (areaToGrab); if (clipImageToComponentBounds) r = r.getIntersection (getLocalBounds()); - ScopedPointer componentImage (Image::createNativeImage (flags.opaqueFlag ? Image::RGB : Image::ARGB, - jmax (1, r.getWidth()), - jmax (1, r.getHeight()), - true)); + Image componentImage (flags.opaqueFlag ? Image::RGB : Image::ARGB, + jmax (1, r.getWidth()), + jmax (1, r.getHeight()), + true); - Graphics imageContext (*componentImage); + Graphics imageContext (componentImage); imageContext.setOrigin (-r.getX(), -r.getY()); paintEntireComponent (imageContext); - return componentImage.release(); + return componentImage; } void Component::setComponentEffect (ImageEffectFilter* const effect) @@ -43027,40 +43024,30 @@ ImageButton::ImageButton (const String& text_) ImageButton::~ImageButton() { - deleteImages(); -} - -void ImageButton::deleteImages() -{ - 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 Image& normalImage_, const float imageOpacityWhenNormal, const Colour& overlayColourWhenNormal, - Image* const overImage_, + const Image& overImage_, const float imageOpacityWhenOver, const Colour& overlayColourWhenOver, - Image* const downImage_, + const Image& downImage_, const float imageOpacityWhenDown, const Colour& overlayColourWhenDown, const float hitTestAlphaThreshold) { - deleteImages(); - normalImage = normalImage_; overImage = overImage_; downImage = downImage_; - if (resizeButtonNowToFitThisImage && normalImage != 0) + if (resizeButtonNowToFitThisImage && normalImage.isValid()) { - imageW = normalImage->getWidth(); - imageH = normalImage->getHeight(); + imageW = normalImage.getWidth(); + imageH = normalImage.getHeight(); setSize (imageW, imageH); } @@ -43080,7 +43067,7 @@ void ImageButton::setImages (const bool resizeButtonNowToFitThisImage, repaint(); } -Image* ImageButton::getCurrentImage() const +const Image ImageButton::getCurrentImage() const { if (isDown() || getToggleState()) return getDownImage(); @@ -43091,21 +43078,21 @@ Image* ImageButton::getCurrentImage() const return getNormalImage(); } -Image* ImageButton::getNormalImage() const throw() +const Image ImageButton::getNormalImage() const { return normalImage; } -Image* ImageButton::getOverImage() const throw() +const Image ImageButton::getOverImage() const { - return (overImage != 0) ? overImage - : normalImage; + return overImage.isValid() ? overImage + : normalImage; } -Image* ImageButton::getDownImage() const throw() +const Image ImageButton::getDownImage() const { - return (downImage != 0) ? downImage - : getOverImage(); + return downImage.isValid() ? downImage + : getOverImage(); } void ImageButton::paintButton (Graphics& g, @@ -43118,12 +43105,12 @@ void ImageButton::paintButton (Graphics& g, isButtonDown = false; } - Image* const im = getCurrentImage(); + Image im (getCurrentImage()); - if (im != 0) + if (im.isValid()) { - const int iw = im->getWidth(); - const int ih = im->getHeight(); + const int iw = im.getWidth(); + const int ih = im.getHeight(); imageW = getWidth(); imageH = getHeight(); imageX = (imageW - iw) >> 1; @@ -43166,7 +43153,7 @@ void ImageButton::paintButton (Graphics& g, imageH = ih; } - getLookAndFeel().drawImageButton (g, im, imageX, imageY, imageW, imageH, + getLookAndFeel().drawImageButton (g, &im, imageX, imageY, imageW, imageH, isButtonDown ? downOverlay : (isMouseOverButton ? overOverlay : normalOverlay), @@ -43182,12 +43169,11 @@ bool ImageButton::hitTest (int x, int y) if (alphaThreshold == 0) return true; - Image* const im = getCurrentImage(); + Image 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.isNull() || (imageW > 0 && imageH > 0 + && alphaThreshold < im.getPixelAt (((x - imageX) * im.getWidth()) / imageW, + ((y - imageY) * im.getHeight()) / imageH).getAlpha()); } END_JUCE_NAMESPACE @@ -43423,11 +43409,14 @@ void ToolbarButton::paintButtonArea (Graphics& g, 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); + { + Graphics g2 (im); + d->drawWithin (g2, 0, 0, width, height, RectanglePlacement::centred, 1.0f); + } + + im.desaturate(); + g.drawImageAt (im, 0, 0); } else { @@ -48035,7 +48024,7 @@ void ListBox::repaintRow (const int rowNumber) throw() repaint (getRowPosition (rowNumber, true)); } -Image* ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY) +const Image ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY) { Rectangle imageArea; const int firstRow = getRowContainingPosition (0, 0); @@ -48056,7 +48045,7 @@ Image* ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY) imageArea = imageArea.getIntersection (getLocalBounds()); imageX = imageArea.getX(); imageY = imageArea.getY(); - Image* snapshot = Image::createNativeImage (Image::ARGB, imageArea.getWidth(), imageArea.getHeight(), true); + Image snapshot (Image::ARGB, imageArea.getWidth(), imageArea.getHeight(), true, Image::NativeImage); for (i = getNumRowsOnScreen() + 2; --i >= 0;) { @@ -48066,7 +48055,7 @@ Image* ListBox::createSnapshotOfSelectedRows (int& imageX, int& imageY) { const Point pos (rowComp->relativePositionToOtherComponent (this, Point())); - Graphics g (*snapshot); + Graphics g (snapshot); g.setOrigin (pos.getX() - imageX, pos.getY() - imageY); if (g.reduceClipRegion (0, 0, rowComp->getWidth(), rowComp->getHeight())) rowComp->paintEntireComponent (g); @@ -48084,8 +48073,8 @@ void ListBox::startDragAndDrop (const MouseEvent& e, const String& dragDescripti if (dragContainer != 0) { int x, y; - Image* dragImage = createSnapshotOfSelectedRows (x, y); - dragImage->multiplyAllAlphas (0.6f); + Image dragImage (createSnapshotOfSelectedRows (x, y)); + dragImage.multiplyAllAlphas (0.6f); MouseEvent e2 (e.getEventRelativeTo (this)); const Point p (x - e2.x, y - e2.y); @@ -49637,10 +49626,11 @@ BEGIN_JUCE_NAMESPACE class DragOverlayComp : public Component { public: - DragOverlayComp (Image* const image_) + DragOverlayComp (const Image& image_) : image (image_) { - image->multiplyAllAlphas (0.8f); + image.duplicateIfShared(); + image.multiplyAllAlphas (0.8f); setAlwaysOnTop (true); } @@ -49654,7 +49644,7 @@ public: } private: - ScopedPointer image; + Image image; DragOverlayComp (const DragOverlayComp&); DragOverlayComp& operator= (const DragOverlayComp&); @@ -54530,7 +54520,7 @@ public: if (dnd != 0) { - dnd->startDragging (Toolbar::toolbarDragDescriptor, getParentComponent(), 0, true); + dnd->startDragging (Toolbar::toolbarDragDescriptor, getParentComponent(), Image(), true); ToolbarItemComponent* const tc = dynamic_cast (getParentComponent()); @@ -54904,10 +54894,10 @@ public: if (dragContainer != 0) { pos.setSize (pos.getWidth(), item->itemHeight); - Image* dragImage = Component::createComponentSnapshot (pos, true); - dragImage->multiplyAllAlphas (0.6f); + Image dragImage (Component::createComponentSnapshot (pos, true)); + dragImage.multiplyAllAlphas (0.6f); - Point imageOffset (pos.getX() - e.x, pos.getY() - e.y); + Point imageOffset (pos.getPosition() - e.getPosition()); dragContainer->startDragging (dragDescription, &owner, dragImage, true, &imageOffset); } else @@ -57680,7 +57670,7 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_FileListComponent.cpp ***/ BEGIN_JUCE_NAMESPACE -Image* juce_createIconForFile (const File& file); +const Image juce_createIconForFile (const File& file); FileListComponent::FileListComponent (DirectoryContentsList& listToShow) : ListBox (String::empty, 0), @@ -57750,7 +57740,7 @@ public: { getLookAndFeel().drawFileBrowserRow (g, getWidth(), getHeight(), file.getFileName(), - icon, + &icon, fileSize, modTime, isDirectory, highlighted, index); @@ -57807,12 +57797,11 @@ public: clearIcon(); } - if (file != File::nonexistent - && icon == 0 && ! isDirectory) + if (file != File::nonexistent && icon.isNull() && ! isDirectory) { updateIcon (true); - if (icon == 0) + if (! icon.isValid()) thread.addTimeSliceClient (this); } } @@ -57838,31 +57827,30 @@ private: File file; String fileSize; String modTime; - Image* icon; + Image icon; bool isDirectory; void clearIcon() { - ImageCache::release (icon); - icon = 0; + icon = Image(); } void updateIcon (const bool onlyUpdateIfCached) { - if (icon == 0) + if (icon.isNull()) { const int hashCode = (file.getFullPathName() + "_iconCacheSalt").hashCode(); - Image* im = ImageCache::getFromHashCode (hashCode); + Image im (ImageCache::getFromHashCode (hashCode)); - if (im == 0 && ! onlyUpdateIfCached) + if (im.isNull() && ! onlyUpdateIfCached) { im = juce_createIconForFile (file); - if (im != 0) + if (im.isValid()) ImageCache::addImageToCache (im, hashCode); } - if (im != 0) + if (im.isValid()) { icon = im; triggerAsyncUpdate(); @@ -58381,7 +58369,7 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_FileTreeComponent.cpp ***/ BEGIN_JUCE_NAMESPACE -Image* juce_createIconForFile (const File& file); +const Image juce_createIconForFile (const File& file); class FileListTreeItem : public TreeViewItem, public TimeSliceClient, @@ -58424,7 +58412,6 @@ public: thread.removeTimeSliceClient (this); clearSubItems(); - ImageCache::release (icon); if (canDeleteSubContentsList) delete subContentsList; @@ -58491,15 +58478,14 @@ public: { updateIcon (true); - if (icon == 0) + if (icon.isNull()) thread.addTimeSliceClient (this); } owner.getLookAndFeel() .drawFileBrowserRow (g, width, height, file.getFileName(), - icon, - fileSize, modTime, + &icon, fileSize, modTime, isDirectory, isSelected(), indexInContentsList); } @@ -58544,26 +58530,26 @@ private: DirectoryContentsList* subContentsList; bool isDirectory, canDeleteSubContentsList; TimeSliceThread& thread; - Image* icon; + Image icon; String fileSize; String modTime; void updateIcon (const bool onlyUpdateIfCached) { - if (icon == 0) + if (icon.isNull()) { const int hashCode = (file.getFullPathName() + "_iconCacheSalt").hashCode(); - Image* im = ImageCache::getFromHashCode (hashCode); + Image im (ImageCache::getFromHashCode (hashCode)); - if (im == 0 && ! onlyUpdateIfCached) + if (im.isNull() && ! onlyUpdateIfCached) { im = juce_createIconForFile (file); - if (im != 0) + if (im.isValid()) ImageCache::addImageToCache (im, hashCode); } - if (im != 0) + if (im.isValid()) { icon = im; triggerAsyncUpdate(); @@ -58653,7 +58639,7 @@ void ImagePreviewComponent::timerCallback() { stopTimer(); - currentThumbnail = 0; + currentThumbnail = Image(); currentDetails = String::empty; repaint(); @@ -58667,10 +58653,10 @@ void ImagePreviewComponent::timerCallback() { currentThumbnail = format->decodeImage (*in); - if (currentThumbnail != 0) + if (currentThumbnail.isValid()) { - int w = currentThumbnail->getWidth(); - int h = currentThumbnail->getHeight(); + int w = currentThumbnail.getWidth(); + int h = currentThumbnail.getHeight(); currentDetails << fileToLoad.getFileName() << "\n" @@ -58680,7 +58666,7 @@ void ImagePreviewComponent::timerCallback() getThumbSize (w, h); - currentThumbnail = currentThumbnail->createCopy (w, h); + currentThumbnail = currentThumbnail.rescaled (w, h); } } } @@ -58688,12 +58674,12 @@ void ImagePreviewComponent::timerCallback() void ImagePreviewComponent::paint (Graphics& g) { - if (currentThumbnail != 0) + if (currentThumbnail.isValid()) { g.setFont (13.0f); - int w = currentThumbnail->getWidth(); - int h = currentThumbnail->getHeight(); + int w = currentThumbnail.getWidth(); + int h = currentThumbnail.getHeight(); getThumbSize (w, h); const int numLines = 4; @@ -64629,7 +64615,7 @@ void LookAndFeel::drawPopupMenuItem (Graphics& g, if (image != 0) { - g.drawImageWithin (image, + g.drawImageWithin (*image, 2, 1, leftBorder - 4, height - 2, RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, false); } @@ -65237,7 +65223,7 @@ void LookAndFeel::drawImageButton (Graphics& g, Image* image, { g.setOpacity (imageOpacity); - g.drawImage (image, imageX, imageY, imageW, imageH, + g.drawImage (*image, imageX, imageY, imageW, imageH, 0, 0, image->getWidth(), image->getHeight(), false); } @@ -65245,7 +65231,7 @@ void LookAndFeel::drawImageButton (Graphics& g, Image* image, { g.setColour (overlayColour); - g.drawImage (image, imageX, imageY, imageW, imageH, + g.drawImage (*image, imageX, imageY, imageW, imageH, 0, 0, image->getWidth(), image->getHeight(), true); } } @@ -65338,7 +65324,7 @@ void LookAndFeel::drawDocumentWindowTitleBar (DocumentWindow& window, if (icon != 0) { g.setOpacity (isActive ? 1.0f : 0.6f); - g.drawImageWithin (icon, textX, (h - iconH) / 2, iconW, iconH, + g.drawImageWithin (*icon, textX, (h - iconH) / 2, iconW, iconH, RectanglePlacement::centred, false); textX += iconW; textW -= iconW; @@ -66079,24 +66065,21 @@ void LookAndFeel::drawFileBrowserRow (Graphics& g, int width, int height, g.setColour (findColour (DirectoryContentsDisplayComponent::textColourId)); g.setFont (height * 0.7f); - Image* im = icon; - Image* toRelease = 0; + Image im; + if (icon != 0) + im = *icon; - if (im == 0) - { - toRelease = im = (isDirectory ? getDefaultFolderImage() - : getDefaultDocumentFileImage()); - } + if (im.isNull()) + im = isDirectory ? getDefaultFolderImage() + : getDefaultDocumentFileImage(); const int x = 32; - if (im != 0) + if (im.isValid()) { g.drawImageWithin (im, 2, 2, x - 4, height - 4, RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize, false); - - ImageCache::release (toRelease); } if (width > 450 && ! isDirectory) @@ -66183,7 +66166,7 @@ void LookAndFeel::layoutFileBrowserComponent (FileBrowserComponent& browserComp, filenameBox->setBounds (x + 50, y, w - 50, controlsHeight); } -Image* LookAndFeel::getDefaultFolderImage() +const 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, @@ -66233,7 +66216,7 @@ Image* LookAndFeel::getDefaultFolderImage() return ImageCache::getFromMemory (foldericon_png, sizeof (foldericon_png)); } -Image* LookAndFeel::getDefaultDocumentFileImage() +const 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, @@ -67661,7 +67644,7 @@ public: const String& text_, const bool active_, const bool isTicked_, - const Image* im, + const Image& im, const Colour& textColour_, const bool usesColour_, PopupMenuCustomComponent* const customComp_, @@ -67669,15 +67652,12 @@ public: ApplicationCommandManager* const commandManager_) : itemId (itemId_), text (text_), textColour (textColour_), active (active_), isSeparator (false), isTicked (isTicked_), - usesColour (usesColour_), customComp (customComp_), + usesColour (usesColour_), image (im), customComp (customComp_), commandManager (commandManager_) { if (subMenu_ != 0) subMenu = new PopupMenu (*subMenu_); - if (im != 0) - image = im->createCopy(); - if (commandManager_ != 0 && itemId_ != 0) { String shortcutKey; @@ -67713,14 +67693,12 @@ public: isSeparator (other.isSeparator), isTicked (other.isTicked), usesColour (other.usesColour), + image (other.image), customComp (other.customComp), commandManager (other.commandManager) { if (other.subMenu != 0) subMenu = new PopupMenu (*(other.subMenu)); - - if (other.image != 0) - image = other.image->createCopy(); } ~Item() @@ -67742,7 +67720,7 @@ public: String text; const Colour textColour; const bool active, isSeparator, isTicked, usesColour; - ScopedPointer image; + Image image; ReferenceCountedObjectPtr customComp; ScopedPointer subMenu; ApplicationCommandManager* const commandManager; @@ -67811,7 +67789,7 @@ public: itemInfo.isTicked, itemInfo.subMenu != 0, mainText, endText, - itemInfo.image, + itemInfo.image.isValid() ? &itemInfo.image : 0, itemInfo.usesColour ? &(itemInfo.textColour) : 0); } } @@ -68907,7 +68885,7 @@ void PopupMenu::addItem (const int itemResultId, const String& itemText, const bool isActive, const bool isTicked, - const Image* const iconToUse) + const Image& 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 @@ -68915,8 +68893,8 @@ void PopupMenu::addItem (const int itemResultId, addSeparatorIfPending(); - items.add (new Item (itemResultId, itemText, isActive, isTicked, - iconToUse, Colours::black, false, 0, 0, 0)); + items.add (new Item (itemResultId, itemText, isActive, isTicked, iconToUse, + Colours::black, false, 0, 0, 0)); } void PopupMenu::addCommandItem (ApplicationCommandManager* commandManager, @@ -68939,7 +68917,7 @@ void PopupMenu::addCommandItem (ApplicationCommandManager* commandManager, : info.shortName, target != 0 && (info.flags & ApplicationCommandInfo::isDisabled) == 0, (info.flags & ApplicationCommandInfo::isTicked) != 0, - 0, + Image(), Colours::black, false, 0, 0, @@ -68952,7 +68930,7 @@ void PopupMenu::addColouredItem (const int itemResultId, const Colour& itemTextColour, const bool isActive, const bool isTicked, - const Image* const iconToUse) + const Image& 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 @@ -68960,8 +68938,8 @@ void PopupMenu::addColouredItem (const int itemResultId, addSeparatorIfPending(); - items.add (new Item (itemResultId, itemText, isActive, isTicked, - iconToUse, itemTextColour, true, 0, 0, 0)); + items.add (new Item (itemResultId, itemText, isActive, isTicked, iconToUse, + itemTextColour, true, 0, 0, 0)); } void PopupMenu::addCustomItem (const int itemResultId, @@ -68973,7 +68951,7 @@ void PopupMenu::addCustomItem (const int itemResultId, addSeparatorIfPending(); - items.add (new Item (itemResultId, String::empty, true, false, 0, + items.add (new Item (itemResultId, String::empty, true, false, Image(), Colours::black, false, customComponent, 0, 0)); } @@ -69027,7 +69005,7 @@ void PopupMenu::addCustomItem (const int itemResultId, void PopupMenu::addSubMenu (const String& subMenuName, const PopupMenu& subMenu, const bool isActive, - Image* const iconToUse, + const Image& iconToUse, const bool isTicked) { addSeparatorIfPending(); @@ -69429,7 +69407,7 @@ class DragImageComponent : public Component, public Timer { public: - DragImageComponent (Image* const im, + DragImageComponent (const Image& im, const String& desc, Component* const sourceComponent, Component* const mouseDragSource_, @@ -69444,7 +69422,7 @@ public: hasCheckedForExternalDrag (false), drawImage (true) { - setSize (im->getWidth(), im->getHeight()); + setSize (im.getWidth(), im.getHeight()); if (mouseDragSource == 0) mouseDragSource = source; @@ -69663,7 +69641,7 @@ public: } private: - ScopedPointer image; + Image image; Component::SafePointer source; Component::SafePointer mouseDragSource; DragAndDropContainer* const owner; @@ -69693,11 +69671,11 @@ DragAndDropContainer::~DragAndDropContainer() void DragAndDropContainer::startDragging (const String& sourceDescription, Component* sourceComponent, - Image* dragImage_, + const Image& dragImage_, const bool allowDraggingToExternalWindows, const Point* imageOffsetFromMouse) { - ScopedPointer dragImage (dragImage_); + Image dragImage (dragImage_); if (dragImageComponent == 0) { @@ -69720,32 +69698,24 @@ void DragAndDropContainer::startDragging (const String& sourceDescription, const Point lastMouseDown (Desktop::getLastMouseDownPosition()); Point imageOffset; - if (dragImage == 0) + if (dragImage.isNull()) { - dragImage = sourceComponent->createComponentSnapshot (sourceComponent->getLocalBounds()); + dragImage = sourceComponent->createComponentSnapshot (sourceComponent->getLocalBounds()) + .convertedToFormat (Image::ARGB); - 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->multiplyAllAlphas (0.6f); + dragImage.multiplyAllAlphas (0.6f); const int lo = 150; const int hi = 400; Point relPos (sourceComponent->globalPositionToRelative (lastMouseDown)); - Point clipped (dragImage->getBounds().getConstrainedPoint (relPos)); + Point clipped (dragImage.getBounds().getConstrainedPoint (relPos)); - for (int y = dragImage->getHeight(); --y >= 0;) + for (int y = dragImage.getHeight(); --y >= 0;) { const double dy = (y - clipped.getY()) * (y - clipped.getY()); - for (int x = dragImage->getWidth(); --x >= 0;) + for (int x = dragImage.getWidth(); --x >= 0;) { const int dx = x - clipped.getX(); const int distance = roundToInt (std::sqrt (dx * dx + dy)); @@ -69756,7 +69726,7 @@ void DragAndDropContainer::startDragging (const String& sourceDescription, : (hi - distance) / (float) (hi - lo) + Random::getSystemRandom().nextFloat() * 0.008f; - dragImage->multiplyAlphaAt (x, y, alpha); + dragImage.multiplyAlphaAt (x, y, alpha); } } } @@ -69766,12 +69736,12 @@ void DragAndDropContainer::startDragging (const String& sourceDescription, else { if (imageOffsetFromMouse == 0) - imageOffset = -dragImage->getBounds().getCentre(); + imageOffset = -dragImage.getBounds().getCentre(); else - imageOffset = -(dragImage->getBounds().getConstrainedPoint (-*imageOffsetFromMouse)); + imageOffset = -(dragImage.getBounds().getConstrainedPoint (-*imageOffsetFromMouse)); } - dragImageComponent = new DragImageComponent (dragImage.release(), sourceDescription, sourceComponent, + dragImageComponent = new DragImageComponent (dragImage, sourceDescription, sourceComponent, draggingSource->getComponentUnderMouse(), this, imageOffset); currentDragDesc = sourceDescription; @@ -73150,13 +73120,13 @@ public: void paint (Graphics& g) { - if (colours == 0) + if (colours.isNull()) { const int width = getWidth() / 2; const int height = getHeight() / 2; - colours = new Image (Image::RGB, width, height, false); + colours = 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) { @@ -73165,17 +73135,15 @@ public: for (int x = 0; x < width; ++x) { const float sat = x / (float) width; - const Colour col (h, sat, val, 1.0f); - PixelRGB* const pix = (PixelRGB*) pixels.getPixelPointer (x, y); - pix->set (col.getPixelARGB()); + pixels.setPixelColour (x, y, Colour (h, sat, val, 1.0f)); } } } g.setOpacity (1.0f); g.drawImage (colours, edge, edge, getWidth() - edge * 2, getHeight() - edge * 2, - 0, 0, colours->getWidth(), colours->getHeight()); + 0, 0, colours.getWidth(), colours.getHeight()); } void mouseDown (const MouseEvent& e) @@ -73196,7 +73164,7 @@ public: if (lastHue != h) { lastHue = h; - colours = 0; + colours = Image(); repaint(); } @@ -73205,7 +73173,7 @@ public: void resized() { - colours = 0; + colours = Image(); updateMarker(); } @@ -73217,8 +73185,7 @@ private: float lastHue; ColourSpaceMarker* marker; const int edge; - - ScopedPointer colours; + Image colours; void updateMarker() const { @@ -73663,17 +73630,19 @@ BEGIN_JUCE_NAMESPACE class ShadowWindow : public Component { Component* owner; - Image** shadowImageSections; + Image shadowImageSections [12]; 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_) + const Image shadowImageSections_ [12]) : owner (owner_), - shadowImageSections (shadowImageSections_), type (type_) { + for (int i = 0; i < numElementsInArray (shadowImageSections); ++i) + shadowImageSections [i] = shadowImageSections_ [i]; + setInterceptsMouseClicks (false, false); if (owner_->isOnDesktop()) @@ -73695,41 +73664,41 @@ public: void paint (Graphics& g) { - Image* const topLeft = shadowImageSections [type * 3]; - Image* const bottomRight = shadowImageSections [type * 3 + 1]; - Image* const filler = shadowImageSections [type * 3 + 2]; + const Image& topLeft = shadowImageSections [type * 3]; + const Image& bottomRight = shadowImageSections [type * 3 + 1]; + const Image& filler = shadowImageSections [type * 3 + 2]; g.setOpacity (1.0f); if (type < 2) { - int imH = jmin (topLeft->getHeight(), getHeight() / 2); + int imH = jmin (topLeft.getHeight(), getHeight() / 2); g.drawImage (topLeft, - 0, 0, topLeft->getWidth(), imH, - 0, 0, topLeft->getWidth(), imH); + 0, 0, topLeft.getWidth(), imH, + 0, 0, topLeft.getWidth(), imH); - imH = jmin (bottomRight->getHeight(), getHeight() - getHeight() / 2); + imH = jmin (bottomRight.getHeight(), getHeight() - getHeight() / 2); g.drawImage (bottomRight, - 0, getHeight() - imH, bottomRight->getWidth(), imH, - 0, bottomRight->getHeight() - imH, bottomRight->getWidth(), imH); + 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())); + 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); + int imW = jmin (topLeft.getWidth(), getWidth() / 2); g.drawImage (topLeft, - 0, 0, imW, topLeft->getHeight(), - 0, 0, imW, topLeft->getHeight()); + 0, 0, imW, topLeft.getHeight(), + 0, 0, imW, topLeft.getHeight()); - imW = jmin (bottomRight->getWidth(), getWidth() - getWidth() / 2); + imW = jmin (bottomRight.getWidth(), getWidth() - getWidth() / 2); g.drawImage (bottomRight, - getWidth() - imW, 0, imW, bottomRight->getHeight(), - bottomRight->getWidth() - imW, 0, imW, bottomRight->getHeight()); + 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()); } } @@ -73777,9 +73746,6 @@ void DropShadower::deleteShadowWindows() for (i = numShadows; --i >= 0;) delete shadowWindows[i]; - for (i = 12; --i >= 0;) - delete shadowImageSections[i]; - numShadows = 0; } } @@ -73857,31 +73823,31 @@ void DropShadower::updateShadows() const int hash = imageId.hashCode(); - Image* bigIm = ImageCache::getFromHashCode (hash); + Image bigIm (ImageCache::getFromHashCode (hash)); - if (bigIm == 0) + if (bigIm.isNull()) { - bigIm = Image::createNativeImage (Image::ARGB, shadowEdge * 5, shadowEdge * 5, true); + bigIm = Image (Image::ARGB, shadowEdge * 5, shadowEdge * 5, true, Image::NativeImage); - Graphics bigG (*bigIm); + Graphics bigG (bigIm); bigG.setColour (Colours::black.withAlpha (alpha)); bigG.fillRect (shadowEdge + xOffset, shadowEdge + yOffset, - bigIm->getWidth() - (shadowEdge * 2), - bigIm->getHeight() - (shadowEdge * 2)); + bigIm.getWidth() - (shadowEdge * 2), + bigIm.getHeight() - (shadowEdge * 2)); ImageConvolutionKernel blurKernel (roundToInt (blurRadius * 2.0f)); blurKernel.createGaussianBlur (blurRadius); - blurKernel.applyToImage (*bigIm, 0, + blurKernel.applyToImage (bigIm, bigIm, Rectangle (xOffset, yOffset, - bigIm->getWidth(), bigIm->getHeight())); + bigIm.getWidth(), bigIm.getHeight())); ImageCache::addImageToCache (bigIm, hash); } - const int iw = bigIm->getWidth(); - const int ih = bigIm->getHeight(); + const int iw = bigIm.getWidth(); + const int ih = bigIm.getHeight(); const int shadowEdge2 = shadowEdge * 2; setShadowImage (bigIm, 0, shadowEdge, shadowEdge2, 0, 0); @@ -73897,8 +73863,6 @@ void DropShadower::updateShadows() setShadowImage (bigIm, 10, shadowEdge, shadowEdge, iw - shadowEdge2, ih - shadowEdge); setShadowImage (bigIm, 11, shadowEdge, shadowEdge, shadowEdge2, ih - shadowEdge); - ImageCache::release (bigIm); - for (int i = 0; i < 4; ++i) { shadowWindows[numShadows] = new ShadowWindow (owner, i, shadowImageSections); @@ -73946,12 +73910,12 @@ void DropShadower::updateShadows() bringShadowWindowsToFront(); } -void DropShadower::setShadowImage (Image* const src, const int num, const int w, const int h, +void DropShadower::setShadowImage (const Image& src, 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] = Image (Image::ARGB, w, h, true, Image::NativeImage); - Graphics g (*shadowImageSections[num]); + Graphics g (shadowImageSections[num]); g.drawImage (src, 0, 0, w, h, sx, sy, w, h); } @@ -74213,7 +74177,7 @@ void MagnifierComponent::paint (Graphics& g) } g.setImageResamplingQuality (quality); - g.drawImageTransformed (&temp, temp.getBounds(), + g.drawImageTransformed (temp, temp.getBounds(), AffineTransform::scale ((float) scaleFactor, (float) scaleFactor), false); } @@ -75460,16 +75424,16 @@ void PreferencesPanel::addSettingsPage (const String& title, } void PreferencesPanel::addSettingsPage (const String& title, - const char* imageData, + const void* imageData, const int imageDataSize) { DrawableImage icon, iconOver, iconDown; - icon.setImage (ImageCache::getFromMemory (imageData, imageDataSize), true); + icon.setImage (ImageCache::getFromMemory (imageData, imageDataSize)); - iconOver.setImage (ImageCache::getFromMemory (imageData, imageDataSize), true); + iconOver.setImage (ImageCache::getFromMemory (imageData, imageDataSize)); iconOver.setOverlayColour (Colours::black.withAlpha (0.12f)); - iconDown.setImage (ImageCache::getFromMemory (imageData, imageDataSize), true); + iconDown.setImage (ImageCache::getFromMemory (imageData, imageDataSize)); iconDown.setOverlayColour (Colours::black.withAlpha (0.25f)); addSettingsPage (title, &icon, &iconOver, &iconDown); @@ -76917,9 +76881,9 @@ void DocumentWindow::setName (const String& newName) } } -void DocumentWindow::setIcon (const Image* imageToUse) +void DocumentWindow::setIcon (const Image& imageToUse) { - titleBarIcon = imageToUse != 0 ? imageToUse->createCopy() : 0; + titleBarIcon = imageToUse; repaintTitleBar(); } @@ -77034,7 +76998,7 @@ void DocumentWindow::paint (Graphics& g) titleBarArea.getHeight(), titleSpaceX1, jmax (1, titleSpaceX2 - titleSpaceX1), - titleBarIcon, + titleBarIcon.isValid() ? &titleBarIcon : 0, ! drawTitleTextCentred); } @@ -77727,33 +77691,31 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE SplashScreen::SplashScreen() - : backgroundImage (0) { setOpaque (true); } SplashScreen::~SplashScreen() { - ImageCache::releaseOrDelete (backgroundImage); } void SplashScreen::show (const String& title, - Image* const backgroundImage_, + const Image& backgroundImage_, const int minimumTimeToDisplayFor, const bool useDropShadow, const bool removeOnMouseClick) { backgroundImage = backgroundImage_; - jassert (backgroundImage_ != 0); + jassert (backgroundImage_.isValid()); - if (backgroundImage_ != 0) + if (backgroundImage_.isValid()) { - setOpaque (! backgroundImage_->hasAlphaChannel()); + setOpaque (! backgroundImage_.hasAlphaChannel()); show (title, - backgroundImage_->getWidth(), - backgroundImage_->getHeight(), + backgroundImage_.getWidth(), + backgroundImage_.getHeight(), minimumTimeToDisplayFor, useDropShadow, removeOnMouseClick); @@ -77790,14 +77752,11 @@ void SplashScreen::show (const String& title, void SplashScreen::paint (Graphics& g) { - if (backgroundImage != 0) - { - g.setOpacity (1.0f); + 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() @@ -80113,7 +80072,7 @@ FillType::FillType (const ColourGradient& gradient_) } FillType::FillType (const Image& image_, const AffineTransform& transform_) throw() - : colour (0xff000000), image (&image_), transform (transform_) + : colour (0xff000000), image (image_), transform (transform_) { } @@ -80154,7 +80113,7 @@ bool FillType::operator!= (const FillType& other) const void FillType::setColour (const Colour& newColour) throw() { gradient = 0; - image = 0; + image = Image(); colour = newColour; } @@ -80166,7 +80125,7 @@ void FillType::setGradient (const ColourGradient& newGradient) } else { - image = 0; + image = Image(); gradient = new ColourGradient (newGradient); colour = Colours::black; } @@ -80175,7 +80134,7 @@ void FillType::setGradient (const ColourGradient& newGradient) void FillType::setTiledImage (const Image& image_, const AffineTransform& transform_) throw() { gradient = 0; - image = &image_; + image = image_; transform = transform_; colour = Colours::black; } @@ -80218,7 +80177,7 @@ LowLevelGraphicsContext::~LowLevelGraphicsContext() { } -Graphics::Graphics (Image& imageToDrawOnto) +Graphics::Graphics (const Image& imageToDrawOnto) : context (imageToDrawOnto.createLowLevelContext()), contextToDelete (context), saveStatePending (false) @@ -80758,23 +80717,20 @@ void Graphics::setImageResamplingQuality (const Graphics::ResamplingQuality newQ context->setInterpolationQuality (newQuality); } -void Graphics::drawImageAt (const Image* const imageToDraw, +void Graphics::drawImageAt (const Image& imageToDraw, const int topLeftX, const int topLeftY, const bool fillAlphaChannelWithCurrentBrush) const { - if (imageToDraw != 0) - { - const int imageW = imageToDraw->getWidth(); - const int imageH = imageToDraw->getHeight(); + 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, +void Graphics::drawImageWithin (const Image& imageToDraw, const int destX, const int destY, const int destW, const int destH, const RectanglePlacement& placementWithinTarget, @@ -80783,10 +80739,10 @@ void Graphics::drawImageWithin (const Image* const imageToDraw, // passing in a silly number can cause maths problems in rendering! jassert (areCoordsSensibleNumbers (destX, destY, destW, destH)); - if (imageToDraw != 0) + if (imageToDraw.isValid()) { - const int imageW = imageToDraw->getWidth(); - const int imageH = imageToDraw->getHeight(); + const int imageW = imageToDraw.getWidth(); + const int imageH = imageToDraw.getHeight(); if (imageW > 0 && imageH > 0) { @@ -80809,7 +80765,7 @@ void Graphics::drawImageWithin (const Image* const imageToDraw, } } -void Graphics::drawImage (const Image* const imageToDraw, +void Graphics::drawImage (const Image& imageToDraw, int dx, int dy, int dw, int dh, int sx, int sy, int sw, int sh, const bool fillAlphaChannelWithCurrentBrush) const @@ -80818,7 +80774,7 @@ void Graphics::drawImage (const Image* const imageToDraw, jassert (areCoordsSensibleNumbers (dx, dy, dw, dh)); jassert (areCoordsSensibleNumbers (sx, sy, sw, sh)); - if (context->clipRegionIntersects (Rectangle (dx, dy, dw, dh))) + if (imageToDraw.isValid() && context->clipRegionIntersects (Rectangle (dx, dy, dw, dh))) { drawImageTransformed (imageToDraw, Rectangle (sx, sy, sw, sh), AffineTransform::scale (dw / (float) sw, dh / (float) sh) @@ -80827,25 +80783,25 @@ void Graphics::drawImage (const Image* const imageToDraw, } } -void Graphics::drawImageTransformed (const Image* const imageToDraw, +void Graphics::drawImageTransformed (const Image& imageToDraw, const Rectangle& imageSubRegion, const AffineTransform& transform, const bool fillAlphaChannelWithCurrentBrush) const { - if (imageToDraw != 0 && ! context->isClipEmpty()) + if (imageToDraw.isValid() && ! context->isClipEmpty()) { - const Rectangle srcClip (imageSubRegion.getIntersection (imageToDraw->getBounds())); + const Rectangle srcClip (imageSubRegion.getIntersection (imageToDraw.getBounds())); if (fillAlphaChannelWithCurrentBrush) { context->saveState(); - context->clipToImageAlpha (*imageToDraw, srcClip, transform); + context->clipToImageAlpha (imageToDraw, srcClip, transform); fillAll(); context->restoreState(); } else { - context->drawImage (*imageToDraw, srcClip, transform, false); + context->drawImage (imageToDraw, srcClip, transform, false); } } } @@ -83270,7 +83226,7 @@ public: } else if (fillType.isTiledImage()) { - renderImage (image, *(fillType.image), fillType.image->getBounds(), fillType.transform, shapeToFill); + renderImage (image, fillType.image, fillType.image.getBounds(), fillType.transform, shapeToFill); } else { @@ -83353,13 +83309,13 @@ private: SavedState& operator= (const SavedState&); }; -LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (Image& image_) +LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (const Image& image_) : image (image_) { currentState = new SavedState (image_.getBounds(), 0, 0); } -LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (Image& image_, const int xOffset, const int yOffset, +LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (const Image& image_, const int xOffset, const int yOffset, const RectangleList& initialClip) : image (image_) { @@ -83814,12 +83770,12 @@ Drawable* Drawable::createFromImageData (const void* data, const size_t numBytes { Drawable* result = 0; - Image* const image = ImageFileFormat::loadFrom (data, (int) numBytes); + Image image (ImageFileFormat::loadFrom (data, (int) numBytes)); - if (image != 0) + if (image.isValid()) { DrawableImage* const di = new DrawableImage(); - di->setImage (image, true); + di->setImage (image); result = di; } else @@ -84152,7 +84108,7 @@ void DrawableComposite::render (const Drawable::RenderingContext& context) const } context.g.setOpacity (context.opacity); - context.g.drawImageAt (&tempImage, clipBounds.getX(), clipBounds.getY()); + context.g.drawImageAt (tempImage, clipBounds.getX(), clipBounds.getY()); } } } @@ -84623,7 +84579,6 @@ BEGIN_JUCE_NAMESPACE DrawableImage::DrawableImage() : image (0), - canDeleteImage (false), opacity (1.0f), overlayColour (0x00000000) { @@ -84632,52 +84587,27 @@ DrawableImage::DrawableImage() } DrawableImage::DrawableImage (const DrawableImage& other) - : image (0), - canDeleteImage (false), + : image (other.image), opacity (other.opacity), overlayColour (other.overlayColour) { for (int i = 0; i < numElementsInArray (controlPoints); ++i) controlPoints[i] = other.controlPoints[i]; - - if (other.image != 0) - { - if ((! other.canDeleteImage) || ! ImageCache::isImageInCache (other.image)) - { - setImage (*other.image); - } - else - { - ImageCache::incReferenceCount (other.image); - setImage (other.image, true); - } - } } DrawableImage::~DrawableImage() { - setImage (0, false); } -void DrawableImage::setImage (const Image& imageToCopy) +void DrawableImage::setImage (const Image& imageToUse) { - setImage (new Image (imageToCopy), true); -} - -void DrawableImage::setImage (Image* imageToUse, - const bool releaseWhenNotNeeded) -{ - if (canDeleteImage) - ImageCache::releaseOrDelete (image); - image = imageToUse; - canDeleteImage = releaseWhenNotNeeded; - if (image != 0) + if (image.isValid()) { controlPoints[0] = RelativePoint (Point (0.0f, 0.0f)); - controlPoints[1] = RelativePoint (Point ((float) image->getWidth(), 0.0f)); - controlPoints[2] = RelativePoint (Point (0.0f, (float) image->getHeight())); + controlPoints[1] = RelativePoint (Point ((float) image.getWidth(), 0.0f)); + controlPoints[2] = RelativePoint (Point (0.0f, (float) image.getHeight())); } } @@ -84702,15 +84632,15 @@ void DrawableImage::setTransform (const RelativePoint& imageTopLeftPosition, const AffineTransform DrawableImage::calculateTransform() const { - if (image == 0) + if (image.isNull()) return AffineTransform::identity; Point resolved[3]; for (int i = 0; i < 3; ++i) resolved[i] = controlPoints[i].resolve (parent); - const Point tr (resolved[0] + (resolved[1] - resolved[0]) / (float) image->getWidth()); - const Point bl (resolved[0] + (resolved[2] - resolved[0]) / (float) image->getHeight()); + const Point tr (resolved[0] + (resolved[1] - resolved[0]) / (float) image.getWidth()); + const Point bl (resolved[0] + (resolved[2] - resolved[0]) / (float) image.getHeight()); return AffineTransform::fromTargetPoints (resolved[0].getX(), resolved[0].getY(), tr.getX(), tr.getY(), @@ -84719,27 +84649,27 @@ const AffineTransform DrawableImage::calculateTransform() const void DrawableImage::render (const Drawable::RenderingContext& context) const { - if (image != 0) + if (image.isValid()) { const AffineTransform t (calculateTransform().followedBy (context.transform)); if (opacity > 0.0f && ! overlayColour.isOpaque()) { context.g.setOpacity (context.opacity * opacity); - context.g.drawImageTransformed (image, image->getBounds(), t, false); + context.g.drawImageTransformed (image, image.getBounds(), t, false); } if (! overlayColour.isTransparent()) { context.g.setColour (overlayColour.withMultipliedAlpha (context.opacity)); - context.g.drawImageTransformed (image, image->getBounds(), t, true); + context.g.drawImageTransformed (image, image.getBounds(), t, true); } } } const Rectangle DrawableImage::getBounds() const { - if (image == 0) + if (image.isNull()) return Rectangle(); Point resolved[3]; @@ -84765,7 +84695,7 @@ const Rectangle DrawableImage::getBounds() const bool DrawableImage::hitTest (float x, float y) const { - if (image == 0) + if (image.isNull()) return false; calculateTransform().inverted().transformPoint (x, y); @@ -84775,9 +84705,9 @@ bool DrawableImage::hitTest (float x, float y) const return ix >= 0 && iy >= 0 - && ix < image->getWidth() - && iy < image->getHeight() - && image->getPixelAt (ix, iy).getAlpha() >= 127; + && ix < image.getWidth() + && iy < image.getHeight() + && image.getPixelAt (ix, iy).getAlpha() >= 127; } Drawable* DrawableImage::createCopy() const @@ -84878,7 +84808,7 @@ const Rectangle DrawableImage::refreshFromValueTree (const ValueTree& tre const float newOpacity = controller.getOpacity(); const Colour newOverlayColour (controller.getOverlayColour()); - Image* newImage = 0; + Image newImage; const var imageIdentifier (controller.getImageIdentifier()); jassert (imageProvider != 0 || imageIdentifier.isVoid()); // if you're using images, you need to provide something that can load and save them! @@ -84902,20 +84832,11 @@ const Rectangle DrawableImage::refreshFromValueTree (const ValueTree& tre controlPoints[0] = newControlPoint[0]; controlPoints[1] = newControlPoint[1]; controlPoints[2] = newControlPoint[2]; - - if (image != newImage) - { - if (canDeleteImage) - ImageCache::releaseOrDelete (image); - - canDeleteImage = true; - image = newImage; - } + image = newImage; return damage.getUnion (getBounds()); } - ImageCache::release (newImage); return Rectangle(); } @@ -84931,7 +84852,7 @@ const ValueTree DrawableImage::createValueTree (ImageProvider* imageProvider) co v.setTargetPositionForTopRight (controlPoints[1], 0); v.setTargetPositionForBottomLeft (controlPoints[2], 0); - if (image != 0) + if (image.isValid()) { jassert (imageProvider != 0); // if you're using images, you need to provide something that can load and save them! @@ -86737,10 +86658,10 @@ void DropShadowEffect::applyEffect (Image& image, Graphics& g) } g.setColour (Colours::black.withAlpha (opacity)); - g.drawImageAt (&shadowImage, offsetX, offsetY, true); + g.drawImageAt (shadowImage, offsetX, offsetY, true); g.setOpacity (1.0f); - g.drawImageAt (&image, 0, 0); + g.drawImageAt (image, 0, 0); } #if JUCE_MSVC && JUCE_DEBUG @@ -86780,13 +86701,13 @@ void GlowEffect::applyEffect (Image& image, Graphics& g) blurKernel.createGaussianBlur (radius); blurKernel.rescaleAllValues (radius); - blurKernel.applyToImage (temp, &image, image.getBounds()); + blurKernel.applyToImage (temp, image, image.getBounds()); g.setColour (colour); - g.drawImageAt (&temp, 0, 0, true); + g.drawImageAt (temp, 0, 0, true); g.setOpacity (1.0f); - g.drawImageAt (&image, 0, 0, false); + g.drawImageAt (image, 0, 0, false); } END_JUCE_NAMESPACE @@ -86813,7 +86734,7 @@ void ReduceOpacityEffect::setOpacity (const float newOpacity) void ReduceOpacityEffect::applyEffect (Image& image, Graphics& g) { g.setOpacity (opacity); - g.drawImageAt (&image, 0, 0); + g.drawImageAt (image, 0, 0); } END_JUCE_NAMESPACE @@ -92528,25 +92449,6 @@ namespace RelativeCoordinateHelpers return String (n, 3).trimCharactersAtEnd ("0").trimCharactersAtEnd ("."); } - - static bool couldBeMistakenForPathCommand (const String& s) - { - switch (s[0]) - { - case 'a': - case 'm': - case 'l': - case 'z': - case 'q': - case 'c': - return s[1] == 0 || CharacterFunctions::isWhitespace (s[1]); - - default: - break; - } - - return false; - } } const String RelativeCoordinate::Strings::parent ("parent"); @@ -92945,7 +92847,7 @@ RelativePointPath::RelativePointPath (const RelativePointPath& other) containsDynamicPoints (false) { ValueTree state (DrawablePath::valueTreeType); - writeTo (state, 0); + other.writeTo (state, 0); parse (state); } @@ -92976,7 +92878,7 @@ RelativePointPath::RelativePointPath (const Path& path) } } -void RelativePointPath::writeTo (ValueTree state, UndoManager* undoManager) +void RelativePointPath::writeTo (ValueTree state, UndoManager* undoManager) const { DrawablePath::ValueTreeWrapper wrapper (state); wrapper.setUsesNonZeroWinding (usesNonZeroWinding, undoManager); @@ -93186,78 +93088,182 @@ BEGIN_JUCE_NAMESPACE static const int fullAlphaThreshold = 253; -Image::Image (const PixelFormat format_, - const int imageWidth_, - const int imageHeight_) - : format (format_), - imageWidth (imageWidth_), - imageHeight (imageHeight_), - imageData (0) +Image::SharedImage::SharedImage (const PixelFormat format_, const int width_, const int height_) + : format (format_), width (width_), height (height_) { 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 (width > 0 && height > 0); // It's illegal to create a zero-sized image! } -Image::Image (const PixelFormat format_, - const int imageWidth_, - const int imageHeight_, - const bool clearImage) - : format (format_), - imageWidth (imageWidth_), - imageHeight (imageHeight_) +Image::SharedImage::~SharedImage() { - 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; +inline uint8* Image::SharedImage::getPixelData (const int x, const int y) const throw() +{ + return imageData + lineStride * y + pixelStride * x; +} - imageDataAllocated.allocate (lineStride * jmax (1, imageHeight_), clearImage); - imageData = imageDataAllocated; +class SoftwareSharedImage : public Image::SharedImage +{ +public: + SoftwareSharedImage (const Image::PixelFormat format_, const int width_, const int height_, const bool clearImage) + : Image::SharedImage (format_, width_, height_) + { + pixelStride = format_ == Image::RGB ? 3 : ((format_ == Image::ARGB) ? 4 : 1); + lineStride = (pixelStride * jmax (1, width) + 3) & ~3; + + imageDataAllocated.allocate (lineStride * jmax (1, height), clearImage); + imageData = imageDataAllocated; + } + + ~SoftwareSharedImage() + { + } + + Image::ImageType getType() const + { + return Image::SoftwareImage; + } + + LowLevelGraphicsContext* createLowLevelContext() + { + return new LowLevelGraphicsSoftwareRenderer (Image (this)); + } + + SharedImage* clone() + { + SoftwareSharedImage* s = new SoftwareSharedImage (format, width, height, false); + memcpy (s->imageData, imageData, lineStride * height); + return s; + } + +private: + HeapBlock imageDataAllocated; +}; + +Image::SharedImage* Image::SharedImage::createSoftwareImage (Image::PixelFormat format, int width, int height, bool clearImage) +{ + return new SoftwareSharedImage (format, width, height, clearImage); +} + +Image::Image() +{ +} + +Image::Image (SharedImage* const instance) + : image (instance) +{ +} + +Image::Image (const PixelFormat format, + const int width, const int height, + const bool clearImage, const ImageType type) + : image (type == Image::NativeImage ? SharedImage::createNativeImage (format, width, height, clearImage) + : new SoftwareSharedImage (format, width, height, clearImage)) +{ } Image::Image (const Image& other) - : format (other.format), - imageWidth (other.imageWidth), - imageHeight (other.imageHeight) + : image (other.image) { - pixelStride = (format == RGB) ? 3 : ((format == ARGB) ? 4 : 1); - lineStride = (pixelStride * jmax (1, imageWidth) + 3) & ~3; +} - imageDataAllocated.malloc (lineStride * jmax (1, imageHeight)); - imageData = imageDataAllocated; - - BitmapData srcData (other, 0, 0, imageWidth, imageHeight); - setPixelData (0, 0, imageWidth, imageHeight, srcData.data, srcData.lineStride); +Image& Image::operator= (const Image& other) +{ + image = other.image; + return *this; } Image::~Image() { } -LowLevelGraphicsContext* Image::createLowLevelContext() +LowLevelGraphicsContext* Image::createLowLevelContext() const { - return new LowLevelGraphicsSoftwareRenderer (*this); + return image == 0 ? 0 : image->createLowLevelContext(); +} + +void Image::duplicateIfShared() +{ + if (image != 0 && image->getReferenceCount() > 1) + image = image->clone(); +} + +const Image Image::rescaled (const int newWidth, const int newHeight, const Graphics::ResamplingQuality quality) const +{ + if (image == 0 || (image->width == newWidth && image->height == newHeight)) + return *this; + + Image newImage (image->format, newWidth, newHeight, hasAlphaChannel(), image->getType()); + + Graphics g (newImage); + g.setImageResamplingQuality (quality); + g.drawImage (*this, 0, 0, newWidth, newHeight, 0, 0, image->width, image->height, false); + + return newImage; +} + +const Image Image::convertedToFormat (PixelFormat newFormat) const +{ + if (image == 0 || newFormat == image->format) + return *this; + + Image newImage (newFormat, image->width, image->height, false, image->getType()); + + if (newFormat == SingleChannel) + { + if (! hasAlphaChannel()) + { + newImage.clear (getBounds(), Colours::black); + } + else + { + const BitmapData destData (newImage, 0, 0, image->width, image->height, true); + const BitmapData srcData (*this, 0, 0, image->width, image->height); + + for (int y = 0; y < image->height; ++y) + { + const PixelARGB* src = (const PixelARGB*) srcData.getLinePointer(y); + uint8* dst = destData.getLinePointer (y); + + for (int x = image->width; --x >= 0;) + { + *dst++ = src->getAlpha(); + ++src; + } + } + } + } + else + { + if (hasAlphaChannel()) + newImage.clear (getBounds()); + + Graphics g (newImage); + g.drawImageAt (*this, 0, 0); + } + + return newImage; } Image::BitmapData::BitmapData (Image& image, const int x, const int y, const int w, const int h, const bool /*makeWritable*/) - : data (image.imageData + image.lineStride * y + image.pixelStride * x), + : data (image.image == 0 ? 0 : image.image->getPixelData (x, y)), pixelFormat (image.getFormat()), - lineStride (image.lineStride), - pixelStride (image.pixelStride), + lineStride (image.image == 0 ? 0 : image.image->lineStride), + pixelStride (image.image == 0 ? 0 : image.image->pixelStride), width (w), height (h) { + jassert (data != 0); jassert (x >= 0 && y >= 0 && w > 0 && h > 0 && x + w <= image.getWidth() && y + h <= image.getHeight()); } Image::BitmapData::BitmapData (const Image& image, const int x, const int y, const int w, const int h) - : data (image.imageData + image.lineStride * y + image.pixelStride * x), + : data (image.image == 0 ? 0 : image.image->getPixelData (x, y)), pixelFormat (image.getFormat()), - lineStride (image.lineStride), - pixelStride (image.pixelStride), + lineStride (image.image == 0 ? 0 : image.image->lineStride), + pixelStride (image.image == 0 ? 0 : image.image->pixelStride), width (w), height (h) { @@ -93268,12 +93274,56 @@ Image::BitmapData::~BitmapData() { } +const Colour Image::BitmapData::getPixelColour (const int x, const int y) const throw() +{ + jassert (((unsigned int) x) < (unsigned int) width && ((unsigned int) y) < (unsigned int) height); + + const uint8* const pixel = getPixelPointer (x, y); + + switch (pixelFormat) + { + case Image::ARGB: + { + PixelARGB p (*(const PixelARGB*) pixel); + p.unpremultiply(); + return Colour (p.getARGB()); + } + case Image::RGB: + return Colour (((const PixelRGB*) pixel)->getARGB()); + + case Image::SingleChannel: + return Colour ((uint8) 0, (uint8) 0, (uint8) 0, *pixel); + + default: + jassertfalse; + break; + } + + return Colour(); +} + +void Image::BitmapData::setPixelColour (const int x, const int y, const Colour& colour) const throw() +{ + jassert (((unsigned int) x) < (unsigned int) width && ((unsigned int) y) < (unsigned int) height); + + uint8* const pixel = getPixelPointer (x, y); + const PixelARGB col (colour.getPixelARGB()); + + switch (pixelFormat) + { + case Image::ARGB: ((PixelARGB*) pixel)->set (col); break; + case Image::RGB: ((PixelRGB*) pixel)->set (col); break; + case Image::SingleChannel: *pixel = col.getAlpha(); break; + default: jassertfalse; break; + } +} + void Image::setPixelData (int x, int y, int w, int h, const uint8* const sourcePixelData, const 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 <= getWidth() && y + h <= getHeight()); - if (Rectangle::intersectRectangles (x, y, w, h, 0, 0, imageWidth, imageHeight)) + if (Rectangle::intersectRectangles (x, y, w, h, 0, 0, getWidth(), getHeight())) { const BitmapData dest (*this, x, y, w, h, true); @@ -93331,106 +93381,32 @@ void Image::clear (const Rectangle& area, const Colour& colourToClearTo) } } -Image* Image::createCopy (int newWidth, int newHeight, - const Graphics::ResamplingQuality quality) const -{ - if (newWidth < 0) - newWidth = imageWidth; - - if (newHeight < 0) - newHeight = imageHeight; - - Image* const newImage = Image::createNativeImage (format, newWidth, newHeight, true); - - Graphics g (*newImage); - g.setImageResamplingQuality (quality); - - g.drawImage (this, - 0, 0, newWidth, newHeight, - 0, 0, imageWidth, imageHeight, - false); - - return newImage; -} - -Image* Image::createCopyOfAlphaChannel() const -{ - jassert (format != SingleChannel); - - Image* const newImage = Image::createNativeImage (SingleChannel, imageWidth, imageHeight, false); - - if (! hasAlphaChannel()) - { - newImage->clear (getBounds(), 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 x = imageWidth; --x >= 0;) - { - *dst++ = src->getAlpha(); - ++src; - } - } - } - - return newImage; -} - const Colour Image::getPixelAt (const int x, const int y) const { - Colour c; - - if (((unsigned int) x) < (unsigned int) imageWidth - && ((unsigned int) y) < (unsigned int) imageHeight) + if (((unsigned int) x) < (unsigned int) getWidth() + && ((unsigned int) y) < (unsigned int) getHeight()) { 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)); + return srcData.getPixelColour (0, 0); } - return c; + return Colour(); } -void Image::setPixelAt (const int x, const int y, - const Colour& colour) +void Image::setPixelAt (const int x, const int y, const Colour& colour) { - if (((unsigned int) x) < (unsigned int) imageWidth - && ((unsigned int) y) < (unsigned int) imageHeight) + if (((unsigned int) x) < (unsigned int) getWidth() + && ((unsigned int) y) < (unsigned int) getHeight()) { 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(); + destData.setPixelColour (0, 0, colour); } } -void Image::multiplyAlphaAt (const int x, const int y, - const float multiplier) +void Image::multiplyAlphaAt (const int x, const int y, const float multiplier) { - if (((unsigned int) x) < (unsigned int) imageWidth - && ((unsigned int) y) < (unsigned int) imageHeight + if (((unsigned int) x) < (unsigned int) getWidth() + && ((unsigned int) y) < (unsigned int) getHeight() && hasAlphaChannel()) { const BitmapData destData (*this, x, y, 1, 1, true); @@ -93450,11 +93426,11 @@ void Image::multiplyAllAlphas (const float amountToMultiplyBy) if (isARGB()) { - for (int y = 0; y < imageHeight; ++y) + for (int y = 0; y < destData.height; ++y) { uint8* p = destData.getLinePointer (y); - for (int x = 0; x < imageWidth; ++x) + for (int x = 0; x < destData.width; ++x) { ((PixelARGB*) p)->multiplyAlpha (amountToMultiplyBy); p += destData.pixelStride; @@ -93463,11 +93439,11 @@ void Image::multiplyAllAlphas (const float amountToMultiplyBy) } else { - for (int y = 0; y < imageHeight; ++y) + for (int y = 0; y < destData.height; ++y) { uint8* p = destData.getLinePointer (y); - for (int x = 0; x < imageWidth; ++x) + for (int x = 0; x < destData.width; ++x) { *p = (uint8) (*p * amountToMultiplyBy); p += destData.pixelStride; @@ -93489,11 +93465,11 @@ void Image::desaturate() if (isARGB()) { - for (int y = 0; y < imageHeight; ++y) + for (int y = 0; y < destData.height; ++y) { uint8* p = destData.getLinePointer (y); - for (int x = 0; x < imageWidth; ++x) + for (int x = 0; x < destData.width; ++x) { ((PixelARGB*) p)->desaturate(); p += destData.pixelStride; @@ -93502,11 +93478,11 @@ void Image::desaturate() } else { - for (int y = 0; y < imageHeight; ++y) + for (int y = 0; y < destData.height; ++y) { uint8* p = destData.getLinePointer (y); - for (int x = 0; x < imageWidth; ++x) + for (int x = 0; x < destData.width; ++x) { ((PixelRGB*) p)->desaturate(); p += destData.pixelStride; @@ -93525,14 +93501,14 @@ void Image::createSolidAreaMask (RectangleList& result, const float alphaThresho const BitmapData srcData (*this, 0, 0, getWidth(), getHeight()); - for (int y = 0; y < imageHeight; ++y) + for (int y = 0; y < srcData.height; ++y) { pixelsOnRow.clear(); const uint8* lineData = srcData.getLinePointer (y); if (isARGB()) { - for (int x = 0; x < imageWidth; ++x) + for (int x = 0; x < srcData.width; ++x) { if (((const PixelARGB*) lineData)->getAlpha() >= threshold) pixelsOnRow.addRange (Range (x, x + 1)); @@ -93542,7 +93518,7 @@ void Image::createSolidAreaMask (RectangleList& result, const float alphaThresho } else { - for (int x = 0; x < imageWidth; ++x) + for (int x = 0; x < srcData.width; ++x) { if (*lineData >= threshold) pixelsOnRow.addRange (Range (x, x + 1)); @@ -93562,7 +93538,7 @@ void Image::createSolidAreaMask (RectangleList& result, const float alphaThresho } else { - result.add (0, 0, imageWidth, imageHeight); + result.add (0, 0, getWidth(), getHeight()); } } @@ -93643,173 +93619,117 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_ImageCache.cpp ***/ BEGIN_JUCE_NAMESPACE -struct ImageCache::Item +class ImageCache::Pimpl : public Timer, + public DeletedAtShutdown { - ScopedPointer image; - int64 hashCode; - int refCount; - uint32 releaseTime; - - juce_UseDebuggingNewOperator -}; - -ImageCache* ImageCache::instance = 0; -int ImageCache::cacheTimeout = 5000; - -ImageCache::ImageCache() -{ -} - -ImageCache::~ImageCache() -{ - jassert (instance == this); - instance = 0; -} - -Image* ImageCache::getFromHashCode (const int64 hashCode) -{ - if (instance != 0) +public: + Pimpl() + : cacheTimeout (5000) { - const ScopedLock sl (instance->lock); + } - for (int i = instance->images.size(); --i >= 0;) + ~Pimpl() + { + clearSingletonInstance(); + } + + const Image getFromHashCode (const int64 hashCode) + { + const ScopedLock sl (lock); + + for (int i = images.size(); --i >= 0;) { - Item* const ci = instance->images.getUnchecked(i); + Item* const item = images.getUnchecked(i); - if (ci->hashCode == hashCode) - { - ci->refCount++; - return ci->image; - } + if (item->hashCode == hashCode) + return item->image; + } + + return Image(); + } + + void addImageToCache (const Image& image, const int64 hashCode) + { + if (image.isValid()) + { + if (! isTimerRunning()) + startTimer (2000); + + Item* const item = new Item(); + item->hashCode = hashCode; + item->image = image; + item->lastUseTime = Time::getApproximateMillisecondCounter(); + + const ScopedLock sl (lock); + images.add (item); } } - return 0; -} - -void ImageCache::addImageToCache (Image* const image, const int64 hashCode) -{ - if (image != 0) + void timerCallback() { - if (instance == 0) - instance = new ImageCache(); + const uint32 now = Time::getApproximateMillisecondCounter(); - Item* const newC = new Item(); - newC->hashCode = hashCode; - newC->image = image; - newC->refCount = 1; - newC->releaseTime = 0; + const ScopedLock sl (lock); - 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); - - for (int i = instance->images.size(); --i >= 0;) + for (int i = images.size(); --i >= 0;) { - Item* const ci = instance->images.getUnchecked(i); + Item* const item = images.getUnchecked(i); - if (static_cast (ci->image) == imageToRelease) + if (item->image.getReferenceCount() <= 1) { - if (--(ci->refCount) == 0) - ci->releaseTime = Time::getApproximateMillisecondCounter(); - - if (! instance->isTimerRunning()) - instance->startTimer (999); - - break; - } - } - } -} - -void ImageCache::releaseOrDelete (Image* const imageToRelease) -{ - if (isImageInCache (imageToRelease)) - release (imageToRelease); - else - delete imageToRelease; -} - -bool ImageCache::isImageInCache (Image* const imageToLookFor) -{ - if (imageToLookFor == 0) - return false; - - if (instance != 0) - { - const ScopedLock sl (instance->lock); - - for (int i = instance->images.size(); --i >= 0;) - if (static_cast (instance->images.getUnchecked(i)->image) == imageToLookFor) - return true; - } - - return false; -} - -void ImageCache::incReferenceCount (Image* const image) -{ - if (instance != 0) - { - const ScopedLock sl (instance->lock); - - for (int i = instance->images.size(); --i >= 0;) - { - Item* const ci = instance->images.getUnchecked(i); - - if (static_cast (ci->image) == image) - { - ci->refCount++; - return; - } - } - } - - jassertfalse; // (trying to inc the ref count of an image that's not in the cache) -} - -void ImageCache::timerCallback() -{ - int numberStillNeedingReleasing = 0; - const uint32 now = Time::getApproximateMillisecondCounter(); - - const ScopedLock sl (lock); - - for (int i = images.size(); --i >= 0;) - { - Item* const ci = images.getUnchecked(i); - - if (ci->refCount <= 0) - { - if (now > ci->releaseTime + cacheTimeout - || now < ci->releaseTime - 1000) - { - images.remove (i); + if (now > item->lastUseTime + cacheTimeout || now < item->lastUseTime - 1000) + images.remove (i); } else { - ++numberStillNeedingReleasing; + item->lastUseTime = now; // multiply-referenced, so this image is still in use. } } + + if (images.size() == 0) + stopTimer(); } - if (numberStillNeedingReleasing == 0) - stopTimer(); + struct Item + { + Image image; + int64 hashCode; + uint32 lastUseTime; + }; + + int cacheTimeout; + + juce_DeclareSingleton_SingleThreaded_Minimal (ImageCache::Pimpl); + +private: + OwnedArray images; + CriticalSection lock; + + Pimpl (const Pimpl&); + Pimpl& operator= (const Pimpl&); +}; + +juce_ImplementSingleton_SingleThreaded (ImageCache::Pimpl); + +const Image ImageCache::getFromHashCode (const int64 hashCode) +{ + if (Pimpl::getInstanceWithoutCreating() != 0) + return Pimpl::getInstanceWithoutCreating()->getFromHashCode (hashCode); + + return Image(); } -Image* ImageCache::getFromFile (const File& file) +void ImageCache::addImageToCache (const Image& image, const int64 hashCode) +{ + Pimpl::getInstance()->addImageToCache (image, hashCode); +} + +const Image ImageCache::getFromFile (const File& file) { const int64 hashCode = file.hashCode64(); - Image* image = getFromHashCode (hashCode); + Image image (getFromHashCode (hashCode)); - if (image == 0) + if (image.isNull()) { image = ImageFileFormat::loadFrom (file); addImageToCache (image, hashCode); @@ -93818,12 +93738,12 @@ Image* ImageCache::getFromFile (const File& file) return image; } -Image* ImageCache::getFromMemory (const void* imageData, const int dataSize) +const Image ImageCache::getFromMemory (const void* imageData, const int dataSize) { const int64 hashCode = (int64) (pointer_sized_int) imageData; - Image* image = getFromHashCode (hashCode); + Image image (getFromHashCode (hashCode)); - if (image == 0) + if (image.isNull()) { image = ImageFileFormat::loadFrom (imageData, dataSize); addImageToCache (image, hashCode); @@ -93834,7 +93754,7 @@ Image* ImageCache::getFromMemory (const void* imageData, const int dataSize) void ImageCache::setCacheTimeout (const int millisecs) { - cacheTimeout = millisecs; + Pimpl::getInstance()->cacheTimeout = millisecs; } END_JUCE_NAMESPACE @@ -93924,25 +93844,22 @@ void ImageConvolutionKernel::createGaussianBlur (const float radius) } void ImageConvolutionKernel::applyToImage (Image& destImage, - const Image* sourceImage, + const Image& sourceImage, const Rectangle& destinationArea) const { - ScopedPointer imageCreated; - - if (sourceImage == 0) + if (sourceImage == destImage) { - sourceImage = imageCreated = destImage.createCopy(); + destImage.duplicateIfShared(); } 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()) + if (sourceImage.getWidth() != destImage.getWidth() + || sourceImage.getHeight() != destImage.getHeight() + || sourceImage.getFormat() != destImage.getFormat()) + { + jassertfalse; return; + } } const Rectangle area (destinationArea.getIntersection (destImage.getBounds())); @@ -93956,7 +93873,7 @@ void ImageConvolutionKernel::applyToImage (Image& destImage, const Image::BitmapData destData (destImage, area.getX(), area.getY(), area.getWidth(), area.getHeight(), 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) { @@ -94095,10 +94012,10 @@ public: GIFLoader (InputStream& in); ~GIFLoader(); - Image* getImage() const { return image; } + const Image& getImage() const { return image; } private: - Image* image; + Image image; InputStream& input; uint8 buffer [300]; uint8 palette [256][4]; @@ -94153,7 +94070,7 @@ public: && header[2] == 'F'; } - Image* decodeImage (InputStream& in) + const Image decodeImage (InputStream& in) { const ScopedPointer loader (new GIFLoader (in)); return loader->getImage(); @@ -94192,17 +94109,17 @@ ImageFileFormat* ImageFileFormat::findImageFormatForStream (InputStream& input) return 0; } -Image* ImageFileFormat::loadFrom (InputStream& input) +const Image ImageFileFormat::loadFrom (InputStream& input) { ImageFileFormat* const format = findImageFormatForStream (input); if (format != 0) return format->decodeImage (input); - return 0; + return Image(); } -Image* ImageFileFormat::loadFrom (const File& file) +const Image ImageFileFormat::loadFrom (const File& file) { InputStream* const in = file.createInputStream(); @@ -94212,10 +94129,10 @@ Image* ImageFileFormat::loadFrom (const File& file) return loadFrom (b); } - return 0; + return Image(); } -Image* ImageFileFormat::loadFrom (const void* rawData, const int numBytes) +const Image ImageFileFormat::loadFrom (const void* rawData, const int numBytes) { if (rawData != 0 && numBytes > 4) { @@ -94223,7 +94140,7 @@ Image* ImageFileFormat::loadFrom (const void* rawData, const int numBytes) return loadFrom (stream); } - return 0; + return Image(); } END_JUCE_NAMESPACE @@ -94297,8 +94214,8 @@ GIFLoader::GIFLoader (InputStream& in) if (! readPalette (numColours)) break; - image = Image::createNativeImage ((transparent >= 0) ? Image::ARGB : Image::RGB, - imageWidth, imageHeight, (transparent >= 0)); + image = Image ((transparent >= 0) ? Image::ARGB : Image::RGB, + imageWidth, imageHeight, (transparent >= 0)); readImage (imageWidth, imageHeight, (buf[8] & 0x40) != 0, @@ -94582,9 +94499,9 @@ bool GIFLoader::readImage (const int width, const int height, int index; int xpos = 0, ypos = 0, pass = 0; - const Image::BitmapData destData (*image, 0, 0, width, height, true); + const Image::BitmapData destData (image, 0, 0, width, height, true); uint8* p = destData.data; - const bool hasAlpha = image->hasAlphaChannel(); + const bool hasAlpha = image.hasAlphaChannel(); while ((index = readLZWByte (false, c)) >= 0) { @@ -209709,7 +209626,7 @@ bool JPEGImageFormat::canUnderstand (InputStream& in) return false; } -Image* JPEGImageFormat::decodeImage (InputStream& in) +const Image JPEGImageFormat::decodeImage (InputStream& in) { using namespace jpeglibNamespace; using namespace JPEGHelpers; @@ -209717,7 +209634,7 @@ Image* JPEGImageFormat::decodeImage (InputStream& in) MemoryBlock mb; in.readIntoMemoryBlock (mb); - Image* image = 0; + Image image; if (mb.getSize() > 16) { @@ -209759,10 +209676,10 @@ Image* JPEGImageFormat::decodeImage (InputStream& in) if (jpeg_start_decompress (&jpegDecompStruct)) { - image = Image::createNativeImage (Image::RGB, width, height, false); - const bool hasAlphaChan = image->hasAlphaChannel(); + image = Image (Image::RGB, width, height, false); + const bool hasAlphaChan = image.hasAlphaChannel(); // (the native image creator may not give back what we expect) - 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) { @@ -235389,10 +235306,10 @@ bool PNGImageFormat::canUnderstand (InputStream& in) && header[3] == 'G'; } -Image* PNGImageFormat::decodeImage (InputStream& in) +const Image PNGImageFormat::decodeImage (InputStream& in) { using namespace pnglibNamespace; - Image* image = 0; + Image image; png_structp pngReadStruct; png_infop pngInfoStruct; @@ -235406,7 +235323,7 @@ Image* PNGImageFormat::decodeImage (InputStream& in) if (pngInfoStruct == 0) { png_destroy_read_struct (&pngReadStruct, 0, 0); - return 0; + return Image(); } png_set_error_fn (pngReadStruct, 0, PNGHelpers::errorCallback, PNGHelpers::errorCallback ); @@ -235459,12 +235376,12 @@ Image* PNGImageFormat::decodeImage (InputStream& in) png_destroy_read_struct (&pngReadStruct, &pngInfoStruct, 0); // now convert the data to a juce image format.. - image = Image::createNativeImage (hasAlphaChan ? Image::ARGB : Image::RGB, - (int) width, (int) height, hasAlphaChan); + image = Image (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, (int) width, (int) height, true); + const Image::BitmapData destData (image, 0, 0, (int) width, (int) height, true); uint8* srcRow = tempBuffer; uint8* destRow = destData.data; @@ -238300,7 +238217,7 @@ const int KeyPress::stopKey = 0x30001; const int KeyPress::fastForwardKey = 0x30002; const int KeyPress::rewindKey = 0x30003; -class WindowsBitmapImage : public Image +class WindowsBitmapImage : public Image::SharedImage { public: @@ -238309,13 +238226,13 @@ public: HDC hdc; unsigned char* bitmapData; - WindowsBitmapImage (const PixelFormat format_, + WindowsBitmapImage (const Image::PixelFormat format_, const int w, const int h, const bool clearImage) - : Image (format_, w, h) + : Image::SharedImage (format_, w, h) { - jassert (format_ == RGB || format_ == ARGB); + jassert (format_ == Image::RGB || format_ == Image::ARGB); - pixelStride = (format_ == RGB) ? 3 : 4; + pixelStride = (format_ == Image::RGB) ? 3 : 4; zerostruct (bitmapInfo); bitmapInfo.bV4Size = sizeof (BITMAPV4HEADER); @@ -238325,7 +238242,7 @@ public: bitmapInfo.bV4CSType = 1; bitmapInfo.bV4BitCount = (unsigned short) (pixelStride * 8); - if (format_ == ARGB) + if (format_ == Image::ARGB) { bitmapInfo.bV4AlphaMask = 0xff000000; bitmapInfo.bV4RedMask = 0xff0000; @@ -238354,7 +238271,7 @@ public: SelectObject (hdc, hBitmap); - if (format_ == ARGB && clearImage) + if (format_ == Image::ARGB && clearImage) zeromem (bitmapData, abs (h * lineStride)); imageData = bitmapData - (lineStride * (h - 1)); @@ -238366,6 +238283,23 @@ public: DeleteObject (hBitmap); } + Image::ImageType getType() const { return Image::NativeImage; } + + LowLevelGraphicsContext* createLowLevelContext() + { + return new LowLevelGraphicsSoftwareRenderer (Image (this)); + } + + SharedImage* clone() + { + WindowsBitmapImage* im = new WindowsBitmapImage (format, width, height, false); + + for (int i = 0; i < height; ++i) + memcpy (im->imageData + i * lineStride, imageData + i * lineStride, lineStride); + + return im; + } + void blitToWindow (HWND hwnd, HDC dc, const bool transparent, const int x, const int y, const RectangleList& maskedRegion) throw() @@ -238454,14 +238388,11 @@ public: } } - const int w = getWidth(); - const int h = getHeight(); - if (hdd == 0) { StretchDIBits (dc, - x, y, w, h, - 0, 0, w, h, + x, y, width, height, + 0, 0, width, height, bitmapData, (const BITMAPINFO*) &bitmapInfo, DIB_RGB_COLORS, SRCCOPY); } @@ -238469,7 +238400,7 @@ public: { DrawDibDraw (hdd, dc, x, y, -1, -1, (BITMAPINFOHEADER*) &bitmapInfo, bitmapData, - 0, 0, w, h, 0); + 0, 0, width, height, 0); } if (! maskedRegion.isEmpty()) @@ -238556,7 +238487,7 @@ public: ~Win32ComponentPeer() { - setTaskBarIcon (0); + setTaskBarIcon (Image()); deleteAndZero (shadower); // do this before the next bit to avoid messages arriving for this window @@ -238880,11 +238811,11 @@ public: return 0; } - void setTaskBarIcon (const Image* const image) + void setTaskBarIcon (const Image& image) { - if (image != 0) + if (image.isValid()) { - HICON hicon = createHICONFromImage (*image, TRUE, 0, 0); + HICON hicon = createHICONFromImage (image, TRUE, 0, 0); if (taskBarIcon == 0) { @@ -238996,12 +238927,12 @@ private: TemporaryImage() {} ~TemporaryImage() {} - WindowsBitmapImage* getImage (const bool transparent, const int w, const int h) throw() + const Image& getImage (const bool transparent, const int w, const int h) { const Image::PixelFormat format = transparent ? Image::ARGB : Image::RGB; - if (image == 0 || image->getWidth() < w || image->getHeight() < h || image->getFormat() != format) - image = new WindowsBitmapImage (format, (w + 31) & ~31, (h + 31) & ~31, false); + if ((! image.isValid()) || image.getWidth() < w || image.getHeight() < h || image.getFormat() != format) + image = Image (new WindowsBitmapImage (format, (w + 31) & ~31, (h + 31) & ~31, false)); startTimer (3000); return image; @@ -239010,11 +238941,11 @@ private: void timerCallback() { stopTimer(); - image = 0; + image = Image(); } private: - ScopedPointer image; + Image image; TemporaryImage (const TemporaryImage&); TemporaryImage& operator= (const TemporaryImage&); @@ -239261,7 +239192,7 @@ private: { clearMaskedRegion(); - WindowsBitmapImage* const offscreenImage = offscreenImageGenerator.getImage (transparent, w, h); + Image offscreenImage (offscreenImageGenerator.getImage (transparent, w, h)); RectangleList contextClip; const Rectangle clipBounds (0, 0, w, h); @@ -239322,7 +239253,7 @@ private: RectangleList::Iterator i (contextClip); while (i.next()) - offscreenImage->clear (*i.getRectangle()); + offscreenImage.clear (*i.getRectangle()); } // if the component's not opaque, this won't draw properly unless the platform can support this @@ -239330,11 +239261,12 @@ private: updateCurrentModifiers(); - LowLevelGraphicsSoftwareRenderer context (*offscreenImage, -x, -y, contextClip); + LowLevelGraphicsSoftwareRenderer context (offscreenImage, -x, -y, contextClip); handlePaint (context); if (! dontRepaint) - offscreenImage->blitToWindow (hwnd, dc, transparent, x, y, maskedRegion); + static_cast (offscreenImage.getSharedImage()) + ->blitToWindow (hwnd, dc, transparent, x, y, maskedRegion); } DeleteObject (rgn); @@ -240247,7 +240179,7 @@ void SystemTrayIconComponent::setIconImage (const Image& newImage) Win32ComponentPeer* const wp = dynamic_cast (getPeer()); if (wp != 0) - wp->setTaskBarIcon (&newImage); + wp->setTaskBarIcon (newImage); } void SystemTrayIconComponent::setIconTooltip (const String& tooltip) @@ -240322,9 +240254,9 @@ void Desktop::setMousePosition (const Point& newPosition) SetCursorPos (newPosition.getX(), newPosition.getY()); } -Image* Image::createNativeImage (const PixelFormat format, const int imageWidth, const int imageHeight, const bool clearImage) +Image::SharedImage* Image::SharedImage::createNativeImage (PixelFormat format, int width, int height, bool clearImage) { - return new Image (format, imageWidth, imageHeight, clearImage); + return createSoftwareImage (format, width, height, clearImage); } class ScreenSaverDefeater : public Timer, @@ -240441,9 +240373,9 @@ void juce_updateMultiMonitorInfo (Array >& monitorCoords, const } } -static Image* createImageFromHBITMAP (HBITMAP bitmap) throw() +static const Image createImageFromHBITMAP (HBITMAP bitmap) throw() { - Image* im = 0; + Image im; if (bitmap != 0) { @@ -240458,7 +240390,8 @@ static Image* createImageFromHBITMAP (HBITMAP bitmap) throw() SelectObject (dc, bitmap); - im = new Image (Image::ARGB, bm.bmWidth, bm.bmHeight, true); + im = Image (Image::ARGB, bm.bmWidth, bm.bmHeight, true); + Image::BitmapData imageData (im, 0, 0, bm.bmWidth, bm.bmHeight, true); for (int y = bm.bmHeight; --y >= 0;) { @@ -240466,9 +240399,9 @@ static Image* createImageFromHBITMAP (HBITMAP bitmap) throw() { COLORREF col = GetPixel (dc, x, y); - im->setPixelAt (x, y, Colour ((uint8) GetRValue (col), - (uint8) GetGValue (col), - (uint8) GetBValue (col))); + imageData.setPixelColour (x, y, Colour ((uint8) GetRValue (col), + (uint8) GetGValue (col), + (uint8) GetBValue (col))); } } @@ -240479,44 +240412,43 @@ static Image* createImageFromHBITMAP (HBITMAP bitmap) throw() return im; } -static Image* createImageFromHICON (HICON icon) throw() +static const Image createImageFromHICON (HICON icon) throw() { ICONINFO info; if (GetIconInfo (icon, &info)) { - ScopedPointer mask (createImageFromHBITMAP (info.hbmMask)); - if (mask == 0) - return 0; + Image mask (createImageFromHBITMAP (info.hbmMask)); + Image image (createImageFromHBITMAP (info.hbmColor)); - ScopedPointer image (createImageFromHBITMAP (info.hbmColor)); - if (image == 0) - return mask.release(); - - for (int y = image->getHeight(); --y >= 0;) + if (mask.isValid() && image.isValid()) { - for (int x = image->getWidth(); --x >= 0;) + for (int y = image.getHeight(); --y >= 0;) { - const float brightness = mask->getPixelAt (x, y).getBrightness(); + 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); + } } - } - return image.release(); + return image; + } } - return 0; + return Image(); } static HICON createHICONFromImage (const Image& image, const BOOL isIcon, int hotspotX, int hotspotY) throw() { - WindowsBitmapImage bitmap (Image::ARGB, image.getWidth(), image.getHeight(), true); + WindowsBitmapImage* nativeBitmap = new WindowsBitmapImage (Image::ARGB, image.getWidth(), image.getHeight(), true); + Image bitmap (nativeBitmap); { Graphics g (bitmap); - g.drawImageAt (&image, 0, 0); + g.drawImageAt (image, 0, 0); } HBITMAP mask = CreateBitmap (image.getWidth(), image.getHeight(), 1, 1, 0); @@ -240526,16 +240458,16 @@ static HICON createHICONFromImage (const Image& image, const BOOL isIcon, int ho info.xHotspot = hotspotX; info.yHotspot = hotspotY; info.hbmMask = mask; - info.hbmColor = bitmap.hBitmap; + info.hbmColor = nativeBitmap->hBitmap; HICON hi = CreateIconIndirect (&info); DeleteObject (mask); return hi; } -Image* juce_createIconForFile (const File& file) +const Image juce_createIconForFile (const File& file) { - Image* image = 0; + Image image; WCHAR filename [1024]; file.getFullPathName().copyToUnicode (filename, 1023); @@ -240558,18 +240490,17 @@ void* MouseCursor::createMouseCursorFromImage (const Image& image, int hotspotX, const int maxW = GetSystemMetrics (SM_CXCURSOR); const int maxH = GetSystemMetrics (SM_CYCURSOR); - const Image* im = ℑ - ScopedPointer newIm; + Image im (image); - if (image.getWidth() > maxW || image.getHeight() > maxH) + if (im.getWidth() > maxW || im.getHeight() > maxH) { - im = newIm = image.createCopy (maxW, maxH); + im = im.rescaled (maxW, maxH); hotspotX = (hotspotX * maxW) / image.getWidth(); hotspotY = (hotspotY * maxH) / image.getHeight(); } - return createHICONFromImage (*im, FALSE, hotspotX, hotspotY); + return createHICONFromImage (im, FALSE, hotspotX, hotspotY); } void MouseCursor::deleteMouseCursor (void* const cursorHandle, const bool isStandard) @@ -240619,8 +240550,7 @@ void* MouseCursor::createStandardMouseCursor (const MouseCursor::StandardCursorT 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 (dragHandData, sizeof (dragHandData))); - dragHandCursor = createMouseCursorFromImage (*image, 8, 7); + dragHandCursor = createMouseCursorFromImage (ImageFileFormat::loadFrom (dragHandData, sizeof (dragHandData)), 8, 7); } return dragHandCursor; @@ -250961,9 +250891,7 @@ public: width (0), height (0), activeUsers (0), - recordNextFrameTime (false), - activeImage (0), - loadingImage (0) + recordNextFrameTime (false) { HRESULT hr = graphBuilder.CoCreateInstance (CLSID_FilterGraph); if (FAILED (hr)) @@ -251053,8 +250981,8 @@ public: if (connectFilters (sampleGrabberBase, nullFilter) && addGraphToRot()) { - activeImage = new Image (Image::RGB, width, height, true); - loadingImage = new Image (Image::RGB, width, height, true); + activeImage = Image (Image::RGB, width, height, true); + loadingImage = Image (Image::RGB, width, height, true); ok = true; } @@ -251080,9 +251008,6 @@ public: smartTeePreviewOutputPin = 0; smartTeeCaptureOutputPin = 0; asfWriter = 0; - - delete activeImage; - delete loadingImage; } void addUser() @@ -251127,7 +251052,7 @@ public: const ScopedLock sl (imageSwapLock); { - const Image::BitmapData destData (*loadingImage, 0, 0, width, height, true); + const Image::BitmapData destData (loadingImage, 0, 0, width, height, true); for (int i = 0; i < height; ++i) memcpy (destData.getLinePointer ((height - 1) - i), @@ -251139,7 +251064,7 @@ public: } if (listeners.size() > 0) - callListeners (*loadingImage); + callListeners (loadingImage); sendChangeMessage (this); } @@ -251277,7 +251202,7 @@ public: removeUser(); } - void callListeners (Image& image) + void callListeners (const Image& image) { const ScopedLock sl (listenerLock); @@ -251362,8 +251287,8 @@ private: CriticalSection imageSwapLock; bool imageNeedsFlipping; - Image* loadingImage; - Image* activeImage; + Image loadingImage; + Image activeImage; bool recordNextFrameTime; @@ -253312,7 +253237,7 @@ int64 juce_getInternetFileContentLength (void* handle) return -1; } -bool juce_getInternetFileHeaders (void* handle, StringPairArray& headers) +void juce_getInternetFileHeaders (void* handle, StringPairArray& headers) { JUCE_HTTPSocketStream* const s = static_cast (handle); @@ -253444,44 +253369,43 @@ void PlatformUtilities::fpuReset() { } -uint32 juce_millisecondsSinceStartup() throw() +static bool juce_getTimeSinceStartup (timeval* const t) throw() { + if (gettimeofday (t, 0) != 0) + return false; + static unsigned int calibrate = 0; static bool calibrated = false; - timeval t; - unsigned int ret = 0; - if (! gettimeofday (&t, 0)) + if (! calibrated) { - if (! calibrated) - { - struct sysinfo sysi; + calibrated = true; - if (sysinfo (&sysi) == 0) - // Safe to assume system was not brought up earlier than 1970! - calibrate = t.tv_sec - sysi.uptime; - - calibrated = true; - } - - ret = 1000 * (t.tv_sec - calibrate) + (t.tv_usec / 1000); + struct sysinfo sysi; + if (sysinfo (&sysi) == 0) + calibrate = t->tv_sec - sysi.uptime; // Safe to assume system was not brought up earlier than 1970! } - return ret; + t->tv_sec -= calibrate; + return true; } -double Time::getMillisecondCounterHiRes() throw() +uint32 juce_millisecondsSinceStartup() throw() { - return getHighResolutionTicks() * 0.001; + timeval t; + if (juce_getTimeSinceStartup (&t)) + return (uint32) (t.tv_sec * 1000 + (t.tv_usec / 1000)); + + return 0; } int64 Time::getHighResolutionTicks() throw() { timeval t; - if (gettimeofday (&t, 0)) - return 0; + if (juce_getTimeSinceStartup (&t)) + return ((int64) t.tv_sec * (int64) 1000000) + (int64) t.tv_usec; - return ((int64) t.tv_sec * (int64) 1000000) + (int64) t.tv_usec; + return 0; } int64 Time::getHighResolutionTicksPerSecond() throw() @@ -253489,6 +253413,11 @@ int64 Time::getHighResolutionTicksPerSecond() throw() return 1000000; // (microseconds) } +double Time::getMillisecondCounterHiRes() throw() +{ + return getHighResolutionTicks() * 0.001; +} + bool Time::setSystemTimeToThisTime() const { timeval t; @@ -255335,19 +255264,19 @@ namespace Visuals } } -class XBitmapImage : public Image +class XBitmapImage : public Image::SharedImage { public: - XBitmapImage (const PixelFormat format_, const int w, const int h, + XBitmapImage (const Image::PixelFormat format_, const int w, const int h, const bool clearImage, const int imageDepth_, Visual* visual) - : Image (format_, w, h), + : Image::SharedImage (format_, w, h), imageDepth (imageDepth_), gc (None) { - jassert (format_ == RGB || format_ == ARGB); + jassert (format_ == Image::RGB || format_ == Image::ARGB); - pixelStride = (format_ == RGB) ? 3 : 4; + pixelStride = (format_ == Image::RGB) ? 3 : 4; lineStride = ((w * pixelStride + 3) & ~3); ScopedXLock xlock; @@ -255402,7 +255331,7 @@ public: imageDataAllocated.malloc (lineStride * h); imageData = imageDataAllocated; - if (format_ == ARGB && clearImage) + if (format_ == Image::ARGB && clearImage) zeromem (imageData, h * lineStride); xImage = (XImage*) juce_calloc (sizeof (XImage)); @@ -255470,6 +255399,19 @@ public: } } + Image::ImageType getType() const { return Image::NativeImage; } + + LowLevelGraphicsContext* createLowLevelContext() + { + return new LowLevelGraphicsSoftwareRenderer (Image (this)); + } + + SharedImage* clone() + { + jassertfalse; + return 0; + } + void blitToWindow (Window window, int dx, int dy, int dw, int dh, int sx, int sy) { ScopedXLock xlock; @@ -255501,7 +255443,7 @@ public: 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 (Image (this), 0, 0, width, height); for (int y = sy; y < sy + dh; ++y) { @@ -255534,6 +255476,7 @@ public: private: XImage* xImage; const int imageDepth; + HeapBlock imageDataAllocated; HeapBlock imageData16Bit; GC gc; @@ -256580,7 +256523,7 @@ public: void setTaskBarIcon (const Image& image) { ScopedXLock xlock; - taskbarImage = image.createCopy(); + taskbarImage = image; Screen* const screen = XDefaultScreenOfDisplay (display); const int screenNumber = XScreenNumberOfScreen (screen); @@ -256634,7 +256577,7 @@ public: XFree (hints); } - const Image* getTaskbarIcon() const throw() { return taskbarImage; } + const Image& getTaskbarIcon() const throw() { return taskbarImage; } juce_UseDebuggingNewOperator @@ -256690,7 +256633,7 @@ private: else if (Time::getApproximateMillisecondCounter() > lastTimeImageUsed + 3000) { stopTimer(); - image = 0; + image = Image(); } } @@ -256720,34 +256663,32 @@ private: if (! totalArea.isEmpty()) { - if (image == 0 || image->getWidth() < totalArea.getWidth() - || image->getHeight() < totalArea.getHeight()) + if (image.isNull() || image.getWidth() < totalArea.getWidth() + || image.getHeight() < totalArea.getHeight()) { #if JUCE_USE_XSHM - image = new XBitmapImage (useARGBImagesForRendering ? Image::ARGB - : Image::RGB, + image = Image (new XBitmapImage (useARGBImagesForRendering ? Image::ARGB + : Image::RGB, #else - image = new XBitmapImage (Image::RGB, + image = Image (new XBitmapImage (Image::RGB, #endif - (totalArea.getWidth() + 31) & ~31, - (totalArea.getHeight() + 31) & ~31, - false, - peer->depth, - peer->visual); + (totalArea.getWidth() + 31) & ~31, + (totalArea.getHeight() + 31) & ~31, + false, peer->depth, peer->visual)); } startTimer (repaintTimerPeriod); RectangleList adjustedList (originalRepaintRegion); adjustedList.offsetAll (-totalArea.getX(), -totalArea.getY()); - LowLevelGraphicsSoftwareRenderer context (*image, -totalArea.getX(), -totalArea.getY(), adjustedList); + LowLevelGraphicsSoftwareRenderer context (image, -totalArea.getX(), -totalArea.getY(), adjustedList); if (peer->depth == 32) { RectangleList::Iterator i (originalRepaintRegion); while (i.next()) - image->clear (*i.getRectangle() - totalArea.getPosition()); + image.clear (*i.getRectangle() - totalArea.getPosition()); } peer->handlePaint (context); @@ -256762,9 +256703,10 @@ private: #endif 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()); + static_cast (image.getSharedImage()) + ->blitToWindow (peer->windowH, + r.getX(), r.getY(), r.getWidth(), r.getHeight(), + r.getX() - totalArea.getX(), r.getY() - totalArea.getY()); } } @@ -256780,7 +256722,7 @@ private: enum { repaintTimerPeriod = 1000 / 100 }; LinuxComponentPeer* const peer; - ScopedPointer image; + Image image; uint32 lastTimeImageUsed; RectangleList regionsNeedingRepaint; @@ -256796,7 +256738,7 @@ private: friend class LinuxRepaintManager; Window windowH, parentWindow; int wx, wy, ww, wh; - ScopedPointer taskbarImage; + Image taskbarImage; bool fullScreen, mapped; Visual* visual; int depth; @@ -257859,6 +257801,7 @@ void* MouseCursor::createMouseCursorFromImage (const Image& image, int hotspotX, return 0; Image im (Image::ARGB, cursorW, cursorH, true); + { Graphics g (im); @@ -257867,13 +257810,13 @@ void* MouseCursor::createMouseCursorFromImage (const Image& image, int hotspotX, hotspotX = (hotspotX * cursorW) / imageW; hotspotY = (hotspotY * cursorH) / imageH; - g.drawImageWithin (&image, 0, 0, imageW, imageH, + g.drawImageWithin (image, 0, 0, imageW, imageH, RectanglePlacement::xLeft | RectanglePlacement::yTop | RectanglePlacement::onlyReduceInSize, false); } else { - g.drawImageAt (&image, 0, 0); + g.drawImageAt (image, 0, 0); } } @@ -257955,8 +257898,7 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty 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 (dragHandData, dragHandDataSize)); - return createMouseCursorFromImage (*im, 8, 7); + return createMouseCursorFromImage (ImageFileFormat::loadFrom (dragHandData, dragHandDataSize), 8, 7); } case CopyingCursor: @@ -257967,8 +257909,7 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty 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 (copyCursorData, copyCursorSize)); - return createMouseCursorFromImage (*im, 1, 3); + return createMouseCursorFromImage (ImageFileFormat::loadFrom (copyCursorData, copyCursorSize), 1, 3); } default: @@ -257994,14 +257935,14 @@ void MouseCursor::showInAllWindows() const showInWindow (ComponentPeer::getPeer (i)); } -Image* juce_createIconForFile (const File& file) +const Image juce_createIconForFile (const File& file) { - return 0; + return Image(); } -Image* Image::createNativeImage (const PixelFormat format, const int imageWidth, const int imageHeight, const bool clearImage) +Image::SharedImage* Image::SharedImage::createNativeImage (PixelFormat format, int width, int height, bool clearImage) { - return new Image (format, imageWidth, imageHeight, clearImage); + return createSoftwareImage (format, width, height, clearImage); } #if JUCE_OPENGL @@ -258224,14 +258165,9 @@ void SystemTrayIconComponent::paint (Graphics& g) 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); - } + g.drawImageWithin (wp->getTaskbarIcon(), 0, 0, getWidth(), getHeight(), + RectanglePlacement::xLeft | RectanglePlacement::yTop | RectanglePlacement::onlyReduceInSize, + false); } } @@ -261367,7 +261303,7 @@ int64 juce_getInternetFileContentLength (void* handle) return -1; } -bool juce_getInternetFileHeaders (void* handle, StringPairArray& headers) +void juce_getInternetFileHeaders (void* handle, StringPairArray& headers) { JuceURLConnection* const s = (JuceURLConnection*) handle; @@ -261379,11 +261315,7 @@ bool juce_getInternetFileHeaders (void* handle, StringPairArray& headers) while ((key = [enumerator nextObject]) != nil) headers.set (nsStringToJuce (key), nsStringToJuce ((NSString*) [s->headers objectForKey: key])); - - return true; } - - return false; } int juce_seekInInternetFile (void* handle, int /*newPosition*/) @@ -263675,21 +263607,24 @@ void Font::getPlatformDefaultFontNames (String& defaultSans, String& defaultSeri // compiled on its own). #if JUCE_INCLUDED_FILE -class CoreGraphicsImage : public Image +class CoreGraphicsImage : public Image::SharedImage { public: - CoreGraphicsImage (const PixelFormat format_, - const int imageWidth_, - const int imageHeight_, - const bool clearImage) - : Image (format_, imageWidth_, imageHeight_, clearImage) + CoreGraphicsImage (const Image::PixelFormat format_, const int width_, const int height_, const bool clearImage) + : Image::SharedImage (format_, width_, height_) { + pixelStride = format_ == Image::RGB ? 3 : ((format_ == Image::ARGB) ? 4 : 1); + lineStride = (pixelStride * jmax (1, width) + 3) & ~3; + + imageDataAllocated.allocate (lineStride * jmax (1, height), clearImage); + imageData = imageDataAllocated; + CGColorSpaceRef colourSpace = (format == Image::SingleChannel) ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB(); - context = CGBitmapContextCreate (imageData, imageWidth, imageHeight, 8, lineStride, - colourSpace, getCGImageFlags (*this)); + context = CGBitmapContextCreate (imageData, width, height, 8, lineStride, + colourSpace, getCGImageFlags (format_)); CGColorSpaceRelease (colourSpace); } @@ -263699,11 +263634,19 @@ public: CGContextRelease (context); } + Image::ImageType getType() const { return Image::NativeImage; } LowLevelGraphicsContext* createLowLevelContext(); + SharedImage* clone() + { + CoreGraphicsImage* im = new CoreGraphicsImage (format, width, height, false); + memcpy (im->imageData, imageData, lineStride * height); + return im; + } + static CGImageRef createImage (const Image& juceImage, const bool forAlpha, CGColorSpaceRef colourSpace) { - const CoreGraphicsImage* nativeImage = dynamic_cast (&juceImage); + const CoreGraphicsImage* nativeImage = dynamic_cast (juceImage.getSharedImage()); if (nativeImage != 0 && (juceImage.getFormat() == Image::SingleChannel || ! forAlpha)) { @@ -263717,7 +263660,7 @@ public: CGImageRef imageRef = CGImageCreate (srcData.width, srcData.height, 8, srcData.pixelStride * 8, srcData.lineStride, - colourSpace, getCGImageFlags (juceImage), provider, + colourSpace, getCGImageFlags (juceImage.getFormat()), provider, 0, true, kCGRenderingIntentDefault); CGDataProviderRelease (provider); @@ -263749,24 +263692,25 @@ public: #endif CGContextRef context; + HeapBlock imageDataAllocated; private: - static CGBitmapInfo getCGImageFlags (const Image& image) + static CGBitmapInfo getCGImageFlags (const Image::PixelFormat& format) { #if JUCE_BIG_ENDIAN - return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big) : kCGBitmapByteOrderDefault; + return format == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big) : kCGBitmapByteOrderDefault; #else - return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little) : kCGBitmapByteOrderDefault; + return format == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little) : kCGBitmapByteOrderDefault; #endif } }; -Image* Image::createNativeImage (const PixelFormat format, const int imageWidth, const int imageHeight, const bool clearImage) +Image::SharedImage* Image::SharedImage::createNativeImage (PixelFormat format, int width, int height, bool clearImage) { #if USE_COREGRAPHICS_RENDERING - return new CoreGraphicsImage (format == RGB ? ARGB : format, imageWidth, imageHeight, clearImage); + return new CoreGraphicsImage (format == RGB ? ARGB : format, width, height, clearImage); #else - return new Image (format, imageWidth, imageHeight, clearImage); + return createSoftwareImage (format, width, height, clearImage); #endif } @@ -263853,16 +263797,12 @@ public: { if (! transform.isSingularity()) { - ScopedPointer imageToDelete; - const Image* singleChannelImage = &sourceImage; + Image singleChannelImage (sourceImage); if (sourceImage.getFormat() != Image::SingleChannel) - { - imageToDelete = sourceImage.createCopyOfAlphaChannel(); - singleChannelImage = imageToDelete; - } + singleChannelImage = sourceImage.convertedToFormat (Image::SingleChannel); - CGImageRef image = CoreGraphicsImage::createImage (*singleChannelImage, true, greyColourSpace); + CGImageRef image = CoreGraphicsImage::createImage (singleChannelImage, true, greyColourSpace); flip(); AffineTransform t (AffineTransform::scale (1.0f, -1.0f).translated (0, sourceImage.getHeight()).followedBy (transform)); @@ -263983,7 +263923,7 @@ public: { CGContextSaveGState (context); CGContextClipToRect (context, cgRect); - drawImage (*(state->fillType.image), state->fillType.image->getBounds(), state->fillType.transform, true); + drawImage (state->fillType.image, state->fillType.image.getBounds(), state->fillType.transform, true); CGContextRestoreGState (context); } } @@ -264016,7 +263956,7 @@ public: if (state->fillType.isGradient()) drawGradient(); else - drawImage (*(state->fillType.image), state->fillType.image->getBounds(), state->fillType.transform, true); + drawImage (state->fillType.image, state->fillType.image.getBounds(), state->fillType.transform, true); } CGContextRestoreGState (context); @@ -264356,7 +264296,7 @@ private: LowLevelGraphicsContext* CoreGraphicsImage::createLowLevelContext() { - return new CoreGraphicsContext (context, imageHeight); + return new CoreGraphicsContext (context, height); } #endif @@ -265192,9 +265132,9 @@ ComponentPeer* Component::createNewPeer (int styleFlags, void* windowToAttachTo) return new UIViewComponentPeer (this, styleFlags, (UIView*) windowToAttachTo); } -Image* juce_createIconForFile (const File& file) +const Image juce_createIconForFile (const File& file) { - return 0; + return Image(); } void Desktop::createMouseInputSources() @@ -266148,10 +266088,10 @@ namespace MouseCursorHelpers BufferedInputStream buf (&fileStream, 4096, false); PNGImageFormat pngFormat; - const ScopedPointer im (pngFormat.decodeImage (buf)); + Image im (pngFormat.decodeImage (buf)); - if (im != 0) - return createFromImage (*im, hx * im->getWidth(), hy * im->getHeight()); + if (im.isValid()) + return createFromImage (im, hx * im.getWidth(), hy * im.getHeight()); jassertfalse; return 0; @@ -268280,21 +268220,24 @@ void Font::getPlatformDefaultFontNames (String& defaultSans, String& defaultSeri // compiled on its own). #if JUCE_INCLUDED_FILE -class CoreGraphicsImage : public Image +class CoreGraphicsImage : public Image::SharedImage { public: - CoreGraphicsImage (const PixelFormat format_, - const int imageWidth_, - const int imageHeight_, - const bool clearImage) - : Image (format_, imageWidth_, imageHeight_, clearImage) + CoreGraphicsImage (const Image::PixelFormat format_, const int width_, const int height_, const bool clearImage) + : Image::SharedImage (format_, width_, height_) { + pixelStride = format_ == Image::RGB ? 3 : ((format_ == Image::ARGB) ? 4 : 1); + lineStride = (pixelStride * jmax (1, width) + 3) & ~3; + + imageDataAllocated.allocate (lineStride * jmax (1, height), clearImage); + imageData = imageDataAllocated; + CGColorSpaceRef colourSpace = (format == Image::SingleChannel) ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB(); - context = CGBitmapContextCreate (imageData, imageWidth, imageHeight, 8, lineStride, - colourSpace, getCGImageFlags (*this)); + context = CGBitmapContextCreate (imageData, width, height, 8, lineStride, + colourSpace, getCGImageFlags (format_)); CGColorSpaceRelease (colourSpace); } @@ -268304,11 +268247,19 @@ public: CGContextRelease (context); } + Image::ImageType getType() const { return Image::NativeImage; } LowLevelGraphicsContext* createLowLevelContext(); + SharedImage* clone() + { + CoreGraphicsImage* im = new CoreGraphicsImage (format, width, height, false); + memcpy (im->imageData, imageData, lineStride * height); + return im; + } + static CGImageRef createImage (const Image& juceImage, const bool forAlpha, CGColorSpaceRef colourSpace) { - const CoreGraphicsImage* nativeImage = dynamic_cast (&juceImage); + const CoreGraphicsImage* nativeImage = dynamic_cast (juceImage.getSharedImage()); if (nativeImage != 0 && (juceImage.getFormat() == Image::SingleChannel || ! forAlpha)) { @@ -268322,7 +268273,7 @@ public: CGImageRef imageRef = CGImageCreate (srcData.width, srcData.height, 8, srcData.pixelStride * 8, srcData.lineStride, - colourSpace, getCGImageFlags (juceImage), provider, + colourSpace, getCGImageFlags (juceImage.getFormat()), provider, 0, true, kCGRenderingIntentDefault); CGDataProviderRelease (provider); @@ -268354,24 +268305,25 @@ public: #endif CGContextRef context; + HeapBlock imageDataAllocated; private: - static CGBitmapInfo getCGImageFlags (const Image& image) + static CGBitmapInfo getCGImageFlags (const Image::PixelFormat& format) { #if JUCE_BIG_ENDIAN - return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big) : kCGBitmapByteOrderDefault; + return format == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big) : kCGBitmapByteOrderDefault; #else - return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little) : kCGBitmapByteOrderDefault; + return format == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little) : kCGBitmapByteOrderDefault; #endif } }; -Image* Image::createNativeImage (const PixelFormat format, const int imageWidth, const int imageHeight, const bool clearImage) +Image::SharedImage* Image::SharedImage::createNativeImage (PixelFormat format, int width, int height, bool clearImage) { #if USE_COREGRAPHICS_RENDERING - return new CoreGraphicsImage (format == RGB ? ARGB : format, imageWidth, imageHeight, clearImage); + return new CoreGraphicsImage (format == RGB ? ARGB : format, width, height, clearImage); #else - return new Image (format, imageWidth, imageHeight, clearImage); + return createSoftwareImage (format, width, height, clearImage); #endif } @@ -268458,16 +268410,12 @@ public: { if (! transform.isSingularity()) { - ScopedPointer imageToDelete; - const Image* singleChannelImage = &sourceImage; + Image singleChannelImage (sourceImage); if (sourceImage.getFormat() != Image::SingleChannel) - { - imageToDelete = sourceImage.createCopyOfAlphaChannel(); - singleChannelImage = imageToDelete; - } + singleChannelImage = sourceImage.convertedToFormat (Image::SingleChannel); - CGImageRef image = CoreGraphicsImage::createImage (*singleChannelImage, true, greyColourSpace); + CGImageRef image = CoreGraphicsImage::createImage (singleChannelImage, true, greyColourSpace); flip(); AffineTransform t (AffineTransform::scale (1.0f, -1.0f).translated (0, sourceImage.getHeight()).followedBy (transform)); @@ -268588,7 +268536,7 @@ public: { CGContextSaveGState (context); CGContextClipToRect (context, cgRect); - drawImage (*(state->fillType.image), state->fillType.image->getBounds(), state->fillType.transform, true); + drawImage (state->fillType.image, state->fillType.image.getBounds(), state->fillType.transform, true); CGContextRestoreGState (context); } } @@ -268621,7 +268569,7 @@ public: if (state->fillType.isGradient()) drawGradient(); else - drawImage (*(state->fillType.image), state->fillType.image->getBounds(), state->fillType.transform, true); + drawImage (state->fillType.image, state->fillType.image.getBounds(), state->fillType.transform, true); } CGContextRestoreGState (context); @@ -268961,7 +268909,7 @@ private: LowLevelGraphicsContext* CoreGraphicsImage::createLowLevelContext() { - return new CoreGraphicsContext (context, imageHeight); + return new CoreGraphicsContext (context, height); } #endif @@ -270578,7 +270526,7 @@ ComponentPeer* Component::createNewPeer (int styleFlags, void* windowToAttachTo) return new NSViewComponentPeer (this, styleFlags, (NSView*) windowToAttachTo); } -Image* juce_createIconForFile (const File& file) +const Image juce_createIconForFile (const File& file) { const ScopedAutoReleasePool pool; @@ -270596,7 +270544,7 @@ Image* juce_createIconForFile (const File& file) [[NSGraphicsContext currentContext] flushGraphics]; [NSGraphicsContext restoreGraphicsState]; - return result; + return Image (result); } const int KeyPress::spaceKey = ' '; @@ -270681,10 +270629,10 @@ namespace MouseCursorHelpers BufferedInputStream buf (&fileStream, 4096, false); PNGImageFormat pngFormat; - const ScopedPointer im (pngFormat.decodeImage (buf)); + Image im (pngFormat.decodeImage (buf)); - if (im != 0) - return createFromImage (*im, hx * im->getWidth(), hy * im->getHeight()); + if (im.isValid()) + return createFromImage (im, hx * im.getWidth(), hy * im.getHeight()); jassertfalse; return 0; @@ -276305,10 +276253,12 @@ public: void callListeners (CIImage* frame, int w, int h) { - CoreGraphicsImage image (Image::ARGB, w, h, false); - CIContext* cic = [CIContext contextWithCGContext: image.context options: nil]; + CoreGraphicsImage* cgImage = new CoreGraphicsImage (Image::ARGB, w, h, false); + Image image (cgImage); + + CIContext* cic = [CIContext contextWithCGContext: cgImage->context options: nil]; [cic drawImage: frame inRect: CGRectMake (0, 0, w, h) fromRect: CGRectMake (0, 0, w, h)]; - CGContextFlush (image.context); + CGContextFlush (cgImage->context); const ScopedLock sl (listenerLock); diff --git a/juce_amalgamated.h b/juce_amalgamated.h index e12f209efa..127c72522a 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -4692,6 +4692,68 @@ typedef BigInteger BitArray; #ifndef __JUCE_IDENTIFIER_JUCEHEADER__ #define __JUCE_IDENTIFIER_JUCEHEADER__ + +/*** Start of inlined file: juce_StringPool.h ***/ +#ifndef __JUCE_STRINGPOOL_JUCEHEADER__ +#define __JUCE_STRINGPOOL_JUCEHEADER__ + +/** + A StringPool holds a set of shared strings, which reduces storage overheads and improves + comparison speed when dealing with many duplicate strings. + + When you add a string to a pool using getPooledString, it'll return a character + array containing the same string. This array is owned by the pool, and the same array + is returned every time a matching string is asked for. This means that it's trivial to + compare two pooled strings for equality, as you can simply compare their pointers. It + also cuts down on storage if you're using many copies of the same string. +*/ +class JUCE_API StringPool +{ +public: + + /** Creates an empty pool. */ + StringPool() throw(); + + /** Destructor */ + ~StringPool(); + + /** Returns a pointer to a copy of the string that is passed in. + + The pool will always return the same pointer when asked for a string that matches it. + The pool will own all the pointers that it returns, deleting them when the pool itself + is deleted. + */ + const juce_wchar* getPooledString (const String& original); + + /** Returns a pointer to a copy of the string that is passed in. + + The pool will always return the same pointer when asked for a string that matches it. + The pool will own all the pointers that it returns, deleting them when the pool itself + is deleted. + */ + const juce_wchar* getPooledString (const char* original); + + /** Returns a pointer to a copy of the string that is passed in. + + The pool will always return the same pointer when asked for a string that matches it. + The pool will own all the pointers that it returns, deleting them when the pool itself + is deleted. + */ + const juce_wchar* getPooledString (const juce_wchar* original); + + /** Returns the number of strings in the pool. */ + int size() const throw(); + + /** Returns one of the strings in the pool, by index. */ + const juce_wchar* operator[] (int index) const throw(); + +private: + Array strings; +}; + +#endif // __JUCE_STRINGPOOL_JUCEHEADER__ +/*** End of inlined file: juce_StringPool.h ***/ + /** Represents a string identifier, designed for accessing properties by name. @@ -4744,7 +4806,7 @@ private: const juce_wchar* name; - class Pool; + static StringPool pool; }; #endif // __JUCE_IDENTIFIER_JUCEHEADER__ @@ -14859,6 +14921,9 @@ public: /** Destructor. */ ~RSAKey(); + bool operator== (const RSAKey& other) const throw(); + bool operator!= (const RSAKey& other) const throw(); + /** Turns the key into a string representation. This can be reloaded using the constructor that takes a string. @@ -16867,68 +16932,6 @@ private: #endif #ifndef __JUCE_STRINGPOOL_JUCEHEADER__ -/*** Start of inlined file: juce_StringPool.h ***/ -#ifndef __JUCE_STRINGPOOL_JUCEHEADER__ -#define __JUCE_STRINGPOOL_JUCEHEADER__ - -/** - A StringPool holds a set of shared strings, which reduces storage overheads and improves - comparison speed when dealing with many duplicate strings. - - When you add a string to a pool using getPooledString, it'll return a character - array containing the same string. This array is owned by the pool, and the same array - is returned every time a matching string is asked for. This means that it's trivial to - compare two pooled strings for equality, as you can simply compare their pointers. It - also cuts down on storage if you're using many copies of the same string. -*/ -class JUCE_API StringPool -{ -public: - - /** Creates an empty pool. */ - StringPool() throw(); - - /** Destructor */ - ~StringPool(); - - /** Returns a pointer to a copy of the string that is passed in. - - The pool will always return the same pointer when asked for a string that matches it. - The pool will own all the pointers that it returns, deleting them when the pool itself - is deleted. - */ - const juce_wchar* getPooledString (const String& original); - - /** Returns a pointer to a copy of the string that is passed in. - - The pool will always return the same pointer when asked for a string that matches it. - The pool will own all the pointers that it returns, deleting them when the pool itself - is deleted. - */ - const juce_wchar* getPooledString (const char* original); - - /** Returns a pointer to a copy of the string that is passed in. - - The pool will always return the same pointer when asked for a string that matches it. - The pool will own all the pointers that it returns, deleting them when the pool itself - is deleted. - */ - const juce_wchar* getPooledString (const juce_wchar* original); - - /** Returns the number of strings in the pool. */ - int size() const throw(); - - /** Returns one of the strings in the pool, by index. */ - const juce_wchar* operator[] (int index) const throw(); - -private: - Array strings; -}; - -#endif // __JUCE_STRINGPOOL_JUCEHEADER__ -/*** End of inlined file: juce_StringPool.h ***/ - - #endif #ifndef __JUCE_XMLDOCUMENT_JUCEHEADER__ @@ -23125,11 +23128,6 @@ private: /*** End of inlined file: juce_Colours.h ***/ -/*** Start of inlined file: juce_FillType.h ***/ -#ifndef __JUCE_FILLTYPE_JUCEHEADER__ -#define __JUCE_FILLTYPE_JUCEHEADER__ - - /*** Start of inlined file: juce_ColourGradient.h ***/ #ifndef __JUCE_COLOURGRADIENT_JUCEHEADER__ #define __JUCE_COLOURGRADIENT_JUCEHEADER__ @@ -23273,117 +23271,6 @@ private: #endif // __JUCE_COLOURGRADIENT_JUCEHEADER__ /*** End of inlined file: juce_ColourGradient.h ***/ -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(); - - /** Creates a fill type of a solid colour. - @see setColour - */ - FillType (const Colour& colour) throw(); - - /** Creates a gradient fill type. - @see setGradient - */ - FillType (const ColourGradient& gradient); - - /** 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(); - - /** Creates a copy of another FillType. */ - FillType (const FillType& other); - - /** Makes a copy of another FillType. */ - FillType& operator= (const FillType& other); - - /** Destructor. */ - ~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; } - - /** Returns true if this is a gradient fill. */ - bool isGradient() const throw() { return gradient != 0; } - - /** Returns true if this is a tiled image pattern fill. */ - 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(); - - /** Turns this object into a gradient fill. */ - void setGradient (const ColourGradient& newGradient); - - /** 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(); - - /** 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 (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(); } - - /** Returns true if this fill type is completely transparent. */ - bool isInvisible() const throw(); - - bool operator== (const FillType& other) const; - bool operator!= (const FillType& other) const; - - /** The solid colour being used. - - 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; - - /** 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; - - /** 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; - - /** The transform that should be applied to the image or gradient that's being drawn. - */ - AffineTransform transform; - - juce_UseDebuggingNewOperator -}; - -#endif // __JUCE_FILLTYPE_JUCEHEADER__ -/*** End of inlined file: juce_FillType.h ***/ - /*** Start of inlined file: juce_RectanglePlacement.h ***/ #ifndef __JUCE_RECTANGLEPLACEMENT_JUCEHEADER__ @@ -23513,6 +23400,7 @@ private: class LowLevelGraphicsContext; class Image; +class FillType; class RectangleList; /** @@ -23540,7 +23428,7 @@ public: Obviously you shouldn't delete the image before this context is deleted. */ - explicit Graphics (Image& imageToDrawOnto); + explicit Graphics (const Image& imageToDrawOnto); /** Destructor. */ ~Graphics(); @@ -23929,7 +23817,7 @@ public: 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, int topLeftX, int topLeftY, + void drawImageAt (const Image& imageToDraw, int topLeftX, int topLeftY, bool fillAlphaChannelWithCurrentBrush = false) const; /** Draws part of an image, rescaling it to fit in a given target region. @@ -23957,7 +23845,7 @@ public: it will just fill the target with a solid rectangle) @see setImageResamplingQuality, drawImageAt, drawImageWithin, fillAlphaMap */ - void drawImage (const Image* const imageToDraw, + void drawImage (const Image& imageToDraw, int destX, int destY, int destWidth, int destHeight, int sourceX, int sourceY, int sourceWidth, int sourceHeight, bool fillAlphaChannelWithCurrentBrush = false) const; @@ -23983,7 +23871,7 @@ public: @see setImageResamplingQuality, drawImage */ - void drawImageTransformed (const Image* imageToDraw, + void drawImageTransformed (const Image& imageToDraw, const Rectangle& imageSubRegion, const AffineTransform& transform, bool fillAlphaChannelWithCurrentBrush = false) const; @@ -24009,7 +23897,7 @@ public: similar to fillAlphaMap(), and see also drawImage() @see setImageResamplingQuality, drawImage, drawImageTransformed, drawImageAt, RectanglePlacement */ - void drawImageWithin (const Image* imageToDraw, + void drawImageWithin (const Image& imageToDraw, int destX, int destY, int destWidth, int destHeight, const RectanglePlacement& placementWithinTarget, bool fillAlphaChannelWithCurrentBrush = false) const; @@ -24162,6 +24050,355 @@ public: /*** End of inlined file: juce_ImageEffectFilter.h ***/ +/*** Start of inlined file: juce_Image.h ***/ +#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 + { + UnknownFormat, + 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 ImageType + { + SoftwareImage = 0, + NativeImage + }; + + /** Creates a null image. */ + Image(); + + /** Creates an image with a specified size and format. + + @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 (if it's RGB) + or transparent black (if it's ARGB). If false, the image may contain + junk initially, so you need to make sure you overwrite it thoroughly. + @param type the type of image - this lets you specify whether you want a purely + memory-based image, or one that may be managed by the OS if possible. + */ + Image (PixelFormat format, + int imageWidth, + int imageHeight, + bool clearImage, + ImageType type = NativeImage); + + /** Creates a shared reference to another image. + + This won't create a duplicate of the image - when Image objects are copied, they simply + point to the same shared image data. To make sure that an Image object has its own unique, + unshared internal data, call duplicateIfShared(). + */ + Image (const Image& other); + + /** Makes this image refer to the same underlying image as another object. + + This won't create a duplicate of the image - when Image objects are copied, they simply + point to the same shared image data. To make sure that an Image object has its own unique, + unshared internal data, call duplicateIfShared(). + */ + Image& operator= (const Image&); + + /** Destructor. */ + ~Image(); + + /** Returns true if the two images are referring to the same internal, shared image. */ + bool operator== (const Image& other) const throw() { return image == other.image; } + + /** Returns true if the two images are not referring to the same internal, shared image. */ + bool operator!= (const Image& other) const throw() { return image != other.image; } + + /** Returns true if this image isn't null. + If you create an Image with the default constructor, it has no size or content, and is null + until you reassign it to an Image which contains some actual data. + The isNull() method is the opposite of isValid(). + @see isNull + */ + inline bool isValid() const throw() { return image != 0; } + + /** Returns true if this image is not valid. + If you create an Image with the default constructor, it has no size or content, and is null + until you reassign it to an Image which contains some actual data. + The isNull() method is the opposite of isValid(). + @see isValid + */ + inline bool isNull() const throw() { return image == 0; } + + /** Returns the image's width (in pixels). */ + int getWidth() const throw() { return image == 0 ? 0 : image->width; } + + /** Returns the image's height (in pixels). */ + int getHeight() const throw() { return image == 0 ? 0 : image->height; } + + /** Returns a rectangle with the same size as this image. + The rectangle's origin is always (0, 0). + */ + const Rectangle getBounds() const throw() { return image == 0 ? Rectangle() : Rectangle (0, 0, image->width, image->height); } + + /** Returns the image's pixel format. */ + PixelFormat getFormat() const throw() { return image == 0 ? UnknownFormat : image->format; } + + /** True if the image's format is ARGB. */ + bool isARGB() const throw() { return getFormat() == ARGB; } + + /** True if the image's format is RGB. */ + bool isRGB() const throw() { return getFormat() == RGB; } + + /** True if the image contains an alpha-channel. */ + bool hasAlphaChannel() const throw() { return getFormat() != RGB; } + + /** Clears a section of the image with a given 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). + */ + void clear (const Rectangle& area, const Colour& colourToClearTo = Colour (0x00000000)); + + /** Returns a rescaled version of this image. + + A new image is returned which is a copy of this one, rescaled to the given size. + + Note that if the new size is identical to the existing image, this will just return + a reference to the original image, and won't actually create a duplicate. + */ + const Image rescaled (int newWidth, int newHeight, + Graphics::ResamplingQuality quality = Graphics::mediumResamplingQuality) const; + + /** Returns a version of this image with a different image format. + + A new image is returned which has been converted to the specified format. + + Note that if the new format is no different to the current one, this will just return + a reference to the original image, and won't actually create a copy. + */ + const Image convertedToFormat (PixelFormat newFormat) const; + + /** Makes sure that no other Image objects share the same underlying data as this one. + + If no other Image objects refer to the same shared data as this one, this method has no + effect. But if there are other references to the data, this will create a new copy of + the data internally. + + Call this if you want to draw onto the image, but want to make sure that this doesn't + affect any other code that may be sharing the same data. + */ + void duplicateIfShared(); + + /** Returns the colour of one of the pixels in the image. + + If the co-ordinates given are beyond the image's boundaries, this will + return Colours::transparentBlack. + + @see setPixelAt, Image::BitmapData::getPixelColour + */ + const Colour getPixelAt (int x, int y) const; + + /** Sets the colour of one of the image's pixels. + + If the co-ordinates are beyond the image's boundaries, then nothing will happen. + + Note that 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. + + @see getPixelAt, Image::BitmapData::setPixelColour + */ + void setPixelAt (int x, 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 setPixelAt + */ + void multiplyAlphaAt (int x, int y, 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. + */ + void multiplyAllAlphas (float amountToMultiplyBy); + + /** Changes all the colours to be shades of grey, based on their current luminosity. + */ + 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, 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 (int y) const throw() { 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 (int x, int y) const throw() { return data + y * lineStride + x * pixelStride; } + + /** Returns the colour of a given pixel. + For performance reasons, this won't do any bounds-checking on the coordinates, so it's the caller's + repsonsibility to make sure they're within the image's size. + */ + const Colour getPixelColour (int x, int y) const throw(); + + /** Sets the colour of a given pixel. + For performance reasons, this won't do any bounds-checking on the coordinates, so it's the caller's + repsonsibility to make sure they're within the image's size. + */ + void setPixelColour (int x, int y, const Colour& colour) const throw(); + + uint8* data; + const PixelFormat pixelFormat; + int lineStride, pixelStride, width, height; + + private: + BitmapData (const BitmapData&); + 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. + */ + 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. */ + 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, + float alphaThreshold = 0.5f) const; + + /** Creates a context suitable for drawing onto this image. + Don't call this method directly! It's used internally by the Graphics class. + */ + LowLevelGraphicsContext* createLowLevelContext() const; + + /** + */ + class SharedImage : public ReferenceCountedObject + { + public: + SharedImage (PixelFormat format, int width, int height); + ~SharedImage(); + + virtual LowLevelGraphicsContext* createLowLevelContext() = 0; + virtual SharedImage* clone() = 0; + virtual ImageType getType() const = 0; + + static SharedImage* createNativeImage (PixelFormat format, int width, int height, bool clearImage); + static SharedImage* createSoftwareImage (PixelFormat format, int width, int height, bool clearImage); + + protected: + friend class Image; + friend class Image::BitmapData; + const PixelFormat format; + const int width, height; + int pixelStride, lineStride; + uint8* imageData; + + uint8* getPixelData (int x, int y) const throw(); + + SharedImage (const SharedImage&); + SharedImage& operator= (const SharedImage&); + }; + + /** @internal */ + SharedImage* getSharedImage() const throw() { return image; } + + /** @internal */ + explicit Image (SharedImage* instance); + + /** @internal */ + int getReferenceCount() const throw() { return image->getReferenceCount(); } + + juce_UseDebuggingNewOperator + +private: + ReferenceCountedObjectPtr image; +}; + +#endif // __JUCE_IMAGE_JUCEHEADER__ +/*** End of inlined file: juce_Image.h ***/ + + /*** Start of inlined file: juce_RectangleList.h ***/ #ifndef __JUCE_RECTANGLELIST_JUCEHEADER__ #define __JUCE_RECTANGLELIST_JUCEHEADER__ @@ -25280,12 +25517,10 @@ public: 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, - bool clipImageToComponentBounds = true); + const Image createComponentSnapshot (const Rectangle& areaToGrab, + bool clipImageToComponentBounds = true); /** Draws this component and all its subcomponents onto the specified graphics context. @@ -26399,7 +26634,7 @@ private: LookAndFeel* lookAndFeel_; MouseCursor cursor_; ImageEffectFilter* effect_; - Image* bufferedImage_; + Image bufferedImage_; Array * mouseListeners_; Array * keyListeners_; ListenerList componentListeners; @@ -34373,7 +34608,7 @@ public: const String& itemText, bool isActive = true, bool isTicked = false, - const Image* iconToUse = 0); + const Image& iconToUse = Image()); /** Adds an item that represents one of the commands in a command manager object. @@ -34398,7 +34633,7 @@ public: const Colour& itemTextColour, bool isActive = true, bool isTicked = false, - const Image* iconToUse = 0); + const Image& iconToUse = Image()); /** Appends a custom menu item. @@ -34436,7 +34671,7 @@ public: void addSubMenu (const String& subMenuName, const PopupMenu& subMenu, bool isActive = true, - Image* iconToUse = 0, + const Image& iconToUse = Image(), bool isTicked = false); /** Appends a separator to the menu, to help break it up into sections. @@ -34602,7 +34837,7 @@ public: bool isCustomComponent; bool isSectionHeader; const Colour* customColour; - const Image* customImage; + Image customImage; ApplicationCommandManager* commandManager; juce_UseDebuggingNewOperator @@ -39382,7 +39617,7 @@ public: @see Component::createComponentSnapshot */ - Image* createSnapshotOfSelectedRows (int& x, int& y); + const Image createSnapshotOfSelectedRows (int& x, int& y); /** Returns the viewport that this ListBox uses. @@ -42271,7 +42506,7 @@ public: bool containsAnyDynamicPoints() const; /** Writes the path to this drawable encoding. */ - void writeTo (ValueTree state, UndoManager* undoManager); + void writeTo (ValueTree state, UndoManager* undoManager) const; /** Quickly swaps the contents of this path with another. */ void swapWith (RelativePointPath& other) throw(); @@ -42560,13 +42795,13 @@ public: The image that is returned will be owned by the caller, but it may come from the ImageCache. */ - virtual Image* getImageForIdentifier (const var& imageIdentifier) = 0; + virtual const Image getImageForIdentifier (const var& imageIdentifier) = 0; /** Returns an identifier to be used to refer to a given image. This is used when converting a drawable into a ValueTree, so if you're only loading drawables, you can just return a var::null here. */ - virtual const var getIdentifierForImage (Image* image) = 0; + virtual const var getIdentifierForImage (const Image& image) = 0; }; /** Tries to create a Drawable from a previously-saved ValueTree. @@ -42899,10 +43134,6 @@ public: /** Sets up the images to draw in various states. - 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! - @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 @@ -42911,9 +43142,7 @@ public: 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 + @param normalImage the image to use when the button is in its normal state. 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 @@ -42923,19 +43152,15 @@ public: 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 + parameter, this value can be a null image. @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 + to a null image, the 'over' image will be drawn instead (or the + normal image if there isn't an 'over' image either). @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 @@ -42951,33 +43176,33 @@ public: void setImages (bool resizeButtonNowToFitThisImage, bool rescaleImagesWhenButtonSizeChanges, bool preserveImageProportions, - Image* normalImage, + const Image& normalImage, float imageOpacityWhenNormal, const Colour& overlayColourWhenNormal, - Image* overImage, + const Image& overImage, float imageOpacityWhenOver, const Colour& overlayColourWhenOver, - Image* downImage, + const Image& downImage, float imageOpacityWhenDown, const Colour& overlayColourWhenDown, float hitTestAlphaThreshold = 0.0f); /** Returns the currently set 'normal' image. */ - Image* getNormalImage() const throw(); + const Image getNormalImage() const; /** 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 + If a valid 'over' image has been set, this will return it; otherwise it'll just return the normal image. */ - Image* getOverImage() const throw(); + const Image getOverImage() const; /** 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 + If a valid '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(); + const Image getDownImage() const; juce_UseDebuggingNewOperator @@ -42994,14 +43219,11 @@ private: bool scaleImageToFit, preserveProportions; unsigned char alphaThreshold; int imageX, imageY, imageW, imageH; - Image* normalImage; - Image* overImage; - Image* downImage; + Image normalImage, overImage, downImage; float normalOpacity, overOpacity, downOpacity; Colour normalOverlay, overOverlay, downOverlay; - Image* getCurrentImage() const; - void deleteImages(); + const Image getCurrentImage() const; ImageButton (const ImageButton&); ImageButton& operator= (const ImageButton&); @@ -43349,10 +43571,8 @@ public: 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 dragImage the image to drag around underneath the mouse. If this is a null image, + a snapshot of the sourceComponent will be used instead. @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. @@ -43363,7 +43583,7 @@ public: */ void startDragging (const String& sourceDescription, Component* sourceComponent, - Image* dragImage = 0, + const Image& dragImage = Image(), bool allowDraggingToOtherJuceWindows = false, const Point* imageOffsetFromMouse = 0); @@ -47455,275 +47675,6 @@ protected: #endif // __JUCE_FILEFILTER_JUCEHEADER__ /*** End of inlined file: juce_FileFilter.h ***/ - -/*** Start of inlined file: juce_Image.h ***/ -#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. */ - }; - - /** Creates an in-memory image with a specified size and format. - - To create an image that can use native OS rendering methods, see createNativeImage(). - - @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 (PixelFormat format, - int imageWidth, - int imageHeight, - bool clearImage); - - /** Creates a copy of another image. - - @see createCopy - */ - Image (const Image& other); - - /** Destructor. */ - virtual ~Image(); - - /** Tries to create an image that is uses native drawing methods when you render - onto it. - - On some platforms this will just return a normal software-based image. - */ - static Image* createNativeImage (PixelFormat format, - int imageWidth, - int imageHeight, - bool clearImage); - - /** Returns the image's width (in pixels). */ - int getWidth() const throw() { return imageWidth; } - - /** Returns the image's height (in pixels). */ - int getHeight() const throw() { return imageHeight; } - - /** 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); } - - /** Returns the image's pixel format. */ - PixelFormat getFormat() const throw() { return format; } - - /** True if the image's format is ARGB. */ - bool isARGB() const throw() { return format == ARGB; } - - /** True if the image's format is RGB. */ - bool isRGB() const throw() { return format == RGB; } - - /** True if the image contains an alpha-channel. */ - bool hasAlphaChannel() const throw() { return format != RGB; } - - /** Clears a section of the image with a given 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 (const Rectangle& area, const Colour& colourToClearTo = Colour (0x00000000)); - - /** Returns a new image that's a copy of this one. - - 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. - - It's up to the caller to delete the image when no longer needed. - */ - virtual Image* createCopy (int newWidth = -1, - int newHeight = -1, - Graphics::ResamplingQuality quality = Graphics::mediumResamplingQuality) const; - - /** Returns a new single-channel image which is a copy of the alpha-channel of this image. - */ - virtual Image* createCopyOfAlphaChannel() const; - - /** Returns the colour of one of the pixels in the image. - - If the co-ordinates given are beyond the image's boundaries, this will - return Colours::transparentBlack. - - (0, 0) is the image's top-left corner. - - @see getAlphaAt, setPixelAt, blendPixelAt - */ - virtual const Colour getPixelAt (int x, int y) const; - - /** Sets the colour of one of the image's pixels. - - If the co-ordinates are beyond the image's boundaries, then nothing will - happen. - - 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. - - (0, 0) is the image's top-left corner. - - @see blendPixelAt - */ - virtual void setPixelAt (int x, 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 (int x, int y, 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 (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, 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 (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 (int x, int y) const { return data + y * lineStride + x * pixelStride; } - - uint8* data; - const PixelFormat pixelFormat; - int lineStride, pixelStride, width, height; - - private: - BitmapData (const BitmapData&); - 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, - 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(); - -protected: - 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 (PixelFormat format, - int imageWidth, - int imageHeight); - - int pixelStride, lineStride; - HeapBlock imageDataAllocated; - uint8* imageData; - -private: - - 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. @@ -48504,13 +48455,13 @@ private: Component* owner; int numShadows; Component* shadowWindows[4]; - Image* shadowImageSections[12]; + Image shadowImageSections[12]; const int shadowEdge, xOffset, yOffset; const float alpha, blurRadius; bool inDestructor, reentrant; void updateShadows(); - void setShadowImage (Image* const src, + void setShadowImage (const Image& src, const int num, const int w, const int h, const int sx, const int sy); @@ -50323,7 +50274,7 @@ public: private: File fileToLoad; - ScopedPointer currentThumbnail; + Image currentThumbnail; String currentDetails; void getThumbSize (int& w, int& h) const; @@ -51722,7 +51673,7 @@ public: image after calling this. If 0 is passed-in, any existing icon will be removed. */ - void setIcon (const Image* imageToUse); + void setIcon (const Image& imageToUse); /** Changes the height of the title-bar. */ void setTitleBarHeight (int newHeight); @@ -51851,7 +51802,7 @@ private: int titleBarHeight, menuBarHeight, requiredButtons; bool positionTitleBarButtonsOnLeft, drawTitleTextCentred; ScopedPointer