diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index e80d7a47b7..88afcb242f 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -4908,7 +4908,7 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_Expression.cpp ***/ BEGIN_JUCE_NAMESPACE -class Expression::Term : public ReferenceCountedObject +class Expression::Term : public SingleThreadedReferenceCountedObject { public: Term() {} @@ -22501,7 +22501,11 @@ AudioThumbnail::~AudioThumbnail() void AudioThumbnail::clear() { source = nullptr; + clearChannelData(); +} +void AudioThumbnail::clearChannelData() +{ const ScopedLock sl (lock); window->invalidate(); channels.clear(); @@ -22531,7 +22535,7 @@ void AudioThumbnail::createChannels (const int length) void AudioThumbnail::loadFrom (InputStream& rawInput) { - clear(); + clearChannelData(); BufferedInputStream input (rawInput, 4096); @@ -86247,7 +86251,7 @@ private: JUCE_DECLARE_NON_COPYABLE (TransformedImageFillEdgeTableRenderer); }; -class ClipRegionBase : public ReferenceCountedObject +class ClipRegionBase : public SingleThreadedReferenceCountedObject { public: ClipRegionBase() {} @@ -91982,33 +91986,40 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_GlyphArrangement.cpp ***/ BEGIN_JUCE_NAMESPACE -PositionedGlyph::PositionedGlyph (const float x_, const float y_, const float w_, const Font& font_, - const juce_wchar character_, const int glyph_) - : x (x_), - y (y_), - w (w_), - font (font_), - character (character_), - glyph (glyph_) +PositionedGlyph::PositionedGlyph (const Font& font_, const juce_wchar character_, const int glyph_, + const float x_, const float y_, const float w_, const bool whitespace_) + : font (font_), character (character_), glyph (glyph_), + x (x_), y (y_), w (w_), whitespace (whitespace_) { } PositionedGlyph::PositionedGlyph (const PositionedGlyph& other) - : x (other.x), - y (other.y), - w (other.w), - font (other.font), - character (other.character), - glyph (other.glyph) + : font (other.font), character (other.character), glyph (other.glyph), + x (other.x), y (other.y), w (other.w), whitespace (other.whitespace) { } +PositionedGlyph::~PositionedGlyph() {} + +PositionedGlyph& PositionedGlyph::operator= (const PositionedGlyph& other) +{ + font = other.font; + character = other.character; + glyph = other.glyph; + x = other.x; + y = other.y; + w = other.w; + whitespace = other.whitespace; + return *this; +} + void PositionedGlyph::draw (const Graphics& g) const { if (! isWhitespace()) { - g.getInternalContext()->setFont (font); - g.getInternalContext()->drawGlyph (glyph, AffineTransform::translation (x, y)); + LowLevelGraphicsContext* const context = g.getInternalContext(); + context->setFont (font); + context->drawGlyph (glyph, AffineTransform::translation (x, y)); } } @@ -92017,9 +92028,10 @@ void PositionedGlyph::draw (const Graphics& g, { if (! isWhitespace()) { - g.getInternalContext()->setFont (font); - g.getInternalContext()->drawGlyph (glyph, AffineTransform::translation (x, y) - .followedBy (transform)); + LowLevelGraphicsContext* const context = g.getInternalContext(); + context->setFont (font); + context->drawGlyph (glyph, AffineTransform::translation (x, y) + .followedBy (transform)); } } @@ -92112,6 +92124,11 @@ void GlyphArrangement::addGlyphArrangement (const GlyphArrangement& other) glyphs.addCopiesOf (other.glyphs); } +void GlyphArrangement::addGlyph (const PositionedGlyph& glyph) +{ + glyphs.add (new PositionedGlyph (glyph)); +} + void GlyphArrangement::removeRangeOfGlyphs (int startIndex, const int num) { glyphs.removeRange (startIndex, num < 0 ? glyphs.size() : num); @@ -92129,7 +92146,7 @@ void GlyphArrangement::addLineOfText (const Font& font, void GlyphArrangement::addCurtailedLineOfText (const Font& font, const String& text, - float xOffset, + const float xOffset, const float yOffset, const float maxWidthPixels, const bool useEllipsis) @@ -92140,6 +92157,7 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font, Array xOffsets; font.getGlyphPositions (text, newGlyphs, xOffsets); const int textLen = newGlyphs.size(); + glyphs.ensureStorageAllocated (glyphs.size() + textLen); String::CharPointerType t (text.getCharPointer()); @@ -92158,8 +92176,12 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font, } else { - glyphs.add (new PositionedGlyph (xOffset + thisX, yOffset, nextX - thisX, - font, t.getAndAdvance(), newGlyphs.getUnchecked(i))); + const bool isWhitespace = t.isWhitespace(); + + glyphs.add (new PositionedGlyph (font, t.getAndAdvance(), + newGlyphs.getUnchecked(i), + xOffset + thisX, yOffset, + nextX - thisX, isWhitespace)); } } } @@ -92194,8 +92216,8 @@ int GlyphArrangement::insertEllipsis (const Font& font, const float maxXPos, for (int i = 3; --i >= 0;) { - glyphs.insert (endIndex++, new PositionedGlyph (xOffset, yOffset, dx, - font, '.', dotGlyphs.getFirst())); + glyphs.insert (endIndex++, new PositionedGlyph (font, '.', dotGlyphs.getFirst(), + xOffset, yOffset, dx, false)); --numDeleted; xOffset += dx; diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 04b3a3b992..287d3dab45 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -7412,6 +7412,24 @@ public: } } + /** This will enlarge or shrink the array to the given number of elements, by adding + or removing items from its end. + + If the array is smaller than the given target size, empty elements will be appended + until its size is as specified. If its size is larger than the target, items will be + removed from its end to shorten it. + */ + void resize (const int targetNumItems) + { + jassert (targetNumItems >= 0); + + const int numToAdd = targetNumItems - numUsed; + if (numToAdd > 0) + insertMultiple (numUsed, ElementType(), numToAdd); + else if (numToAdd < 0) + removeRange (targetNumItems, -numToAdd); + } + /** Inserts a new element into the array, assuming that the array is sorted. This will use a comparator to find the position at which the new element @@ -9059,7 +9077,11 @@ private: Once a new ReferenceCountedObject has been assigned to a pointer, be careful not to delete the object manually. - @see ReferenceCountedObjectPtr, ReferenceCountedArray + This class uses an Atomic value to hold the reference count, so that it + the pointers can be passed between threads safely. For a faster but non-thread-safe + version, use SingleThreadedReferenceCountedObject instead. + + @see ReferenceCountedObjectPtr, ReferenceCountedArray, SingleThreadedReferenceCountedObject */ class JUCE_API ReferenceCountedObject { @@ -9088,10 +9110,7 @@ public: } /** Returns the object's current reference count. */ - inline int getReferenceCount() const noexcept - { - return refCount.get(); - } + inline int getReferenceCount() const noexcept { return refCount.get(); } protected: @@ -9112,6 +9131,62 @@ private: Atomic refCount; }; +/** + Adds reference-counting to an object. + + This is efectively a version of the ReferenceCountedObject class, but which + uses a non-atomic counter, and so is not thread-safe (but which will be more + efficient). + For more details on how to use it, see the ReferenceCountedObject class notes. + + @see ReferenceCountedObject, ReferenceCountedObjectPtr, ReferenceCountedArray +*/ +class JUCE_API SingleThreadedReferenceCountedObject +{ +public: + + /** Increments the object's reference count. + + This is done automatically by the smart pointer, but is public just + in case it's needed for nefarious purposes. + */ + inline void incReferenceCount() noexcept + { + ++refCount; + } + + /** Decreases the object's reference count. + + If the count gets to zero, the object will be deleted. + */ + inline void decReferenceCount() noexcept + { + jassert (getReferenceCount() > 0); + + if (--refCount == 0) + delete this; + } + + /** Returns the object's current reference count. */ + inline int getReferenceCount() const noexcept { return refCount; } + +protected: + + /** Creates the reference-counted object (with an initial ref count of zero). */ + SingleThreadedReferenceCountedObject() : refCount (0) {} + + /** Destructor. */ + virtual ~SingleThreadedReferenceCountedObject() + { + // it's dangerous to delete an object that's still referenced by something else! + jassert (getReferenceCount() == 0); + } + +private: + + int refCount; +}; + /** A smart-pointer class which points to a reference-counted object. @@ -16262,7 +16337,7 @@ public: of a ValueSource object. If you're feeling adventurous, you can create your own custom ValueSource classes to allow Value objects to represent your own custom data items. */ - class JUCE_API ValueSource : public ReferenceCountedObject, + class JUCE_API ValueSource : public SingleThreadedReferenceCountedObject, public AsyncUpdater { public: @@ -17147,14 +17222,11 @@ public: private: - class SetPropertyAction; - friend class SetPropertyAction; - class AddOrRemoveChildAction; - friend class AddOrRemoveChildAction; - class MoveChildAction; - friend class MoveChildAction; + class SetPropertyAction; friend class SetPropertyAction; + class AddOrRemoveChildAction; friend class AddOrRemoveChildAction; + class MoveChildAction; friend class MoveChildAction; - class JUCE_API SharedObject : public ReferenceCountedObject + class JUCE_API SharedObject : public SingleThreadedReferenceCountedObject { public: explicit SharedObject (const Identifier& type); @@ -21560,7 +21632,7 @@ private: @see WeakReference::Master */ -template +template class WeakReference { public: @@ -21607,7 +21679,7 @@ public: in your code! @see WeakReference */ - class SharedPointer : public ReferenceCountedObject + class SharedPointer : public ReferenceCountingType { public: explicit SharedPointer (ObjectType* const owner_) noexcept : owner (owner_) {} @@ -24999,7 +25071,7 @@ class AffineTransform; @see CustomTypeface, Font */ -class JUCE_API Typeface : public ReferenceCountedObject +class JUCE_API Typeface : public SingleThreadedReferenceCountedObject { public: @@ -25403,7 +25475,7 @@ private: friend class FontGlyphAlphaMap; friend class TypefaceCache; - class SharedFontInternal : public ReferenceCountedObject + class SharedFontInternal : public SingleThreadedReferenceCountedObject { public: SharedFontInternal (float height, int styleFlags) noexcept; @@ -37453,6 +37525,7 @@ private: double sampleRate; CriticalSection lock; + void clearChannelData(); bool setDataSource (LevelDataSource* newSource); void setLevels (const MinMaxValue* const* values, int thumbIndex, int numChans, int numValues); void createChannels (int length); @@ -44045,7 +44118,7 @@ public: @see PopupMenu::addCustomItem */ class JUCE_API CustomComponent : public Component, - public ReferenceCountedObject + public SingleThreadedReferenceCountedObject { public: /** Creates a custom item. @@ -57363,25 +57436,33 @@ private: A glyph from a particular font, with a particular size, style, typeface and position. + You should rarely need to use this class directly - for most purposes, the + GlyphArrangement class will do what you need for text layout. + @see GlyphArrangement, Font */ class JUCE_API PositionedGlyph { public: + PositionedGlyph (const Font& font, juce_wchar character, int glyphNumber, + float anchorX, float baselineY, float width, bool isWhitespace); + PositionedGlyph (const PositionedGlyph& other); + PositionedGlyph& operator= (const PositionedGlyph& other); + ~PositionedGlyph(); /** Returns the character the glyph represents. */ - juce_wchar getCharacter() const { return character; } + juce_wchar getCharacter() const noexcept { return character; } /** Checks whether the glyph is actually empty. */ - bool isWhitespace() const { return CharacterFunctions::isWhitespace (character); } + bool isWhitespace() const noexcept { return whitespace; } /** Returns the position of the glyph's left-hand edge. */ - float getLeft() const { return x; } + float getLeft() const noexcept { return x; } /** Returns the position of the glyph's right-hand edge. */ - float getRight() const { return x + w; } + float getRight() const noexcept { return x + w; } /** Returns the y position of the glyph's baseline. */ - float getBaselineY() const { return y; } + float getBaselineY() const noexcept { return y; } /** Returns the y position of the top of the glyph. */ float getTop() const { return y - font.getAscent(); } /** Returns the y position of the bottom of the glyph. */ @@ -57410,12 +57491,12 @@ public: private: friend class GlyphArrangement; - float x, y, w; Font font; juce_wchar character; int glyph; + float x, y, w; + bool whitespace; - PositionedGlyph (float x, float y, float w, const Font& font, juce_wchar character, int glyph); JUCE_LEAK_DETECTOR (PositionedGlyph); }; @@ -57439,7 +57520,6 @@ public: GlyphArrangement (const GlyphArrangement& other); /** Copies another arrangement onto this one. - To add another arrangement without clearing this one, use addGlyphArrangement(). */ GlyphArrangement& operator= (const GlyphArrangement& other); @@ -57530,6 +57610,9 @@ public: /** Appends another glyph arrangement to this one. */ void addGlyphArrangement (const GlyphArrangement& other); + /** Appends a custom glyph to the arrangement. */ + void addGlyph (const PositionedGlyph& glyph); + /** Draws this glyph arrangement to a graphics context. This uses cached bitmaps so is much faster than the draw (Graphics&, const AffineTransform&) @@ -57611,9 +57694,9 @@ private: OwnedArray glyphs; - int insertEllipsis (const Font& font, float maxXPos, int startIndex, int endIndex); - int fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font& font, - const Justification& justification, float minimumHorizontalScale); + int insertEllipsis (const Font&, float maxXPos, int startIndex, int endIndex); + int fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font&, + const Justification&, float minimumHorizontalScale); void spreadOutLine (int start, int numGlyphs, float targetWidth); JUCE_LEAK_DETECTOR (GlyphArrangement); diff --git a/src/audio/audio_file_formats/juce_AudioThumbnail.cpp b/src/audio/audio_file_formats/juce_AudioThumbnail.cpp index b6dc660ab7..be1bd9f36b 100644 --- a/src/audio/audio_file_formats/juce_AudioThumbnail.cpp +++ b/src/audio/audio_file_formats/juce_AudioThumbnail.cpp @@ -541,7 +541,11 @@ AudioThumbnail::~AudioThumbnail() void AudioThumbnail::clear() { source = nullptr; + clearChannelData(); +} +void AudioThumbnail::clearChannelData() +{ const ScopedLock sl (lock); window->invalidate(); channels.clear(); @@ -572,7 +576,7 @@ void AudioThumbnail::createChannels (const int length) //============================================================================== void AudioThumbnail::loadFrom (InputStream& rawInput) { - clear(); + clearChannelData(); BufferedInputStream input (rawInput, 4096); diff --git a/src/audio/audio_file_formats/juce_AudioThumbnail.h b/src/audio/audio_file_formats/juce_AudioThumbnail.h index f9f84ccd22..99c70f899c 100644 --- a/src/audio/audio_file_formats/juce_AudioThumbnail.h +++ b/src/audio/audio_file_formats/juce_AudioThumbnail.h @@ -227,6 +227,7 @@ private: double sampleRate; CriticalSection lock; + void clearChannelData(); bool setDataSource (LevelDataSource* newSource); void setLevels (const MinMaxValue* const* values, int thumbIndex, int numChans, int numValues); void createChannels (int length); diff --git a/src/containers/juce_Array.h b/src/containers/juce_Array.h index 195638972b..e20e0e76a3 100644 --- a/src/containers/juce_Array.h +++ b/src/containers/juce_Array.h @@ -594,6 +594,24 @@ public: } } + /** This will enlarge or shrink the array to the given number of elements, by adding + or removing items from its end. + + If the array is smaller than the given target size, empty elements will be appended + until its size is as specified. If its size is larger than the target, items will be + removed from its end to shorten it. + */ + void resize (const int targetNumItems) + { + jassert (targetNumItems >= 0); + + const int numToAdd = targetNumItems - numUsed; + if (numToAdd > 0) + insertMultiple (numUsed, ElementType(), numToAdd); + else if (numToAdd < 0) + removeRange (targetNumItems, -numToAdd); + } + /** Inserts a new element into the array, assuming that the array is sorted. This will use a comparator to find the position at which the new element diff --git a/src/containers/juce_Value.h b/src/containers/juce_Value.h index b06f37bc54..232d69899a 100644 --- a/src/containers/juce_Value.h +++ b/src/containers/juce_Value.h @@ -170,7 +170,7 @@ public: of a ValueSource object. If you're feeling adventurous, you can create your own custom ValueSource classes to allow Value objects to represent your own custom data items. */ - class JUCE_API ValueSource : public ReferenceCountedObject, + class JUCE_API ValueSource : public SingleThreadedReferenceCountedObject, public AsyncUpdater { public: diff --git a/src/containers/juce_ValueTree.h b/src/containers/juce_ValueTree.h index 3ba66cc677..017133c5b2 100644 --- a/src/containers/juce_ValueTree.h +++ b/src/containers/juce_ValueTree.h @@ -466,14 +466,11 @@ public: private: //============================================================================== - class SetPropertyAction; - friend class SetPropertyAction; - class AddOrRemoveChildAction; - friend class AddOrRemoveChildAction; - class MoveChildAction; - friend class MoveChildAction; + class SetPropertyAction; friend class SetPropertyAction; + class AddOrRemoveChildAction; friend class AddOrRemoveChildAction; + class MoveChildAction; friend class MoveChildAction; - class JUCE_API SharedObject : public ReferenceCountedObject + class JUCE_API SharedObject : public SingleThreadedReferenceCountedObject { public: explicit SharedObject (const Identifier& type); diff --git a/src/gui/components/menus/juce_PopupMenu.h b/src/gui/components/menus/juce_PopupMenu.h index 550557fa1d..e7c4b40d46 100644 --- a/src/gui/components/menus/juce_PopupMenu.h +++ b/src/gui/components/menus/juce_PopupMenu.h @@ -415,7 +415,7 @@ public: @see PopupMenu::addCustomItem */ class JUCE_API CustomComponent : public Component, - public ReferenceCountedObject + public SingleThreadedReferenceCountedObject { public: /** Creates a custom item. diff --git a/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp b/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp index 93bc506bb1..c33adea508 100644 --- a/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp +++ b/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp @@ -1018,7 +1018,7 @@ private: }; //============================================================================== -class ClipRegionBase : public ReferenceCountedObject +class ClipRegionBase : public SingleThreadedReferenceCountedObject { public: ClipRegionBase() {} diff --git a/src/gui/graphics/fonts/juce_Font.h b/src/gui/graphics/fonts/juce_Font.h index 07d01f2fa0..6604b65d94 100644 --- a/src/gui/graphics/fonts/juce_Font.h +++ b/src/gui/graphics/fonts/juce_Font.h @@ -364,7 +364,7 @@ private: friend class FontGlyphAlphaMap; friend class TypefaceCache; - class SharedFontInternal : public ReferenceCountedObject + class SharedFontInternal : public SingleThreadedReferenceCountedObject { public: SharedFontInternal (float height, int styleFlags) noexcept; diff --git a/src/gui/graphics/fonts/juce_GlyphArrangement.cpp b/src/gui/graphics/fonts/juce_GlyphArrangement.cpp index 2b4171bfc1..077c8882d1 100644 --- a/src/gui/graphics/fonts/juce_GlyphArrangement.cpp +++ b/src/gui/graphics/fonts/juce_GlyphArrangement.cpp @@ -34,33 +34,40 @@ BEGIN_JUCE_NAMESPACE //============================================================================== -PositionedGlyph::PositionedGlyph (const float x_, const float y_, const float w_, const Font& font_, - const juce_wchar character_, const int glyph_) - : x (x_), - y (y_), - w (w_), - font (font_), - character (character_), - glyph (glyph_) +PositionedGlyph::PositionedGlyph (const Font& font_, const juce_wchar character_, const int glyph_, + const float x_, const float y_, const float w_, const bool whitespace_) + : font (font_), character (character_), glyph (glyph_), + x (x_), y (y_), w (w_), whitespace (whitespace_) { } PositionedGlyph::PositionedGlyph (const PositionedGlyph& other) - : x (other.x), - y (other.y), - w (other.w), - font (other.font), - character (other.character), - glyph (other.glyph) + : font (other.font), character (other.character), glyph (other.glyph), + x (other.x), y (other.y), w (other.w), whitespace (other.whitespace) { } +PositionedGlyph::~PositionedGlyph() {} + +PositionedGlyph& PositionedGlyph::operator= (const PositionedGlyph& other) +{ + font = other.font; + character = other.character; + glyph = other.glyph; + x = other.x; + y = other.y; + w = other.w; + whitespace = other.whitespace; + return *this; +} + void PositionedGlyph::draw (const Graphics& g) const { if (! isWhitespace()) { - g.getInternalContext()->setFont (font); - g.getInternalContext()->drawGlyph (glyph, AffineTransform::translation (x, y)); + LowLevelGraphicsContext* const context = g.getInternalContext(); + context->setFont (font); + context->drawGlyph (glyph, AffineTransform::translation (x, y)); } } @@ -69,9 +76,10 @@ void PositionedGlyph::draw (const Graphics& g, { if (! isWhitespace()) { - g.getInternalContext()->setFont (font); - g.getInternalContext()->drawGlyph (glyph, AffineTransform::translation (x, y) - .followedBy (transform)); + LowLevelGraphicsContext* const context = g.getInternalContext(); + context->setFont (font); + context->drawGlyph (glyph, AffineTransform::translation (x, y) + .followedBy (transform)); } } @@ -168,6 +176,11 @@ void GlyphArrangement::addGlyphArrangement (const GlyphArrangement& other) glyphs.addCopiesOf (other.glyphs); } +void GlyphArrangement::addGlyph (const PositionedGlyph& glyph) +{ + glyphs.add (new PositionedGlyph (glyph)); +} + void GlyphArrangement::removeRangeOfGlyphs (int startIndex, const int num) { glyphs.removeRange (startIndex, num < 0 ? glyphs.size() : num); @@ -186,7 +199,7 @@ void GlyphArrangement::addLineOfText (const Font& font, void GlyphArrangement::addCurtailedLineOfText (const Font& font, const String& text, - float xOffset, + const float xOffset, const float yOffset, const float maxWidthPixels, const bool useEllipsis) @@ -197,6 +210,7 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font, Array xOffsets; font.getGlyphPositions (text, newGlyphs, xOffsets); const int textLen = newGlyphs.size(); + glyphs.ensureStorageAllocated (glyphs.size() + textLen); String::CharPointerType t (text.getCharPointer()); @@ -215,8 +229,12 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font, } else { - glyphs.add (new PositionedGlyph (xOffset + thisX, yOffset, nextX - thisX, - font, t.getAndAdvance(), newGlyphs.getUnchecked(i))); + const bool isWhitespace = t.isWhitespace(); + + glyphs.add (new PositionedGlyph (font, t.getAndAdvance(), + newGlyphs.getUnchecked(i), + xOffset + thisX, yOffset, + nextX - thisX, isWhitespace)); } } } @@ -251,8 +269,8 @@ int GlyphArrangement::insertEllipsis (const Font& font, const float maxXPos, for (int i = 3; --i >= 0;) { - glyphs.insert (endIndex++, new PositionedGlyph (xOffset, yOffset, dx, - font, '.', dotGlyphs.getFirst())); + glyphs.insert (endIndex++, new PositionedGlyph (font, '.', dotGlyphs.getFirst(), + xOffset, yOffset, dx, false)); --numDeleted; xOffset += dx; diff --git a/src/gui/graphics/fonts/juce_GlyphArrangement.h b/src/gui/graphics/fonts/juce_GlyphArrangement.h index d72b353030..197e68a04e 100644 --- a/src/gui/graphics/fonts/juce_GlyphArrangement.h +++ b/src/gui/graphics/fonts/juce_GlyphArrangement.h @@ -35,25 +35,33 @@ A glyph from a particular font, with a particular size, style, typeface and position. + You should rarely need to use this class directly - for most purposes, the + GlyphArrangement class will do what you need for text layout. + @see GlyphArrangement, Font */ class JUCE_API PositionedGlyph { public: //============================================================================== + PositionedGlyph (const Font& font, juce_wchar character, int glyphNumber, + float anchorX, float baselineY, float width, bool isWhitespace); + PositionedGlyph (const PositionedGlyph& other); + PositionedGlyph& operator= (const PositionedGlyph& other); + ~PositionedGlyph(); /** Returns the character the glyph represents. */ - juce_wchar getCharacter() const { return character; } + juce_wchar getCharacter() const noexcept { return character; } /** Checks whether the glyph is actually empty. */ - bool isWhitespace() const { return CharacterFunctions::isWhitespace (character); } + bool isWhitespace() const noexcept { return whitespace; } /** Returns the position of the glyph's left-hand edge. */ - float getLeft() const { return x; } + float getLeft() const noexcept { return x; } /** Returns the position of the glyph's right-hand edge. */ - float getRight() const { return x + w; } + float getRight() const noexcept { return x + w; } /** Returns the y position of the glyph's baseline. */ - float getBaselineY() const { return y; } + float getBaselineY() const noexcept { return y; } /** Returns the y position of the top of the glyph. */ float getTop() const { return y - font.getAscent(); } /** Returns the y position of the bottom of the glyph. */ @@ -84,12 +92,12 @@ public: private: //============================================================================== friend class GlyphArrangement; - float x, y, w; Font font; juce_wchar character; int glyph; + float x, y, w; + bool whitespace; - PositionedGlyph (float x, float y, float w, const Font& font, juce_wchar character, int glyph); JUCE_LEAK_DETECTOR (PositionedGlyph); }; @@ -115,7 +123,6 @@ public: GlyphArrangement (const GlyphArrangement& other); /** Copies another arrangement onto this one. - To add another arrangement without clearing this one, use addGlyphArrangement(). */ GlyphArrangement& operator= (const GlyphArrangement& other); @@ -208,6 +215,9 @@ public: /** Appends another glyph arrangement to this one. */ void addGlyphArrangement (const GlyphArrangement& other); + /** Appends a custom glyph to the arrangement. */ + void addGlyph (const PositionedGlyph& glyph); + //============================================================================== /** Draws this glyph arrangement to a graphics context. @@ -293,9 +303,9 @@ private: //============================================================================== OwnedArray glyphs; - int insertEllipsis (const Font& font, float maxXPos, int startIndex, int endIndex); - int fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font& font, - const Justification& justification, float minimumHorizontalScale); + int insertEllipsis (const Font&, float maxXPos, int startIndex, int endIndex); + int fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font&, + const Justification&, float minimumHorizontalScale); void spreadOutLine (int start, int numGlyphs, float targetWidth); JUCE_LEAK_DETECTOR (GlyphArrangement); diff --git a/src/gui/graphics/fonts/juce_Typeface.h b/src/gui/graphics/fonts/juce_Typeface.h index 489cbc98f6..eab11448cb 100644 --- a/src/gui/graphics/fonts/juce_Typeface.h +++ b/src/gui/graphics/fonts/juce_Typeface.h @@ -49,7 +49,7 @@ class AffineTransform; @see CustomTypeface, Font */ -class JUCE_API Typeface : public ReferenceCountedObject +class JUCE_API Typeface : public SingleThreadedReferenceCountedObject { public: //============================================================================== diff --git a/src/maths/juce_Expression.cpp b/src/maths/juce_Expression.cpp index 7d6c7cd38e..cb0e2c7d53 100644 --- a/src/maths/juce_Expression.cpp +++ b/src/maths/juce_Expression.cpp @@ -32,7 +32,7 @@ BEGIN_JUCE_NAMESPACE //============================================================================== -class Expression::Term : public ReferenceCountedObject +class Expression::Term : public SingleThreadedReferenceCountedObject { public: Term() {} diff --git a/src/memory/juce_ReferenceCountedObject.h b/src/memory/juce_ReferenceCountedObject.h index 1a3a6f09bf..e4f2f03e9f 100644 --- a/src/memory/juce_ReferenceCountedObject.h +++ b/src/memory/juce_ReferenceCountedObject.h @@ -55,7 +55,11 @@ Once a new ReferenceCountedObject has been assigned to a pointer, be careful not to delete the object manually. - @see ReferenceCountedObjectPtr, ReferenceCountedArray + This class uses an Atomic value to hold the reference count, so that it + the pointers can be passed between threads safely. For a faster but non-thread-safe + version, use SingleThreadedReferenceCountedObject instead. + + @see ReferenceCountedObjectPtr, ReferenceCountedArray, SingleThreadedReferenceCountedObject */ class JUCE_API ReferenceCountedObject { @@ -84,10 +88,7 @@ public: } /** Returns the object's current reference count. */ - inline int getReferenceCount() const noexcept - { - return refCount.get(); - } + inline int getReferenceCount() const noexcept { return refCount.get(); } protected: @@ -110,6 +111,64 @@ private: }; +//============================================================================== +/** + Adds reference-counting to an object. + + This is efectively a version of the ReferenceCountedObject class, but which + uses a non-atomic counter, and so is not thread-safe (but which will be more + efficient). + For more details on how to use it, see the ReferenceCountedObject class notes. + + @see ReferenceCountedObject, ReferenceCountedObjectPtr, ReferenceCountedArray +*/ +class JUCE_API SingleThreadedReferenceCountedObject +{ +public: + //============================================================================== + /** Increments the object's reference count. + + This is done automatically by the smart pointer, but is public just + in case it's needed for nefarious purposes. + */ + inline void incReferenceCount() noexcept + { + ++refCount; + } + + /** Decreases the object's reference count. + + If the count gets to zero, the object will be deleted. + */ + inline void decReferenceCount() noexcept + { + jassert (getReferenceCount() > 0); + + if (--refCount == 0) + delete this; + } + + /** Returns the object's current reference count. */ + inline int getReferenceCount() const noexcept { return refCount; } + + +protected: + //============================================================================== + /** Creates the reference-counted object (with an initial ref count of zero). */ + SingleThreadedReferenceCountedObject() : refCount (0) {} + + /** Destructor. */ + virtual ~SingleThreadedReferenceCountedObject() + { + // it's dangerous to delete an object that's still referenced by something else! + jassert (getReferenceCount() == 0); + } + +private: + //============================================================================== + int refCount; +}; + //============================================================================== /** diff --git a/src/memory/juce_WeakReference.h b/src/memory/juce_WeakReference.h index 74751b4f2c..afed7b0746 100644 --- a/src/memory/juce_WeakReference.h +++ b/src/memory/juce_WeakReference.h @@ -81,7 +81,7 @@ @see WeakReference::Master */ -template +template class WeakReference { public: @@ -129,7 +129,7 @@ public: in your code! @see WeakReference */ - class SharedPointer : public ReferenceCountedObject + class SharedPointer : public ReferenceCountingType { public: explicit SharedPointer (ObjectType* const owner_) noexcept : owner (owner_) {}