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