| @@ -4908,7 +4908,7 @@ END_JUCE_NAMESPACE | |||||
| /*** Start of inlined file: juce_Expression.cpp ***/ | /*** Start of inlined file: juce_Expression.cpp ***/ | ||||
| BEGIN_JUCE_NAMESPACE | BEGIN_JUCE_NAMESPACE | ||||
| class Expression::Term : public ReferenceCountedObject | |||||
| class Expression::Term : public SingleThreadedReferenceCountedObject | |||||
| { | { | ||||
| public: | public: | ||||
| Term() {} | Term() {} | ||||
| @@ -22501,7 +22501,11 @@ AudioThumbnail::~AudioThumbnail() | |||||
| void AudioThumbnail::clear() | void AudioThumbnail::clear() | ||||
| { | { | ||||
| source = nullptr; | source = nullptr; | ||||
| clearChannelData(); | |||||
| } | |||||
| void AudioThumbnail::clearChannelData() | |||||
| { | |||||
| const ScopedLock sl (lock); | const ScopedLock sl (lock); | ||||
| window->invalidate(); | window->invalidate(); | ||||
| channels.clear(); | channels.clear(); | ||||
| @@ -22531,7 +22535,7 @@ void AudioThumbnail::createChannels (const int length) | |||||
| void AudioThumbnail::loadFrom (InputStream& rawInput) | void AudioThumbnail::loadFrom (InputStream& rawInput) | ||||
| { | { | ||||
| clear(); | |||||
| clearChannelData(); | |||||
| BufferedInputStream input (rawInput, 4096); | BufferedInputStream input (rawInput, 4096); | ||||
| @@ -86247,7 +86251,7 @@ private: | |||||
| JUCE_DECLARE_NON_COPYABLE (TransformedImageFillEdgeTableRenderer); | JUCE_DECLARE_NON_COPYABLE (TransformedImageFillEdgeTableRenderer); | ||||
| }; | }; | ||||
| class ClipRegionBase : public ReferenceCountedObject | |||||
| class ClipRegionBase : public SingleThreadedReferenceCountedObject | |||||
| { | { | ||||
| public: | public: | ||||
| ClipRegionBase() {} | ClipRegionBase() {} | ||||
| @@ -91982,33 +91986,40 @@ END_JUCE_NAMESPACE | |||||
| /*** Start of inlined file: juce_GlyphArrangement.cpp ***/ | /*** Start of inlined file: juce_GlyphArrangement.cpp ***/ | ||||
| BEGIN_JUCE_NAMESPACE | 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) | 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 | void PositionedGlyph::draw (const Graphics& g) const | ||||
| { | { | ||||
| if (! isWhitespace()) | 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()) | 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); | glyphs.addCopiesOf (other.glyphs); | ||||
| } | } | ||||
| void GlyphArrangement::addGlyph (const PositionedGlyph& glyph) | |||||
| { | |||||
| glyphs.add (new PositionedGlyph (glyph)); | |||||
| } | |||||
| void GlyphArrangement::removeRangeOfGlyphs (int startIndex, const int num) | void GlyphArrangement::removeRangeOfGlyphs (int startIndex, const int num) | ||||
| { | { | ||||
| glyphs.removeRange (startIndex, num < 0 ? glyphs.size() : 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, | void GlyphArrangement::addCurtailedLineOfText (const Font& font, | ||||
| const String& text, | const String& text, | ||||
| float xOffset, | |||||
| const float xOffset, | |||||
| const float yOffset, | const float yOffset, | ||||
| const float maxWidthPixels, | const float maxWidthPixels, | ||||
| const bool useEllipsis) | const bool useEllipsis) | ||||
| @@ -92140,6 +92157,7 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font, | |||||
| Array <float> xOffsets; | Array <float> xOffsets; | ||||
| font.getGlyphPositions (text, newGlyphs, xOffsets); | font.getGlyphPositions (text, newGlyphs, xOffsets); | ||||
| const int textLen = newGlyphs.size(); | const int textLen = newGlyphs.size(); | ||||
| glyphs.ensureStorageAllocated (glyphs.size() + textLen); | |||||
| String::CharPointerType t (text.getCharPointer()); | String::CharPointerType t (text.getCharPointer()); | ||||
| @@ -92158,8 +92176,12 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font, | |||||
| } | } | ||||
| else | 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;) | 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; | --numDeleted; | ||||
| xOffset += dx; | xOffset += dx; | ||||
| @@ -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. | /** 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 | 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 | Once a new ReferenceCountedObject has been assigned to a pointer, be | ||||
| careful not to delete the object manually. | careful not to delete the object manually. | ||||
| @see ReferenceCountedObjectPtr, ReferenceCountedArray | |||||
| This class uses an Atomic<int> 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 | class JUCE_API ReferenceCountedObject | ||||
| { | { | ||||
| @@ -9088,10 +9110,7 @@ public: | |||||
| } | } | ||||
| /** Returns the object's current reference count. */ | /** Returns the object's current reference count. */ | ||||
| inline int getReferenceCount() const noexcept | |||||
| { | |||||
| return refCount.get(); | |||||
| } | |||||
| inline int getReferenceCount() const noexcept { return refCount.get(); } | |||||
| protected: | protected: | ||||
| @@ -9112,6 +9131,62 @@ private: | |||||
| Atomic <int> refCount; | Atomic <int> 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. | 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 | 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. | 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 AsyncUpdater | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -17147,14 +17222,11 @@ public: | |||||
| private: | 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: | public: | ||||
| explicit SharedObject (const Identifier& type); | explicit SharedObject (const Identifier& type); | ||||
| @@ -21560,7 +21632,7 @@ private: | |||||
| @see WeakReference::Master | @see WeakReference::Master | ||||
| */ | */ | ||||
| template <class ObjectType> | |||||
| template <class ObjectType, class ReferenceCountingType = ReferenceCountedObject> | |||||
| class WeakReference | class WeakReference | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -21607,7 +21679,7 @@ public: | |||||
| in your code! | in your code! | ||||
| @see WeakReference | @see WeakReference | ||||
| */ | */ | ||||
| class SharedPointer : public ReferenceCountedObject | |||||
| class SharedPointer : public ReferenceCountingType | |||||
| { | { | ||||
| public: | public: | ||||
| explicit SharedPointer (ObjectType* const owner_) noexcept : owner (owner_) {} | explicit SharedPointer (ObjectType* const owner_) noexcept : owner (owner_) {} | ||||
| @@ -24999,7 +25071,7 @@ class AffineTransform; | |||||
| @see CustomTypeface, Font | @see CustomTypeface, Font | ||||
| */ | */ | ||||
| class JUCE_API Typeface : public ReferenceCountedObject | |||||
| class JUCE_API Typeface : public SingleThreadedReferenceCountedObject | |||||
| { | { | ||||
| public: | public: | ||||
| @@ -25403,7 +25475,7 @@ private: | |||||
| friend class FontGlyphAlphaMap; | friend class FontGlyphAlphaMap; | ||||
| friend class TypefaceCache; | friend class TypefaceCache; | ||||
| class SharedFontInternal : public ReferenceCountedObject | |||||
| class SharedFontInternal : public SingleThreadedReferenceCountedObject | |||||
| { | { | ||||
| public: | public: | ||||
| SharedFontInternal (float height, int styleFlags) noexcept; | SharedFontInternal (float height, int styleFlags) noexcept; | ||||
| @@ -37453,6 +37525,7 @@ private: | |||||
| double sampleRate; | double sampleRate; | ||||
| CriticalSection lock; | CriticalSection lock; | ||||
| void clearChannelData(); | |||||
| bool setDataSource (LevelDataSource* newSource); | bool setDataSource (LevelDataSource* newSource); | ||||
| void setLevels (const MinMaxValue* const* values, int thumbIndex, int numChans, int numValues); | void setLevels (const MinMaxValue* const* values, int thumbIndex, int numChans, int numValues); | ||||
| void createChannels (int length); | void createChannels (int length); | ||||
| @@ -44045,7 +44118,7 @@ public: | |||||
| @see PopupMenu::addCustomItem | @see PopupMenu::addCustomItem | ||||
| */ | */ | ||||
| class JUCE_API CustomComponent : public Component, | class JUCE_API CustomComponent : public Component, | ||||
| public ReferenceCountedObject | |||||
| public SingleThreadedReferenceCountedObject | |||||
| { | { | ||||
| public: | public: | ||||
| /** Creates a custom item. | /** Creates a custom item. | ||||
| @@ -57363,25 +57436,33 @@ private: | |||||
| A glyph from a particular font, with a particular size, style, | A glyph from a particular font, with a particular size, style, | ||||
| typeface and position. | 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 | @see GlyphArrangement, Font | ||||
| */ | */ | ||||
| class JUCE_API PositionedGlyph | class JUCE_API PositionedGlyph | ||||
| { | { | ||||
| public: | public: | ||||
| PositionedGlyph (const Font& font, juce_wchar character, int glyphNumber, | |||||
| float anchorX, float baselineY, float width, bool isWhitespace); | |||||
| PositionedGlyph (const PositionedGlyph& other); | PositionedGlyph (const PositionedGlyph& other); | ||||
| PositionedGlyph& operator= (const PositionedGlyph& other); | |||||
| ~PositionedGlyph(); | |||||
| /** Returns the character the glyph represents. */ | /** 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. */ | /** 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. */ | /** 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. */ | /** 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. */ | /** 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. */ | /** Returns the y position of the top of the glyph. */ | ||||
| float getTop() const { return y - font.getAscent(); } | float getTop() const { return y - font.getAscent(); } | ||||
| /** Returns the y position of the bottom of the glyph. */ | /** Returns the y position of the bottom of the glyph. */ | ||||
| @@ -57410,12 +57491,12 @@ public: | |||||
| private: | private: | ||||
| friend class GlyphArrangement; | friend class GlyphArrangement; | ||||
| float x, y, w; | |||||
| Font font; | Font font; | ||||
| juce_wchar character; | juce_wchar character; | ||||
| int glyph; | 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); | JUCE_LEAK_DETECTOR (PositionedGlyph); | ||||
| }; | }; | ||||
| @@ -57439,7 +57520,6 @@ public: | |||||
| GlyphArrangement (const GlyphArrangement& other); | GlyphArrangement (const GlyphArrangement& other); | ||||
| /** Copies another arrangement onto this one. | /** Copies another arrangement onto this one. | ||||
| To add another arrangement without clearing this one, use addGlyphArrangement(). | To add another arrangement without clearing this one, use addGlyphArrangement(). | ||||
| */ | */ | ||||
| GlyphArrangement& operator= (const GlyphArrangement& other); | GlyphArrangement& operator= (const GlyphArrangement& other); | ||||
| @@ -57530,6 +57610,9 @@ public: | |||||
| /** Appends another glyph arrangement to this one. */ | /** Appends another glyph arrangement to this one. */ | ||||
| void addGlyphArrangement (const GlyphArrangement& other); | 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. | /** Draws this glyph arrangement to a graphics context. | ||||
| This uses cached bitmaps so is much faster than the draw (Graphics&, const AffineTransform&) | This uses cached bitmaps so is much faster than the draw (Graphics&, const AffineTransform&) | ||||
| @@ -57611,9 +57694,9 @@ private: | |||||
| OwnedArray <PositionedGlyph> glyphs; | OwnedArray <PositionedGlyph> 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); | void spreadOutLine (int start, int numGlyphs, float targetWidth); | ||||
| JUCE_LEAK_DETECTOR (GlyphArrangement); | JUCE_LEAK_DETECTOR (GlyphArrangement); | ||||
| @@ -541,7 +541,11 @@ AudioThumbnail::~AudioThumbnail() | |||||
| void AudioThumbnail::clear() | void AudioThumbnail::clear() | ||||
| { | { | ||||
| source = nullptr; | source = nullptr; | ||||
| clearChannelData(); | |||||
| } | |||||
| void AudioThumbnail::clearChannelData() | |||||
| { | |||||
| const ScopedLock sl (lock); | const ScopedLock sl (lock); | ||||
| window->invalidate(); | window->invalidate(); | ||||
| channels.clear(); | channels.clear(); | ||||
| @@ -572,7 +576,7 @@ void AudioThumbnail::createChannels (const int length) | |||||
| //============================================================================== | //============================================================================== | ||||
| void AudioThumbnail::loadFrom (InputStream& rawInput) | void AudioThumbnail::loadFrom (InputStream& rawInput) | ||||
| { | { | ||||
| clear(); | |||||
| clearChannelData(); | |||||
| BufferedInputStream input (rawInput, 4096); | BufferedInputStream input (rawInput, 4096); | ||||
| @@ -227,6 +227,7 @@ private: | |||||
| double sampleRate; | double sampleRate; | ||||
| CriticalSection lock; | CriticalSection lock; | ||||
| void clearChannelData(); | |||||
| bool setDataSource (LevelDataSource* newSource); | bool setDataSource (LevelDataSource* newSource); | ||||
| void setLevels (const MinMaxValue* const* values, int thumbIndex, int numChans, int numValues); | void setLevels (const MinMaxValue* const* values, int thumbIndex, int numChans, int numValues); | ||||
| void createChannels (int length); | void createChannels (int length); | ||||
| @@ -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. | /** 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 | This will use a comparator to find the position at which the new element | ||||
| @@ -170,7 +170,7 @@ public: | |||||
| of a ValueSource object. If you're feeling adventurous, you can create your own custom | 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. | 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 AsyncUpdater | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -466,14 +466,11 @@ public: | |||||
| private: | private: | ||||
| //============================================================================== | //============================================================================== | ||||
| class SetPropertyAction; | |||||
| friend class SetPropertyAction; | |||||
| class AddOrRemoveChildAction; | |||||
| friend class AddOrRemoveChildAction; | |||||
| class MoveChildAction; | |||||
| friend class MoveChildAction; | |||||
| class JUCE_API SharedObject : public ReferenceCountedObject | |||||
| class SetPropertyAction; friend class SetPropertyAction; | |||||
| class AddOrRemoveChildAction; friend class AddOrRemoveChildAction; | |||||
| class MoveChildAction; friend class MoveChildAction; | |||||
| class JUCE_API SharedObject : public SingleThreadedReferenceCountedObject | |||||
| { | { | ||||
| public: | public: | ||||
| explicit SharedObject (const Identifier& type); | explicit SharedObject (const Identifier& type); | ||||
| @@ -415,7 +415,7 @@ public: | |||||
| @see PopupMenu::addCustomItem | @see PopupMenu::addCustomItem | ||||
| */ | */ | ||||
| class JUCE_API CustomComponent : public Component, | class JUCE_API CustomComponent : public Component, | ||||
| public ReferenceCountedObject | |||||
| public SingleThreadedReferenceCountedObject | |||||
| { | { | ||||
| public: | public: | ||||
| /** Creates a custom item. | /** Creates a custom item. | ||||
| @@ -1018,7 +1018,7 @@ private: | |||||
| }; | }; | ||||
| //============================================================================== | //============================================================================== | ||||
| class ClipRegionBase : public ReferenceCountedObject | |||||
| class ClipRegionBase : public SingleThreadedReferenceCountedObject | |||||
| { | { | ||||
| public: | public: | ||||
| ClipRegionBase() {} | ClipRegionBase() {} | ||||
| @@ -364,7 +364,7 @@ private: | |||||
| friend class FontGlyphAlphaMap; | friend class FontGlyphAlphaMap; | ||||
| friend class TypefaceCache; | friend class TypefaceCache; | ||||
| class SharedFontInternal : public ReferenceCountedObject | |||||
| class SharedFontInternal : public SingleThreadedReferenceCountedObject | |||||
| { | { | ||||
| public: | public: | ||||
| SharedFontInternal (float height, int styleFlags) noexcept; | SharedFontInternal (float height, int styleFlags) noexcept; | ||||
| @@ -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) | 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 | void PositionedGlyph::draw (const Graphics& g) const | ||||
| { | { | ||||
| if (! isWhitespace()) | 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()) | 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); | glyphs.addCopiesOf (other.glyphs); | ||||
| } | } | ||||
| void GlyphArrangement::addGlyph (const PositionedGlyph& glyph) | |||||
| { | |||||
| glyphs.add (new PositionedGlyph (glyph)); | |||||
| } | |||||
| void GlyphArrangement::removeRangeOfGlyphs (int startIndex, const int num) | void GlyphArrangement::removeRangeOfGlyphs (int startIndex, const int num) | ||||
| { | { | ||||
| glyphs.removeRange (startIndex, num < 0 ? glyphs.size() : 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, | void GlyphArrangement::addCurtailedLineOfText (const Font& font, | ||||
| const String& text, | const String& text, | ||||
| float xOffset, | |||||
| const float xOffset, | |||||
| const float yOffset, | const float yOffset, | ||||
| const float maxWidthPixels, | const float maxWidthPixels, | ||||
| const bool useEllipsis) | const bool useEllipsis) | ||||
| @@ -197,6 +210,7 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font, | |||||
| Array <float> xOffsets; | Array <float> xOffsets; | ||||
| font.getGlyphPositions (text, newGlyphs, xOffsets); | font.getGlyphPositions (text, newGlyphs, xOffsets); | ||||
| const int textLen = newGlyphs.size(); | const int textLen = newGlyphs.size(); | ||||
| glyphs.ensureStorageAllocated (glyphs.size() + textLen); | |||||
| String::CharPointerType t (text.getCharPointer()); | String::CharPointerType t (text.getCharPointer()); | ||||
| @@ -215,8 +229,12 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font, | |||||
| } | } | ||||
| else | 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;) | 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; | --numDeleted; | ||||
| xOffset += dx; | xOffset += dx; | ||||
| @@ -35,25 +35,33 @@ | |||||
| A glyph from a particular font, with a particular size, style, | A glyph from a particular font, with a particular size, style, | ||||
| typeface and position. | 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 | @see GlyphArrangement, Font | ||||
| */ | */ | ||||
| class JUCE_API PositionedGlyph | class JUCE_API PositionedGlyph | ||||
| { | { | ||||
| public: | public: | ||||
| //============================================================================== | //============================================================================== | ||||
| PositionedGlyph (const Font& font, juce_wchar character, int glyphNumber, | |||||
| float anchorX, float baselineY, float width, bool isWhitespace); | |||||
| PositionedGlyph (const PositionedGlyph& other); | PositionedGlyph (const PositionedGlyph& other); | ||||
| PositionedGlyph& operator= (const PositionedGlyph& other); | |||||
| ~PositionedGlyph(); | |||||
| /** Returns the character the glyph represents. */ | /** 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. */ | /** 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. */ | /** 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. */ | /** 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. */ | /** 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. */ | /** Returns the y position of the top of the glyph. */ | ||||
| float getTop() const { return y - font.getAscent(); } | float getTop() const { return y - font.getAscent(); } | ||||
| /** Returns the y position of the bottom of the glyph. */ | /** Returns the y position of the bottom of the glyph. */ | ||||
| @@ -84,12 +92,12 @@ public: | |||||
| private: | private: | ||||
| //============================================================================== | //============================================================================== | ||||
| friend class GlyphArrangement; | friend class GlyphArrangement; | ||||
| float x, y, w; | |||||
| Font font; | Font font; | ||||
| juce_wchar character; | juce_wchar character; | ||||
| int glyph; | 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); | JUCE_LEAK_DETECTOR (PositionedGlyph); | ||||
| }; | }; | ||||
| @@ -115,7 +123,6 @@ public: | |||||
| GlyphArrangement (const GlyphArrangement& other); | GlyphArrangement (const GlyphArrangement& other); | ||||
| /** Copies another arrangement onto this one. | /** Copies another arrangement onto this one. | ||||
| To add another arrangement without clearing this one, use addGlyphArrangement(). | To add another arrangement without clearing this one, use addGlyphArrangement(). | ||||
| */ | */ | ||||
| GlyphArrangement& operator= (const GlyphArrangement& other); | GlyphArrangement& operator= (const GlyphArrangement& other); | ||||
| @@ -208,6 +215,9 @@ public: | |||||
| /** Appends another glyph arrangement to this one. */ | /** Appends another glyph arrangement to this one. */ | ||||
| void addGlyphArrangement (const GlyphArrangement& other); | 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. | /** Draws this glyph arrangement to a graphics context. | ||||
| @@ -293,9 +303,9 @@ private: | |||||
| //============================================================================== | //============================================================================== | ||||
| OwnedArray <PositionedGlyph> glyphs; | OwnedArray <PositionedGlyph> 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); | void spreadOutLine (int start, int numGlyphs, float targetWidth); | ||||
| JUCE_LEAK_DETECTOR (GlyphArrangement); | JUCE_LEAK_DETECTOR (GlyphArrangement); | ||||
| @@ -49,7 +49,7 @@ class AffineTransform; | |||||
| @see CustomTypeface, Font | @see CustomTypeface, Font | ||||
| */ | */ | ||||
| class JUCE_API Typeface : public ReferenceCountedObject | |||||
| class JUCE_API Typeface : public SingleThreadedReferenceCountedObject | |||||
| { | { | ||||
| public: | public: | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -32,7 +32,7 @@ BEGIN_JUCE_NAMESPACE | |||||
| //============================================================================== | //============================================================================== | ||||
| class Expression::Term : public ReferenceCountedObject | |||||
| class Expression::Term : public SingleThreadedReferenceCountedObject | |||||
| { | { | ||||
| public: | public: | ||||
| Term() {} | Term() {} | ||||
| @@ -55,7 +55,11 @@ | |||||
| Once a new ReferenceCountedObject has been assigned to a pointer, be | Once a new ReferenceCountedObject has been assigned to a pointer, be | ||||
| careful not to delete the object manually. | careful not to delete the object manually. | ||||
| @see ReferenceCountedObjectPtr, ReferenceCountedArray | |||||
| This class uses an Atomic<int> 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 | class JUCE_API ReferenceCountedObject | ||||
| { | { | ||||
| @@ -84,10 +88,7 @@ public: | |||||
| } | } | ||||
| /** Returns the object's current reference count. */ | /** Returns the object's current reference count. */ | ||||
| inline int getReferenceCount() const noexcept | |||||
| { | |||||
| return refCount.get(); | |||||
| } | |||||
| inline int getReferenceCount() const noexcept { return refCount.get(); } | |||||
| protected: | 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; | |||||
| }; | |||||
| //============================================================================== | //============================================================================== | ||||
| /** | /** | ||||
| @@ -81,7 +81,7 @@ | |||||
| @see WeakReference::Master | @see WeakReference::Master | ||||
| */ | */ | ||||
| template <class ObjectType> | |||||
| template <class ObjectType, class ReferenceCountingType = ReferenceCountedObject> | |||||
| class WeakReference | class WeakReference | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -129,7 +129,7 @@ public: | |||||
| in your code! | in your code! | ||||
| @see WeakReference | @see WeakReference | ||||
| */ | */ | ||||
| class SharedPointer : public ReferenceCountedObject | |||||
| class SharedPointer : public ReferenceCountingType | |||||
| { | { | ||||
| public: | public: | ||||
| explicit SharedPointer (ObjectType* const owner_) noexcept : owner (owner_) {} | explicit SharedPointer (ObjectType* const owner_) noexcept : owner (owner_) {} | ||||