diff --git a/extras/juce demo/Source/demos/RenderingTestComponent.cpp b/extras/juce demo/Source/demos/RenderingTestComponent.cpp index ccf3d0f79f..8a2b629ef3 100644 --- a/extras/juce demo/Source/demos/RenderingTestComponent.cpp +++ b/extras/juce demo/Source/demos/RenderingTestComponent.cpp @@ -166,8 +166,8 @@ private: return AffineTransform::rotation ((float) owner.angleSlider->getValue() / (180.0f / float_Pi)) .scaled ((float) owner.sizeSlider->getValue(), (float) owner.sizeSlider->getValue()) - .translated (getWidth() * 0.5f + (float) owner.xSlider->getValue(), - getHeight() * 0.5f + (float) owner.ySlider->getValue()); + .translated (getWidth() / 2 + (float) owner.xSlider->getValue(), + getHeight() / 2 + (float) owner.ySlider->getValue()); } void clipToRectangle (Graphics& g) diff --git a/extras/the jucer/src/model/jucer_BinaryResources.cpp b/extras/the jucer/src/model/jucer_BinaryResources.cpp index 1f0e4b17dd..8666d4ff9e 100644 --- a/extras/the jucer/src/model/jucer_BinaryResources.cpp +++ b/extras/the jucer/src/model/jucer_BinaryResources.cpp @@ -261,7 +261,7 @@ void BinaryResources::loadFromCpp (const File& cppFileLocation, const String& cp break; } - jassert (size < out.getDataSize() && size > out.getDataSize() - 2); + jassert (size < (int) out.getDataSize() && size > (int) out.getDataSize() - 2); MemoryBlock mb (out.getData(), out.getDataSize()); mb.setSize (size); diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 9b623d8674..ff7d0be6f0 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -479,7 +479,7 @@ #undef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (push) #pragma warning (disable : 4100 4201 4514 4312 4995) #endif @@ -614,7 +614,7 @@ #import #endif -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (pop) #endif @@ -1893,9 +1893,9 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_Time.cpp ***/ -#ifdef _MSC_VER - #pragma warning (disable: 4514) +#if JUCE_MSVC #pragma warning (push) + #pragma warning (disable: 4514) #endif #ifndef JUCE_WINDOWS @@ -1906,9 +1906,7 @@ END_JUCE_NAMESPACE #include -BEGIN_JUCE_NAMESPACE - -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (pop) #ifdef _INC_TIME_INL @@ -1916,6 +1914,8 @@ BEGIN_JUCE_NAMESPACE #endif #endif +BEGIN_JUCE_NAMESPACE + namespace TimeHelpers { static struct tm millisToLocal (const int64 millis) throw() @@ -7236,7 +7236,8 @@ END_JUCE_NAMESPACE #if JUCE_WINDOWS #include - #ifdef _MSC_VER + #if JUCE_MSVC + #pragma warning (push) #pragma warning (disable : 4127 4389 4018) #endif @@ -7821,6 +7822,10 @@ bool DatagramSocket::isLocal() const throw() return hostName == "127.0.0.1"; } +#if JUCE_MSVC + #pragma warning (pop) +#endif + END_JUCE_NAMESPACE /*** End of inlined file: juce_Socket.cpp ***/ @@ -9320,19 +9325,15 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_CharacterFunctions.cpp ***/ -#ifdef _MSC_VER - #pragma warning (disable: 4514 4996) +#if JUCE_MSVC #pragma warning (push) + #pragma warning (disable: 4514 4996) #endif #include #include #include -#ifdef _MSC_VER - #pragma warning (pop) -#endif - BEGIN_JUCE_NAMESPACE int CharacterFunctions::length (const char* const s) throw() @@ -10082,6 +10083,10 @@ int CharacterFunctions::getHexDigitValue (const juce_wchar digit) throw() return -1; } +#if JUCE_MSVC + #pragma warning (pop) +#endif + END_JUCE_NAMESPACE /*** End of inlined file: juce_CharacterFunctions.cpp ***/ @@ -10215,19 +10220,16 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_String.cpp ***/ -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (push) #pragma warning (disable: 4514) #endif -#include -#if JUCE_MSVC - #include -#endif +#include BEGIN_JUCE_NAMESPACE -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (pop) #endif @@ -11853,12 +11855,12 @@ const String String::formatted (const juce_wchar* const pf, ... ) const int num = (int) vswprintf (result.text, bufferSize - 1, pf, tempArgs); va_end (tempArgs); #elif JUCE_WINDOWS - #ifdef _MSC_VER + #if JUCE_MSVC #pragma warning (push) #pragma warning (disable: 4996) #endif const int num = (int) _vsnwprintf (result.text, bufferSize - 1, pf, args); - #ifdef _MSC_VER + #if JUCE_MSVC #pragma warning (pop) #endif #else @@ -12293,9 +12295,9 @@ const char* String::toCString() const } } -#ifdef _MSC_VER - #pragma warning (disable: 4514 4996) +#if JUCE_MSVC #pragma warning (push) + #pragma warning (disable: 4514 4996) #endif int String::getNumBytesAsCString() const throw() @@ -12313,7 +12315,7 @@ int String::copyToCString (char* destBuffer, const int maxBufferSizeBytes) const return numBytes; } -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (pop) #endif @@ -31370,7 +31372,7 @@ BEGIN_JUCE_NAMESPACE #undef PRAGMA_ALIGN_SUPPORTED #define VST_FORCE_DEPRECATED 0 -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (push) #pragma warning (disable: 4996) #endif @@ -31383,7 +31385,7 @@ BEGIN_JUCE_NAMESPACE */ #include "pluginterfaces/vst2.x/aeffectx.h" -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (pop) #endif @@ -33705,14 +33707,14 @@ VstIntPtr VSTPluginInstance::handleCallback (VstInt32 opcode, VstInt32 index, Vs break; case audioMasterGetTime: - #ifdef _MSC_VER + #if JUCE_MSVC #pragma warning (push) #pragma warning (disable: 4311) #endif return (VstIntPtr) &vstHostTime; - #ifdef _MSC_VER + #if JUCE_MSVC #pragma warning (pop) #endif break; @@ -80545,7 +80547,7 @@ void Graphics::drawHorizontalLine (const int y, float left, float right) const void Graphics::drawLine (float x1, float y1, float x2, float y2) const { - context->drawLine (x1, y1, x2, y2); + context->drawLine (Line (x1, y1, x2, y2)); } void Graphics::drawLine (const float startX, const float startY, @@ -81226,21 +81228,21 @@ void LowLevelGraphicsPostScriptRenderer::drawImage (const Image& sourceImage, co needToClip = true; } -void LowLevelGraphicsPostScriptRenderer::drawLine (double x1, double y1, double x2, double y2) +void LowLevelGraphicsPostScriptRenderer::drawLine (const Line & line) { Path p; - p.addLineSegment ((float) x1, (float) y1, (float) x2, (float) y2, 1.0f); + p.addLineSegment (line.getStartX(), line.getStartY(), line.getEndX(), line.getEndY(), 1.0f); fillPath (p, AffineTransform::identity); } -void LowLevelGraphicsPostScriptRenderer::drawVerticalLine (const int x, double top, double bottom) +void LowLevelGraphicsPostScriptRenderer::drawVerticalLine (const int x, float top, float bottom) { - drawLine (x, top, x, bottom); + drawLine (Line ((float) x, top, (float) x, bottom)); } -void LowLevelGraphicsPostScriptRenderer::drawHorizontalLine (const int y, double left, double right) +void LowLevelGraphicsPostScriptRenderer::drawHorizontalLine (const int y, float left, float right) { - drawLine (left, y, right, y); + drawLine (Line (left, (float) y, right, (float) y)); } void LowLevelGraphicsPostScriptRenderer::setFont (const Font& newFont) @@ -81273,15 +81275,18 @@ BEGIN_JUCE_NAMESPACE #endif #if JUCE_MSVC + #pragma warning (push) + #pragma warning (disable: 4127) // "expression is constant" warning + #if JUCE_DEBUG #pragma optimize ("t", on) // optimise just this file, to avoid sluggish graphics when debugging #pragma warning (disable: 4714) // warning about forcedinline methods not being inlined #endif - - #pragma warning (push) - #pragma warning (disable: 4127) // "expression is constant" warning #endif +namespace SoftwareRendererClasses +{ + template class SolidColourEdgeTableRenderer { @@ -82119,7 +82124,7 @@ public: virtual const Ptr clone() const = 0; - const Ptr clipTo (ClipRegionBase* other); + virtual const Ptr applyClipTo (const Ptr& target) const = 0; virtual const Ptr clipToRectangle (const Rectangle& r) = 0; virtual const Ptr clipToRectangleList (const RectangleList& r) = 0; virtual const Ptr excludeClipRectangle (const Rectangle& r) = 0; @@ -82134,14 +82139,14 @@ public: virtual void fillRectWithColour (Image::BitmapData& destData, const Rectangle& area, const PixelARGB& colour) const = 0; virtual void fillAllWithColour (Image::BitmapData& destData, const PixelARGB& colour, bool replaceContents) const = 0; virtual void fillAllWithGradient (Image::BitmapData& destData, ColourGradient& gradient, const AffineTransform& transform, bool isIdentity) const = 0; - virtual void renderImageTransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const Rectangle& srcClip, const int alpha, const AffineTransform& t, bool betterQuality, bool tiledFill) const = 0; - virtual void renderImageUntransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const Rectangle& srcClip, const int alpha, int x, int y, bool tiledFill) const = 0; + virtual void renderImageTransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const int alpha, const AffineTransform& t, bool betterQuality, bool tiledFill) const = 0; + virtual void renderImageUntransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const int alpha, int x, int y, bool tiledFill) const = 0; protected: template static void renderImageTransformedInternal (Iterator& iter, const Image::BitmapData& destData, const Image::BitmapData& srcData, - const Rectangle& srcClip, const int alpha, const AffineTransform& transform, bool betterQuality, bool tiledFill) + const int alpha, const AffineTransform& transform, bool betterQuality, bool tiledFill) { switch (destData.pixelFormat) { @@ -82202,7 +82207,7 @@ protected: } template - static void renderImageUntransformedInternal (Iterator& iter, const Image::BitmapData& destData, const Image::BitmapData& srcData, const Rectangle& srcClip, const int alpha, int x, int y, bool tiledFill) + static void renderImageUntransformedInternal (Iterator& iter, const Image::BitmapData& destData, const Image::BitmapData& srcData, const int alpha, int x, int y, bool tiledFill) { switch (destData.pixelFormat) { @@ -82321,6 +82326,11 @@ public: return new ClipRegion_EdgeTable (*this); } + const Ptr applyClipTo (const Ptr& target) const + { + return target->clipToEdgeTable (edgeTable); + } + const Ptr clipToRectangle (const Rectangle& r) { edgeTable.clipToRectangle (r); @@ -82458,14 +82468,14 @@ public: } } - void renderImageTransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const Rectangle& srcClip, const int alpha, const AffineTransform& transform, bool betterQuality, bool tiledFill) const + void renderImageTransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const int alpha, const AffineTransform& transform, bool betterQuality, bool tiledFill) const { - renderImageTransformedInternal (edgeTable, destData, srcData, srcClip, alpha, transform, betterQuality, tiledFill); + renderImageTransformedInternal (edgeTable, destData, srcData, alpha, transform, betterQuality, tiledFill); } - void renderImageUntransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const Rectangle& srcClip, const int alpha, int x, int y, bool tiledFill) const + void renderImageUntransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const int alpha, int x, int y, bool tiledFill) const { - renderImageUntransformedInternal (edgeTable, destData, srcData, srcClip, alpha, x, y, tiledFill); + renderImageUntransformedInternal (edgeTable, destData, srcData, alpha, x, y, tiledFill); } EdgeTable edgeTable; @@ -82510,6 +82520,11 @@ public: return new ClipRegion_RectangleList (*this); } + const Ptr applyClipTo (const Ptr& target) const + { + return target->clipToRectangleList (clip); + } + const Ptr clipToRectangle (const Rectangle& r) { clip.clipTo (r); @@ -82601,14 +82616,14 @@ public: } } - void renderImageTransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const Rectangle& srcClip, const int alpha, const AffineTransform& transform, bool betterQuality, bool tiledFill) const + void renderImageTransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const int alpha, const AffineTransform& transform, bool betterQuality, bool tiledFill) const { - renderImageTransformedInternal (*this, destData, srcData, srcClip, alpha, transform, betterQuality, tiledFill); + renderImageTransformedInternal (*this, destData, srcData, alpha, transform, betterQuality, tiledFill); } - void renderImageUntransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const Rectangle& srcClip, const int alpha, int x, int y, bool tiledFill) const + void renderImageUntransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const int alpha, int x, int y, bool tiledFill) const { - renderImageUntransformedInternal (*this, destData, srcData, srcClip, alpha, x, y, tiledFill); + renderImageUntransformedInternal (*this, destData, srcData, alpha, x, y, tiledFill); } RectangleList clip; @@ -82671,6 +82686,9 @@ private: private: const RectangleList& clip; const Rectangle area; + + SubRectangleIterator (const SubRectangleIterator&); + SubRectangleIterator& operator= (const SubRectangleIterator&); }; class SubRectangleIteratorFloat @@ -82833,52 +82851,38 @@ private: private: const RectangleList& clip; const Rectangle& area; + + SubRectangleIteratorFloat (const SubRectangleIteratorFloat&); + SubRectangleIteratorFloat& operator= (const SubRectangleIteratorFloat&); }; ClipRegion_RectangleList& operator= (const ClipRegion_RectangleList&); }; -const ClipRegionBase::Ptr ClipRegionBase::clipTo (ClipRegionBase* const other) -{ - ClipRegion_EdgeTable* et = dynamic_cast (other); - - if (et != 0) - return clipToEdgeTable (et->edgeTable); - - ClipRegion_RectangleList* rl = dynamic_cast (other); - - if (rl != 0) - return clipToRectangleList (rl->clip); - - jassertfalse - return 0; } -class LLGCSavedState +class LowLevelGraphicsSoftwareRenderer::SavedState { public: - LLGCSavedState (const Rectangle& clip_, const int xOffset_, const int yOffset_) - : clip (new ClipRegion_RectangleList (clip_)), - xOffset (xOffset_), yOffset (yOffset_), - interpolationQuality (Graphics::mediumResamplingQuality) + SavedState (const Rectangle& clip_, const int xOffset_, const int yOffset_) + : clip (new SoftwareRendererClasses::ClipRegion_RectangleList (clip_)), + xOffset (xOffset_), yOffset (yOffset_), interpolationQuality (Graphics::mediumResamplingQuality) { } - LLGCSavedState (const RectangleList& clip_, const int xOffset_, const int yOffset_) - : clip (new ClipRegion_RectangleList (clip_)), - xOffset (xOffset_), yOffset (yOffset_), - interpolationQuality (Graphics::mediumResamplingQuality) + SavedState (const RectangleList& clip_, const int xOffset_, const int yOffset_) + : clip (new SoftwareRendererClasses::ClipRegion_RectangleList (clip_)), + xOffset (xOffset_), yOffset (yOffset_), interpolationQuality (Graphics::mediumResamplingQuality) { } - LLGCSavedState (const LLGCSavedState& other) - : clip (other.clip), xOffset (other.xOffset), - yOffset (other.yOffset), font (other.font), + SavedState (const SavedState& other) + : clip (other.clip), xOffset (other.xOffset), yOffset (other.yOffset), font (other.font), fillType (other.fillType), interpolationQuality (other.interpolationQuality) { } - ~LLGCSavedState() + ~SavedState() { } @@ -82977,7 +82981,7 @@ public: const Rectangle clipped (totalClip.getIntersection (r.translated (xOffset, yOffset))); if (! clipped.isEmpty()) - fillShape (image, new ClipRegion_RectangleList (clipped), false); + fillShape (image, new SoftwareRendererClasses::ClipRegion_RectangleList (clipped), false); } } } @@ -82997,7 +83001,7 @@ public: const Rectangle clipped (totalClip.getIntersection (r.translated ((float) xOffset, (float) yOffset))); if (! clipped.isEmpty()) - fillShape (image, new ClipRegion_EdgeTable (clipped), false); + fillShape (image, new SoftwareRendererClasses::ClipRegion_EdgeTable (clipped), false); } } } @@ -83005,31 +83009,31 @@ public: void fillPath (Image& image, const Path& path, const AffineTransform& transform) { if (clip != 0) - fillShape (image, new ClipRegion_EdgeTable (clip->getClipBounds(), path, transform.translated ((float) xOffset, (float) yOffset)), false); + fillShape (image, new SoftwareRendererClasses::ClipRegion_EdgeTable (clip->getClipBounds(), path, transform.translated ((float) xOffset, (float) yOffset)), false); } void fillEdgeTable (Image& image, const EdgeTable& edgeTable, const float x, const int y) { if (clip != 0) { - ClipRegion_EdgeTable* edgeTableClip = new ClipRegion_EdgeTable (edgeTable); - ClipRegionBase::Ptr shapeToFill (edgeTableClip); + SoftwareRendererClasses::ClipRegion_EdgeTable* edgeTableClip = new SoftwareRendererClasses::ClipRegion_EdgeTable (edgeTable); + SoftwareRendererClasses::ClipRegionBase::Ptr shapeToFill (edgeTableClip); edgeTableClip->edgeTable.translate (x + xOffset, y + yOffset); fillShape (image, shapeToFill, false); } } - void fillShape (Image& image, ClipRegionBase::Ptr shapeToFill, const bool replaceContents) + void fillShape (Image& image, SoftwareRendererClasses::ClipRegionBase::Ptr shapeToFill, const bool replaceContents) { jassert (clip != 0); - shapeToFill = shapeToFill->clipTo (clip); + shapeToFill = clip->applyClipTo (shapeToFill); if (shapeToFill != 0) fillShapeWithoutClipping (image, shapeToFill, replaceContents); } - void fillShapeWithoutClipping (Image& image, const ClipRegionBase::Ptr& shapeToFill, const bool replaceContents) + void fillShapeWithoutClipping (Image& image, const SoftwareRendererClasses::ClipRegionBase::Ptr& shapeToFill, const bool replaceContents) { Image::BitmapData destData (image, 0, 0, image.getWidth(), image.getHeight(), true); @@ -83065,7 +83069,7 @@ public: } void renderImage (Image& destImage, const Image& sourceImage, const Rectangle& srcClip, - const AffineTransform& t, const ClipRegionBase* const tiledFillClipRegion) + const AffineTransform& t, const SoftwareRendererClasses::ClipRegionBase* const tiledFillClipRegion) { const AffineTransform transform (t.translated ((float) xOffset, (float) yOffset)); @@ -83087,15 +83091,15 @@ public: if (tiledFillClipRegion != 0) { - tiledFillClipRegion->renderImageUntransformed (destData, srcData, srcClip, alpha, tx, ty, true); + tiledFillClipRegion->renderImageUntransformed (destData, srcData, alpha, tx, ty, true); } else { - ClipRegionBase::Ptr c (new ClipRegion_EdgeTable (Rectangle (tx, ty, srcClip.getWidth(), srcClip.getHeight()).getIntersection (destImage.getBounds()))); - c = c->clipTo (clip); + SoftwareRendererClasses::ClipRegionBase::Ptr c (new SoftwareRendererClasses::ClipRegion_EdgeTable (Rectangle (tx, ty, srcClip.getWidth(), srcClip.getHeight()).getIntersection (destImage.getBounds()))); + c = clip->applyClipTo (c); if (c != 0) - c->renderImageUntransformed (destData, srcData, srcClip, alpha, tx, ty, false); + c->renderImageUntransformed (destData, srcData, alpha, tx, ty, false); } return; @@ -83107,22 +83111,22 @@ public: if (tiledFillClipRegion != 0) { - tiledFillClipRegion->renderImageTransformed (destData, srcData, srcClip, alpha, transform, betterQuality, true); + tiledFillClipRegion->renderImageTransformed (destData, srcData, alpha, transform, betterQuality, true); } else { Path p; p.addRectangle (0.0f, 0.0f, (float) srcClip.getWidth(), (float) srcClip.getHeight()); - ClipRegionBase::Ptr c (clip->clone()); + SoftwareRendererClasses::ClipRegionBase::Ptr c (clip->clone()); c = c->clipToPath (p, transform); if (c != 0) - c->renderImageTransformed (destData, srcData, srcClip, alpha, transform, betterQuality, true); + c->renderImageTransformed (destData, srcData, alpha, transform, betterQuality, true); } } - ClipRegionBase::Ptr clip; + SoftwareRendererClasses::ClipRegionBase::Ptr clip; int xOffset, yOffset; Font font; FillType fillType; @@ -83135,20 +83139,20 @@ private: clip = clip->clone(); } - LLGCSavedState& operator= (const LLGCSavedState&); + SavedState& operator= (const SavedState&); }; LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (Image& image_) : image (image_) { - currentState = new LLGCSavedState (image_.getBounds(), 0, 0); + currentState = new SavedState (image_.getBounds(), 0, 0); } LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (Image& image_, const int xOffset, const int yOffset, const RectangleList& initialClip) : image (image_) { - currentState = new LLGCSavedState (initialClip, xOffset, yOffset); + currentState = new SavedState (initialClip, xOffset, yOffset); } LowLevelGraphicsSoftwareRenderer::~LowLevelGraphicsSoftwareRenderer() @@ -83207,12 +83211,12 @@ bool LowLevelGraphicsSoftwareRenderer::isClipEmpty() const void LowLevelGraphicsSoftwareRenderer::saveState() { - stateStack.add (new LLGCSavedState (*currentState)); + stateStack.add (new SavedState (*currentState)); } void LowLevelGraphicsSoftwareRenderer::restoreState() { - LLGCSavedState* const top = stateStack.getLast(); + SavedState* const top = stateStack.getLast(); if (top != 0) { @@ -83259,26 +83263,70 @@ void LowLevelGraphicsSoftwareRenderer::drawImage (const Image& sourceImage, cons fillEntireClipAsTiles ? currentState->clip : 0); } -void LowLevelGraphicsSoftwareRenderer::drawLine (double x1, double y1, double x2, double y2) +void LowLevelGraphicsSoftwareRenderer::drawLine (const Line & line) { Path p; - p.addLineSegment ((float) x1, (float) y1, (float) x2, (float) y2, 1.0f); + p.addLineSegment (line.getStartX(), line.getStartY(), line.getEndX(), line.getEndY(), 1.0f); fillPath (p, AffineTransform::identity); } -void LowLevelGraphicsSoftwareRenderer::drawVerticalLine (const int x, double top, double bottom) +void LowLevelGraphicsSoftwareRenderer::drawVerticalLine (const int x, float top, float bottom) { if (bottom > top) - currentState->fillRect (image, Rectangle ((float) x, (float) top, 1.0f, (float) (bottom - top))); + currentState->fillRect (image, Rectangle ((float) x, top, 1.0f, bottom - top)); } -void LowLevelGraphicsSoftwareRenderer::drawHorizontalLine (const int y, double left, double right) +void LowLevelGraphicsSoftwareRenderer::drawHorizontalLine (const int y, float left, float right) { if (right > left) - currentState->fillRect (image, Rectangle ((float) left, (float) y, (float) (right - left), 1.0f)); + currentState->fillRect (image, Rectangle (left, (float) y, right - left, 1.0f)); } -class GlyphCache : private DeletedAtShutdown +class LowLevelGraphicsSoftwareRenderer::CachedGlyph +{ +public: + CachedGlyph() : glyph (0), lastAccessCount (0) {} + ~CachedGlyph() {} + + void draw (SavedState& state, Image& image, const float x, const float y) const + { + if (edgeTable != 0) + state.fillEdgeTable (image, *edgeTable, x, roundToInt (y)); + } + + void generate (const Font& newFont, const int glyphNumber) + { + font = newFont; + glyph = glyphNumber; + edgeTable = 0; + + Path glyphPath; + font.getTypeface()->getOutlineForGlyph (glyphNumber, glyphPath); + + if (! glyphPath.isEmpty()) + { + const float fontHeight = font.getHeight(); + const AffineTransform transform (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight) + .translated (0.0f, -0.5f)); + + edgeTable = new EdgeTable (glyphPath.getBoundsTransformed (transform).getSmallestIntegerContainer().expanded (1, 0), + glyphPath, transform); + } + } + + int glyph, lastAccessCount; + Font font; + + juce_UseDebuggingNewOperator + +private: + ScopedPointer edgeTable; + + CachedGlyph (const CachedGlyph&); + CachedGlyph& operator= (const CachedGlyph&); +}; + +class LowLevelGraphicsSoftwareRenderer::GlyphCache : private DeletedAtShutdown { public: GlyphCache() @@ -83295,7 +83343,7 @@ public: juce_DeclareSingleton_SingleThreaded_Minimal (GlyphCache); - void drawGlyph (LLGCSavedState& state, Image& image, const Font& font, const int glyphNumber, float x, float y) + void drawGlyph (SavedState& state, Image& image, const Font& font, const int glyphNumber, float x, float y) { ++accessCounter; int oldestCounter = std::numeric_limits::max(); @@ -83338,53 +83386,10 @@ public: oldest->draw (state, image, x, y); } - class CachedGlyph - { - public: - CachedGlyph() : glyph (0), lastAccessCount (0) {} - ~CachedGlyph() {} - - void draw (LLGCSavedState& state, Image& image, const float x, const float y) const - { - if (edgeTable != 0) - state.fillEdgeTable (image, *edgeTable, x, roundToInt (y)); - } - - void generate (const Font& newFont, const int glyphNumber) - { - font = newFont; - glyph = glyphNumber; - edgeTable = 0; - - Path glyphPath; - font.getTypeface()->getOutlineForGlyph (glyphNumber, glyphPath); - - if (! glyphPath.isEmpty()) - { - const float fontHeight = font.getHeight(); - const AffineTransform transform (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight) - .translated (0.0f, -0.5f)); - - edgeTable = new EdgeTable (glyphPath.getBoundsTransformed (transform).getSmallestIntegerContainer().expanded (1, 0), - glyphPath, transform); - } - } - - int glyph, lastAccessCount; - Font font; - - juce_UseDebuggingNewOperator - - private: - ScopedPointer edgeTable; - - CachedGlyph (const CachedGlyph&); - CachedGlyph& operator= (const CachedGlyph&); - }; - juce_UseDebuggingNewOperator private: + friend class OwnedArray ; OwnedArray glyphs; int accessCounter, hits, misses; @@ -83392,7 +83397,7 @@ private: GlyphCache& operator= (const GlyphCache&); }; -juce_ImplementSingleton_SingleThreaded (GlyphCache); +juce_ImplementSingleton_SingleThreaded (LowLevelGraphicsSoftwareRenderer::GlyphCache); void LowLevelGraphicsSoftwareRenderer::setFont (const Font& newFont) { @@ -85623,8 +85628,8 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_DropShadowEffect.cpp ***/ BEGIN_JUCE_NAMESPACE -#if JUCE_MSVC - #pragma optimize ("t", on) // try to avoid slowing everything down in debug builds +#if JUCE_MSVC && JUCE_DEBUG + #pragma optimize ("t", on) #endif DropShadowEffect::DropShadowEffect() @@ -85699,6 +85704,10 @@ void DropShadowEffect::applyEffect (Image& image, Graphics& g) g.drawImageAt (&image, 0, 0); } +#if JUCE_MSVC && JUCE_DEBUG + #pragma optimize ("", on) // resets optimisations to the project defaults +#endif + END_JUCE_NAMESPACE /*** End of inlined file: juce_DropShadowEffect.cpp ***/ @@ -89528,7 +89537,7 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_PathIterator.cpp ***/ BEGIN_JUCE_NAMESPACE -#if JUCE_MSVC +#if JUCE_MSVC && JUCE_DEBUG #pragma optimize ("t", on) #endif @@ -89785,6 +89794,10 @@ bool PathFlatteningIterator::next() } } +#if JUCE_MSVC && JUCE_DEBUG + #pragma optimize ("", on) // resets optimisations to the project defaults +#endif + END_JUCE_NAMESPACE /*** End of inlined file: juce_PathIterator.cpp ***/ @@ -102016,14 +102029,13 @@ END_JUCE_NAMESPACE #include #endif -#ifdef _MSC_VER - #pragma warning (disable : 4505) - #pragma warning (push) -#endif - namespace FlacNamespace { #if JUCE_INCLUDE_FLAC_CODE + #if JUCE_MSVC + #pragma warning (disable : 4505) // (unreferenced static function removal warning) + #endif + #define FLAC__NO_DLL 1 #if ! defined (SIZE_MAX) @@ -124743,10 +124755,6 @@ void FLAC__window_welch(FLAC__real *window, const FLAC__int32 L) #undef max #undef min -#ifdef _MSC_VER - #pragma warning (pop) -#endif - BEGIN_JUCE_NAMESPACE static const char* const flacFormatName = "FLAC file"; @@ -207975,7 +207983,7 @@ END_JUCE_NAMESPACE /*** Start of inlined file: juce_PNGLoader.cpp ***/ -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (push) #pragma warning (disable: 4390 4611) #endif @@ -233416,7 +233424,7 @@ png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) #undef max #undef min -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (pop) #endif @@ -237130,7 +237138,6 @@ private: if (hasTitleBar()) { type |= WS_OVERLAPPED; - exstyle |= WS_EX_APPWINDOW; if ((styleFlags & windowHasCloseButton) != 0) { @@ -237148,13 +237155,13 @@ private: else { type |= WS_POPUP | WS_SYSMENU; - - if ((styleFlags & windowAppearsOnTaskbar) == 0) - exstyle |= WS_EX_TOOLWINDOW; - else - exstyle |= WS_EX_APPWINDOW; } + if ((styleFlags & windowAppearsOnTaskbar) == 0) + exstyle |= WS_EX_TOOLWINDOW; + else + exstyle |= WS_EX_APPWINDOW; + if ((styleFlags & windowHasMinimiseButton) != 0) type |= WS_MINIMIZEBOX; @@ -262182,7 +262189,7 @@ public: CGContextRestoreGState (context); } - void drawLine (double x1, double y1, double x2, double y2) + void drawLine (const Line& line) { CGContextSetLineCap (context, kCGLineCapSquare); CGContextSetLineWidth (context, 1.0f); @@ -262190,31 +262197,31 @@ public: state->fillType.colour.getFloatRed(), state->fillType.colour.getFloatGreen(), state->fillType.colour.getFloatBlue(), state->fillType.colour.getFloatAlpha()); - CGPoint line[] = { { (CGFloat) x1, flipHeight - (CGFloat) y1 }, - { (CGFloat) x2, flipHeight - (CGFloat) y2 } }; + CGPoint cgLine[] = { { (CGFloat) line.getStartX(), flipHeight - (CGFloat) line.getStartY() }, + { (CGFloat) line.getEndX(), flipHeight - (CGFloat) line.getEndY() } }; - CGContextStrokeLineSegments (context, line, 1); + CGContextStrokeLineSegments (context, cgLine, 1); } - void drawVerticalLine (const int x, double top, double bottom) + void drawVerticalLine (const int x, float top, float bottom) { #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 - CGContextFillRect (context, CGRectMake (x, flipHeight - (float) bottom, 1.0f, (float) (bottom - top))); + CGContextFillRect (context, CGRectMake (x, flipHeight - bottom, 1.0f, bottom - top)); #else // On Leopard, unless both co-ordinates are non-integer, it disables anti-aliasing, so nudge // the x co-ord slightly to trick it.. - CGContextFillRect (context, CGRectMake (x + 1.0f / 256.0f, flipHeight - (float) bottom, 1.0f + 1.0f / 256.0f, (float) (bottom - top))); + CGContextFillRect (context, CGRectMake (x + 1.0f / 256.0f, flipHeight - bottom, 1.0f + 1.0f / 256.0f, bottom - top)); #endif } - void drawHorizontalLine (const int y, double left, double right) + void drawHorizontalLine (const int y, float left, float right) { #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 - CGContextFillRect (context, CGRectMake ((float) left, flipHeight - (y + 1.0f), (float) (right - left), 1.0f)); + CGContextFillRect (context, CGRectMake (left, flipHeight - (y + 1.0f), right - left, 1.0f)); #else // On Leopard, unless both co-ordinates are non-integer, it disables anti-aliasing, so nudge // the x co-ord slightly to trick it.. - CGContextFillRect (context, CGRectMake ((float) left, flipHeight - (y + (1.0f + 1.0f / 256.0f)), (float) (right - left), 1.0f + 1.0f / 256.0f)); + CGContextFillRect (context, CGRectMake (left, flipHeight - (y + (1.0f + 1.0f / 256.0f)), right - left, 1.0f + 1.0f / 256.0f)); #endif } @@ -262379,23 +262386,12 @@ private: { switch (i.elementType) { - case Path::Iterator::startNewSubPath: - CGContextMoveToPoint (context, i.x1, i.y1); - break; - case Path::Iterator::lineTo: - CGContextAddLineToPoint (context, i.x1, i.y1); - break; - case Path::Iterator::quadraticTo: - CGContextAddQuadCurveToPoint (context, i.x1, i.y1, i.x2, i.y2); - break; - case Path::Iterator::cubicTo: - CGContextAddCurveToPoint (context, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); - break; - case Path::Iterator::closePath: - CGContextClosePath (context); break; - default: - jassertfalse - break; + case Path::Iterator::startNewSubPath: CGContextMoveToPoint (context, i.x1, i.y1); break; + case Path::Iterator::lineTo: CGContextAddLineToPoint (context, i.x1, i.y1); break; + case Path::Iterator::quadraticTo: CGContextAddQuadCurveToPoint (context, i.x1, i.y1, i.x2, i.y2); break; + case Path::Iterator::cubicTo: CGContextAddCurveToPoint (context, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); break; + case Path::Iterator::closePath: CGContextClosePath (context); break; + default: jassertfalse; break; } } } @@ -266856,7 +266852,7 @@ public: CGContextRestoreGState (context); } - void drawLine (double x1, double y1, double x2, double y2) + void drawLine (const Line& line) { CGContextSetLineCap (context, kCGLineCapSquare); CGContextSetLineWidth (context, 1.0f); @@ -266864,31 +266860,31 @@ public: state->fillType.colour.getFloatRed(), state->fillType.colour.getFloatGreen(), state->fillType.colour.getFloatBlue(), state->fillType.colour.getFloatAlpha()); - CGPoint line[] = { { (CGFloat) x1, flipHeight - (CGFloat) y1 }, - { (CGFloat) x2, flipHeight - (CGFloat) y2 } }; + CGPoint cgLine[] = { { (CGFloat) line.getStartX(), flipHeight - (CGFloat) line.getStartY() }, + { (CGFloat) line.getEndX(), flipHeight - (CGFloat) line.getEndY() } }; - CGContextStrokeLineSegments (context, line, 1); + CGContextStrokeLineSegments (context, cgLine, 1); } - void drawVerticalLine (const int x, double top, double bottom) + void drawVerticalLine (const int x, float top, float bottom) { #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 - CGContextFillRect (context, CGRectMake (x, flipHeight - (float) bottom, 1.0f, (float) (bottom - top))); + CGContextFillRect (context, CGRectMake (x, flipHeight - bottom, 1.0f, bottom - top)); #else // On Leopard, unless both co-ordinates are non-integer, it disables anti-aliasing, so nudge // the x co-ord slightly to trick it.. - CGContextFillRect (context, CGRectMake (x + 1.0f / 256.0f, flipHeight - (float) bottom, 1.0f + 1.0f / 256.0f, (float) (bottom - top))); + CGContextFillRect (context, CGRectMake (x + 1.0f / 256.0f, flipHeight - bottom, 1.0f + 1.0f / 256.0f, bottom - top)); #endif } - void drawHorizontalLine (const int y, double left, double right) + void drawHorizontalLine (const int y, float left, float right) { #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 - CGContextFillRect (context, CGRectMake ((float) left, flipHeight - (y + 1.0f), (float) (right - left), 1.0f)); + CGContextFillRect (context, CGRectMake (left, flipHeight - (y + 1.0f), right - left, 1.0f)); #else // On Leopard, unless both co-ordinates are non-integer, it disables anti-aliasing, so nudge // the x co-ord slightly to trick it.. - CGContextFillRect (context, CGRectMake ((float) left, flipHeight - (y + (1.0f + 1.0f / 256.0f)), (float) (right - left), 1.0f + 1.0f / 256.0f)); + CGContextFillRect (context, CGRectMake (left, flipHeight - (y + (1.0f + 1.0f / 256.0f)), right - left, 1.0f + 1.0f / 256.0f)); #endif } @@ -267053,23 +267049,12 @@ private: { switch (i.elementType) { - case Path::Iterator::startNewSubPath: - CGContextMoveToPoint (context, i.x1, i.y1); - break; - case Path::Iterator::lineTo: - CGContextAddLineToPoint (context, i.x1, i.y1); - break; - case Path::Iterator::quadraticTo: - CGContextAddQuadCurveToPoint (context, i.x1, i.y1, i.x2, i.y2); - break; - case Path::Iterator::cubicTo: - CGContextAddCurveToPoint (context, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); - break; - case Path::Iterator::closePath: - CGContextClosePath (context); break; - default: - jassertfalse - break; + case Path::Iterator::startNewSubPath: CGContextMoveToPoint (context, i.x1, i.y1); break; + case Path::Iterator::lineTo: CGContextAddLineToPoint (context, i.x1, i.y1); break; + case Path::Iterator::quadraticTo: CGContextAddQuadCurveToPoint (context, i.x1, i.y1, i.x2, i.y2); break; + case Path::Iterator::cubicTo: CGContextAddCurveToPoint (context, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); break; + case Path::Iterator::closePath: CGContextClosePath (context); break; + default: jassertfalse; break; } } } diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 6909a65619..0e67680337 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -5716,7 +5716,7 @@ public: }; /* - The following code allows the atomics to be performed as inline functions where possible... + The following code is in the header so that the atomics can be inlined where possible... */ #if (JUCE_IPHONE && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_2 || ! defined (__IPHONE_3_2))) \ || (JUCE_MAC && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))) @@ -5773,6 +5773,11 @@ public: #endif #endif +#if JUCE_MSVC + #pragma warning (push) + #pragma warning (disable: 4311) // (truncation warning) +#endif + template inline Type Atomic::get() const throw() { @@ -5893,6 +5898,10 @@ inline void Atomic::memoryBarrier() throw() #endif } +#if JUCE_MSVC + #pragma warning (pop) +#endif + #endif // __JUCE_ATOMIC_JUCEHEADER__ /*** End of inlined file: juce_Atomic.h ***/ @@ -18756,8 +18765,6 @@ public: */ float getTranslationY() const throw() { return mat12; } - juce_UseDebuggingNewOperator - /* The transform matrix is: (mat00 mat01 mat02) @@ -18767,6 +18774,8 @@ public: float mat00, mat01, mat02; float mat10, mat11, mat12; + juce_UseDebuggingNewOperator + private: const AffineTransform followedBy (float mat00, float mat01, float mat02, @@ -57041,9 +57050,9 @@ public: virtual void drawImage (const Image& sourceImage, const Rectangle& srcClip, const AffineTransform& transform, bool fillEntireClipAsTiles) = 0; - virtual void drawLine (double x1, double y1, double x2, double y2) = 0; - virtual void drawVerticalLine (int x, double top, double bottom) = 0; - virtual void drawHorizontalLine (int y, double left, double right) = 0; + virtual void drawLine (const Line & line) = 0; + virtual void drawVerticalLine (int x, float top, float bottom) = 0; + virtual void drawHorizontalLine (int y, float left, float right) = 0; virtual void setFont (const Font& newFont) = 0; virtual const Font getFont() = 0; @@ -57103,10 +57112,10 @@ public: void drawImage (const Image& sourceImage, const Rectangle& srcClip, const AffineTransform& transform, bool fillEntireClipAsTiles); - void drawLine (double x1, double y1, double x2, double y2); + void drawLine (const Line & line); - void drawVerticalLine (int x, double top, double bottom); - void drawHorizontalLine (int x, double top, double bottom); + void drawVerticalLine (int x, float top, float bottom); + void drawHorizontalLine (int x, float top, float bottom); const Font getFont(); void setFont (const Font& newFont); @@ -57159,8 +57168,6 @@ protected: #ifndef __JUCE_LOWLEVELGRAPHICSSOFTWARERENDERER_JUCEHEADER__ #define __JUCE_LOWLEVELGRAPHICSSOFTWARERENDERER_JUCEHEADER__ -class LLGCSavedState; - /** A lowest-common-denominator implementation of LowLevelGraphicsContext that does all its rendering in memory. @@ -57203,10 +57210,10 @@ public: void drawImage (const Image& sourceImage, const Rectangle& srcClip, const AffineTransform& transform, bool fillEntireClipAsTiles); - void drawLine (double x1, double y1, double x2, double y2); + void drawLine (const Line & line); - void drawVerticalLine (int x, double top, double bottom); - void drawHorizontalLine (int x, double top, double bottom); + void drawVerticalLine (int x, float top, float bottom); + void drawHorizontalLine (int x, float top, float bottom); void setFont (const Font& newFont); const Font getFont(); @@ -57219,8 +57226,14 @@ protected: Image& image; - ScopedPointer currentState; - OwnedArray stateStack; + class GlyphCache; + class CachedGlyph; + class SavedState; + friend class ScopedPointer ; + friend class OwnedArray ; + friend class OwnedArray ; + ScopedPointer currentState; + OwnedArray stateStack; LowLevelGraphicsSoftwareRenderer (const LowLevelGraphicsSoftwareRenderer& other); LowLevelGraphicsSoftwareRenderer& operator= (const LowLevelGraphicsSoftwareRenderer&); @@ -57815,14 +57828,10 @@ public: */ bool next(); - /** The x position of the start of the current line segment. */ - float x1; - /** The y position of the start of the current line segment. */ - float y1; - /** The x position of the end of the current line segment. */ - float x2; - /** The y position of the end of the current line segment. */ - float y2; + float x1; /**< The x position of the start of the current line segment. */ + float y1; /**< The y position of the start of the current line segment. */ + float x2; /**< The x position of the end of the current line segment. */ + float y2; /**< The y position of the end of the current line segment. */ /** Indicates whether the current line segment is closing a sub-path. @@ -57839,9 +57848,8 @@ public: int subPathIndex; /** Returns true if the current segment is the last in the current sub-path. */ - bool isLastInSubpath() const { return stackPos == stackBase.getData() - && (index >= path.numElements - || points [index] == Path::moveMarker); } + bool isLastInSubpath() const throw() { return stackPos == stackBase.getData() + && (index >= path.numElements || points [index] == Path::moveMarker); } juce_UseDebuggingNewOperator diff --git a/src/audio/audio_file_formats/juce_FlacAudioFormat.cpp b/src/audio/audio_file_formats/juce_FlacAudioFormat.cpp index eebfed7267..75b1869558 100644 --- a/src/audio/audio_file_formats/juce_FlacAudioFormat.cpp +++ b/src/audio/audio_file_formats/juce_FlacAudioFormat.cpp @@ -34,14 +34,13 @@ #include "../../core/juce_StandardHeader.h" -#ifdef _MSC_VER - #pragma warning (disable : 4505) - #pragma warning (push) -#endif - namespace FlacNamespace { #if JUCE_INCLUDE_FLAC_CODE + #if JUCE_MSVC + #pragma warning (disable : 4505) // (unreferenced static function removal warning) + #endif + #define FLAC__NO_DLL 1 #if ! defined (SIZE_MAX) @@ -73,10 +72,6 @@ namespace FlacNamespace #undef max #undef min -#ifdef _MSC_VER - #pragma warning (pop) -#endif - BEGIN_JUCE_NAMESPACE #include "juce_FlacAudioFormat.h" diff --git a/src/audio/plugins/formats/juce_VSTPluginFormat.cpp b/src/audio/plugins/formats/juce_VSTPluginFormat.cpp index 806f0d477d..3e862fae9c 100644 --- a/src/audio/plugins/formats/juce_VSTPluginFormat.cpp +++ b/src/audio/plugins/formats/juce_VSTPluginFormat.cpp @@ -84,7 +84,7 @@ BEGIN_JUCE_NAMESPACE #undef PRAGMA_ALIGN_SUPPORTED #define VST_FORCE_DEPRECATED 0 -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (push) #pragma warning (disable: 4996) #endif @@ -97,7 +97,7 @@ BEGIN_JUCE_NAMESPACE */ #include "pluginterfaces/vst2.x/aeffectx.h" -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (pop) #endif @@ -2311,14 +2311,14 @@ VstIntPtr VSTPluginInstance::handleCallback (VstInt32 opcode, VstInt32 index, Vs break; case audioMasterGetTime: - #ifdef _MSC_VER + #if JUCE_MSVC #pragma warning (push) #pragma warning (disable: 4311) #endif return (VstIntPtr) &vstHostTime; - #ifdef _MSC_VER + #if JUCE_MSVC #pragma warning (pop) #endif break; diff --git a/src/core/juce_Atomic.h b/src/core/juce_Atomic.h index 8ed20ac8bb..f5299aa8b5 100644 --- a/src/core/juce_Atomic.h +++ b/src/core/juce_Atomic.h @@ -150,7 +150,7 @@ public: //============================================================================== /* - The following code allows the atomics to be performed as inline functions where possible... + The following code is in the header so that the atomics can be inlined where possible... */ #if (JUCE_IPHONE && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_2 || ! defined (__IPHONE_3_2))) \ || (JUCE_MAC && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))) @@ -208,6 +208,11 @@ public: #endif #endif +#if JUCE_MSVC + #pragma warning (push) + #pragma warning (disable: 4311) // (truncation warning) +#endif + //============================================================================== template inline Type Atomic::get() const throw() @@ -329,5 +334,8 @@ inline void Atomic::memoryBarrier() throw() #endif } +#if JUCE_MSVC + #pragma warning (pop) +#endif #endif // __JUCE_ATOMIC_JUCEHEADER__ diff --git a/src/core/juce_Time.cpp b/src/core/juce_Time.cpp index e0145c9c7b..541432a2a8 100644 --- a/src/core/juce_Time.cpp +++ b/src/core/juce_Time.cpp @@ -23,13 +23,13 @@ ============================================================================== */ -#ifdef _MSC_VER - #pragma warning (disable: 4514) - #pragma warning (push) -#endif - #include "juce_StandardHeader.h" +#if JUCE_MSVC + #pragma warning (push) + #pragma warning (disable: 4514) +#endif + #ifndef JUCE_WINDOWS #include #else @@ -38,15 +38,7 @@ #include -BEGIN_JUCE_NAMESPACE - - -#include "juce_Time.h" -#include "../threads/juce_Thread.h" -#include "../containers/juce_MemoryBlock.h" -#include "../text/juce_LocalisedStrings.h" - -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (pop) #ifdef _INC_TIME_INL @@ -54,6 +46,13 @@ BEGIN_JUCE_NAMESPACE #endif #endif +BEGIN_JUCE_NAMESPACE + +#include "juce_Time.h" +#include "../threads/juce_Thread.h" +#include "../containers/juce_MemoryBlock.h" +#include "../text/juce_LocalisedStrings.h" + //============================================================================== namespace TimeHelpers { diff --git a/src/gui/graphics/contexts/juce_EdgeTable.cpp b/src/gui/graphics/contexts/juce_EdgeTable.cpp index bade51c873..5502384bcf 100644 --- a/src/gui/graphics/contexts/juce_EdgeTable.cpp +++ b/src/gui/graphics/contexts/juce_EdgeTable.cpp @@ -1,757 +1,757 @@ -/* - ============================================================================== - - This file is part of the JUCE library - "Jules' Utility Class Extensions" - Copyright 2004-10 by Raw Material Software Ltd. - - ------------------------------------------------------------------------------ - - JUCE can be redistributed and/or modified under the terms of the GNU General - Public License (Version 2), as published by the Free Software Foundation. - A copy of the license is included in the JUCE distribution, or can be found - online at www.gnu.org/licenses. - - JUCE is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - To release a closed-source product which uses JUCE, commercial licenses are - available: visit www.rawmaterialsoftware.com/juce for more information. - - ============================================================================== -*/ - -#include "../../../core/juce_StandardHeader.h" - -BEGIN_JUCE_NAMESPACE - -#include "juce_EdgeTable.h" -#include "../geometry/juce_PathIterator.h" -#include "../imaging/juce_Image.h" -#include "../geometry/juce_RectangleList.h" - -const int juce_edgeTableDefaultEdgesPerLine = 32; - -//============================================================================== -EdgeTable::EdgeTable (const Rectangle& bounds_, - const Path& path, const AffineTransform& transform) - : bounds (bounds_), - maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), - lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), - needToCheckEmptinesss (true) -{ - table.malloc ((bounds.getHeight() + 1) * lineStrideElements); - int* t = table; - - for (int i = bounds.getHeight(); --i >= 0;) - { - *t = 0; - t += lineStrideElements; - } - - const int topLimit = bounds.getY() << 8; - const int heightLimit = bounds.getHeight() << 8; - const int leftLimit = bounds.getX() << 8; - const int rightLimit = bounds.getRight() << 8; - - PathFlatteningIterator iter (path, transform); - - while (iter.next()) - { - int y1 = roundToInt (iter.y1 * 256.0f); - int y2 = roundToInt (iter.y2 * 256.0f); - - if (y1 != y2) - { - y1 -= topLimit; - y2 -= topLimit; - - const int startY = y1; - int direction = -1; - - if (y1 > y2) - { - swapVariables (y1, y2); - direction = 1; - } - - if (y1 < 0) - y1 = 0; - - if (y2 > heightLimit) - y2 = heightLimit; - - if (y1 < y2) - { - const double startX = 256.0f * iter.x1; - const double multiplier = (iter.x2 - iter.x1) / (iter.y2 - iter.y1); - const int stepSize = jlimit (1, 256, 256 / (1 + (int) std::abs (multiplier))); - - do - { - const int step = jmin (stepSize, y2 - y1, 256 - (y1 & 255)); - int x = roundToInt (startX + multiplier * ((y1 + (step >> 1)) - startY)); - - if (x < leftLimit) - x = leftLimit; - else if (x >= rightLimit) - x = rightLimit - 1; - - addEdgePoint (x, y1 >> 8, direction * step); - y1 += step; - } - while (y1 < y2); - } - } - } - - sanitiseLevels (path.isUsingNonZeroWinding()); -} - -EdgeTable::EdgeTable (const Rectangle& rectangleToAdd) - : bounds (rectangleToAdd), - maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), - lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), - needToCheckEmptinesss (true) -{ - table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); - table[0] = 0; - - const int x1 = rectangleToAdd.getX() << 8; - const int x2 = rectangleToAdd.getRight() << 8; - - int* t = table; - for (int i = rectangleToAdd.getHeight(); --i >= 0;) - { - t[0] = 2; - t[1] = x1; - t[2] = 255; - t[3] = x2; - t[4] = 0; - t += lineStrideElements; - } -} - -EdgeTable::EdgeTable (const RectangleList& rectanglesToAdd) - : bounds (rectanglesToAdd.getBounds()), - maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), - lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), - needToCheckEmptinesss (true) -{ - table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); - - int* t = table; - for (int i = bounds.getHeight(); --i >= 0;) - { - *t = 0; - t += lineStrideElements; - } - - for (RectangleList::Iterator iter (rectanglesToAdd); iter.next();) - { - const Rectangle* const r = iter.getRectangle(); - - const int x1 = r->getX() << 8; - const int x2 = r->getRight() << 8; - int y = r->getY() - bounds.getY(); - - for (int j = r->getHeight(); --j >= 0;) - { - addEdgePoint (x1, y, 255); - addEdgePoint (x2, y, -255); - ++y; - } - } - - sanitiseLevels (true); -} - -EdgeTable::EdgeTable (const Rectangle& rectangleToAdd) - : bounds (Rectangle ((int) std::floor (rectangleToAdd.getX()), - roundToInt (rectangleToAdd.getY() * 256.0f) >> 8, - 2 + (int) rectangleToAdd.getWidth(), - 2 + (int) rectangleToAdd.getHeight())), - maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), - lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), - needToCheckEmptinesss (true) -{ - jassert (! rectangleToAdd.isEmpty()); - table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); - table[0] = 0; - - const int x1 = roundToInt (rectangleToAdd.getX() * 256.0f); - const int x2 = roundToInt (rectangleToAdd.getRight() * 256.0f); - - int y1 = roundToInt (rectangleToAdd.getY() * 256.0f) - (bounds.getY() << 8); - jassert (y1 < 256); - int y2 = roundToInt (rectangleToAdd.getBottom() * 256.0f) - (bounds.getY() << 8); - - if (x2 <= x1 || y2 <= y1) - { - bounds.setHeight (0); - return; - } - - int lineY = 0; - int* t = table; - - if ((y1 >> 8) == (y2 >> 8)) - { - t[0] = 2; - t[1] = x1; - t[2] = y2 - y1; - t[3] = x2; - t[4] = 0; - ++lineY; - t += lineStrideElements; - } - else - { - t[0] = 2; - t[1] = x1; - t[2] = 255 - (y1 & 255); - t[3] = x2; - t[4] = 0; - ++lineY; - t += lineStrideElements; - - while (lineY < (y2 >> 8)) - { - t[0] = 2; - t[1] = x1; - t[2] = 255; - t[3] = x2; - t[4] = 0; - ++lineY; - t += lineStrideElements; - } - - jassert (lineY < bounds.getHeight()); - t[0] = 2; - t[1] = x1; - t[2] = y2 & 255; - t[3] = x2; - t[4] = 0; - ++lineY; - t += lineStrideElements; - } - - while (lineY < bounds.getHeight()) - { - t[0] = 0; - t += lineStrideElements; - ++lineY; - } -} - -EdgeTable::EdgeTable (const EdgeTable& other) -{ - operator= (other); -} - -EdgeTable& EdgeTable::operator= (const EdgeTable& other) -{ - bounds = other.bounds; - maxEdgesPerLine = other.maxEdgesPerLine; - lineStrideElements = other.lineStrideElements; - needToCheckEmptinesss = other.needToCheckEmptinesss; - - table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); - copyEdgeTableData (table, lineStrideElements, other.table, lineStrideElements, bounds.getHeight()); - return *this; -} - -EdgeTable::~EdgeTable() -{ -} - -//============================================================================== -void EdgeTable::copyEdgeTableData (int* dest, const int destLineStride, const int* src, const int srcLineStride, int numLines) throw() -{ - while (--numLines >= 0) - { - memcpy (dest, src, (src[0] * 2 + 1) * sizeof (int)); - src += srcLineStride; - dest += destLineStride; - } -} - -void EdgeTable::sanitiseLevels (const bool useNonZeroWinding) throw() -{ - // Convert the table from relative windings to absolute levels.. - int* lineStart = table; - - for (int i = bounds.getHeight(); --i >= 0;) - { - int* line = lineStart; - lineStart += lineStrideElements; - - int num = *line; - if (num == 0) - continue; - - int level = 0; - - if (useNonZeroWinding) - { - while (--num > 0) - { - line += 2; - level += *line; - int corrected = abs (level); - if (corrected >> 8) - corrected = 255; - - *line = corrected; - } - } - else - { - while (--num > 0) - { - line += 2; - level += *line; - int corrected = abs (level); - if (corrected >> 8) - { - corrected &= 511; - if (corrected >> 8) - corrected = 511 - corrected; - } - - *line = corrected; - } - } - - line[2] = 0; // force the last level to 0, just in case something went wrong in creating the table - } -} - -void EdgeTable::remapTableForNumEdges (const int newNumEdgesPerLine) throw() -{ - if (newNumEdgesPerLine != maxEdgesPerLine) - { - maxEdgesPerLine = newNumEdgesPerLine; - - jassert (bounds.getHeight() > 0); - const int newLineStrideElements = maxEdgesPerLine * 2 + 1; - - HeapBlock newTable (bounds.getHeight() * newLineStrideElements); - - copyEdgeTableData (newTable, newLineStrideElements, table, lineStrideElements, bounds.getHeight()); - - table.swapWith (newTable); - lineStrideElements = newLineStrideElements; - } -} - -void EdgeTable::optimiseTable() throw() -{ - int maxLineElements = 0; - - for (int i = bounds.getHeight(); --i >= 0;) - maxLineElements = jmax (maxLineElements, table [i * lineStrideElements]); - - remapTableForNumEdges (maxLineElements); -} - -void EdgeTable::addEdgePoint (const int x, const int y, const int winding) throw() -{ - jassert (y >= 0 && y < bounds.getHeight()); - - int* line = table + lineStrideElements * y; - const int numPoints = line[0]; - int n = numPoints << 1; - - if (n > 0) - { - while (n > 0) - { - const int cx = line [n - 1]; - - if (cx <= x) - { - if (cx == x) - { - line [n] += winding; - return; - } - - break; - } - - n -= 2; - } - - if (numPoints >= maxEdgesPerLine) - { - remapTableForNumEdges (maxEdgesPerLine + juce_edgeTableDefaultEdgesPerLine); - jassert (numPoints < maxEdgesPerLine); - line = table + lineStrideElements * y; - } - - memmove (line + (n + 3), line + (n + 1), sizeof (int) * ((numPoints << 1) - n)); - } - - line [n + 1] = x; - line [n + 2] = winding; - line[0]++; -} - -void EdgeTable::translate (float dx, const int dy) throw() -{ - bounds.translate ((int) std::floor (dx), dy); - - int* lineStart = table; - const int intDx = (int) (dx * 256.0f); - - for (int i = bounds.getHeight(); --i >= 0;) - { - int* line = lineStart; - lineStart += lineStrideElements; - int num = *line++; - - while (--num >= 0) - { - *line += intDx; - line += 2; - } - } -} - -void EdgeTable::intersectWithEdgeTableLine (const int y, const int* otherLine) throw() -{ - jassert (y >= 0 && y < bounds.getHeight()); - - int* dest = table + lineStrideElements * y; - if (dest[0] == 0) - return; - - int otherNumPoints = *otherLine; - if (otherNumPoints == 0) - { - *dest = 0; - return; - } - - const int right = bounds.getRight() << 8; - - // optimise for the common case where our line lies entirely within a - // single pair of points, as happens when clipping to a simple rect. - if (otherNumPoints == 2 && otherLine[2] >= 255) - { - clipEdgeTableLineToRange (dest, otherLine[1], jmin (right, otherLine[3])); - return; - } - - ++otherLine; - const size_t lineSizeBytes = (dest[0] * 2 + 1) * sizeof (int); - int* temp = (int*) alloca (lineSizeBytes); - memcpy (temp, dest, lineSizeBytes); - - const int* src1 = temp; - int srcNum1 = *src1++; - int x1 = *src1++; - - const int* src2 = otherLine; - int srcNum2 = otherNumPoints; - int x2 = *src2++; - - int destIndex = 0, destTotal = 0; - int level1 = 0, level2 = 0; - int lastX = std::numeric_limits::min(), lastLevel = 0; - - while (srcNum1 > 0 && srcNum2 > 0) - { - int nextX; - - if (x1 < x2) - { - nextX = x1; - level1 = *src1++; - x1 = *src1++; - --srcNum1; - } - else if (x1 == x2) - { - nextX = x1; - level1 = *src1++; - level2 = *src2++; - x1 = *src1++; - x2 = *src2++; - --srcNum1; - --srcNum2; - } - else - { - nextX = x2; - level2 = *src2++; - x2 = *src2++; - --srcNum2; - } - - if (nextX > lastX) - { - if (nextX >= right) - break; - - lastX = nextX; - - const int nextLevel = (level1 * (level2 + 1)) >> 8; - jassert (((unsigned int) nextLevel) < (unsigned int) 256); - - if (nextLevel != lastLevel) - { - if (destTotal >= maxEdgesPerLine) - { - dest[0] = destTotal; - remapTableForNumEdges (maxEdgesPerLine + juce_edgeTableDefaultEdgesPerLine); - dest = table + lineStrideElements * y; - } - - ++destTotal; - lastLevel = nextLevel; - dest[++destIndex] = nextX; - dest[++destIndex] = nextLevel; - } - } - } - - if (lastLevel > 0) - { - if (destTotal >= maxEdgesPerLine) - { - dest[0] = destTotal; - remapTableForNumEdges (maxEdgesPerLine + juce_edgeTableDefaultEdgesPerLine); - dest = table + lineStrideElements * y; - } - - ++destTotal; - dest[++destIndex] = right; - dest[++destIndex] = 0; - } - - dest[0] = destTotal; - -#if JUCE_DEBUG - int last = std::numeric_limits::min(); - for (int i = 0; i < dest[0]; ++i) - { - jassert (dest[i * 2 + 1] > last); - last = dest[i * 2 + 1]; - } - - jassert (dest [dest[0] * 2] == 0); -#endif -} - -void EdgeTable::clipEdgeTableLineToRange (int* dest, const int x1, const int x2) throw() -{ - int* lastItem = dest + (dest[0] * 2 - 1); - - if (x2 < lastItem[0]) - { - if (x2 <= dest[1]) - { - dest[0] = 0; - return; - } - - while (x2 < lastItem[-2]) - { - --(dest[0]); - lastItem -= 2; - } - - lastItem[0] = x2; - lastItem[1] = 0; - } - - if (x1 > dest[1]) - { - while (lastItem[0] > x1) - lastItem -= 2; - - const int itemsRemoved = (int) (lastItem - (dest + 1)) / 2; - - if (itemsRemoved > 0) - { - dest[0] -= itemsRemoved; - memmove (dest + 1, lastItem, dest[0] * (sizeof (int) * 2)); - } - - dest[1] = x1; - } -} - - -//============================================================================== -void EdgeTable::clipToRectangle (const Rectangle& r) throw() -{ - const Rectangle clipped (r.getIntersection (bounds)); - - if (clipped.isEmpty()) - { - needToCheckEmptinesss = false; - bounds.setHeight (0); - } - else - { - const int top = clipped.getY() - bounds.getY(); - const int bottom = clipped.getBottom() - bounds.getY(); - - if (bottom < bounds.getHeight()) - bounds.setHeight (bottom); - - if (clipped.getRight() < bounds.getRight()) - bounds.setRight (clipped.getRight()); - - for (int i = top; --i >= 0;) - table [lineStrideElements * i] = 0; - - if (clipped.getX() > bounds.getX()) - { - const int x1 = clipped.getX() << 8; - const int x2 = jmin (bounds.getRight(), clipped.getRight()) << 8; - int* line = table + lineStrideElements * top; - - for (int i = bottom - top; --i >= 0;) - { - if (line[0] != 0) - clipEdgeTableLineToRange (line, x1, x2); - - line += lineStrideElements; - } - } - - needToCheckEmptinesss = true; - } -} - -void EdgeTable::excludeRectangle (const Rectangle& r) throw() -{ - const Rectangle clipped (r.getIntersection (bounds)); - - if (! clipped.isEmpty()) - { - const int top = clipped.getY() - bounds.getY(); - const int bottom = clipped.getBottom() - bounds.getY(); - - //XXX optimise here by shortening the table if it fills top or bottom - - const int rectLine[] = { 4, std::numeric_limits::min(), 255, - clipped.getX() << 8, 0, - clipped.getRight() << 8, 255, - std::numeric_limits::max(), 0 }; - - for (int i = top; i < bottom; ++i) - intersectWithEdgeTableLine (i, rectLine); - - needToCheckEmptinesss = true; - } -} - -void EdgeTable::clipToEdgeTable (const EdgeTable& other) -{ - const Rectangle clipped (other.bounds.getIntersection (bounds)); - - if (clipped.isEmpty()) - { - needToCheckEmptinesss = false; - bounds.setHeight (0); - } - else - { - const int top = clipped.getY() - bounds.getY(); - const int bottom = clipped.getBottom() - bounds.getY(); - - if (bottom < bounds.getHeight()) - bounds.setHeight (bottom); - - if (clipped.getRight() < bounds.getRight()) - bounds.setRight (clipped.getRight()); - - int i = 0; - for (i = top; --i >= 0;) - table [lineStrideElements * i] = 0; - - const int* otherLine = other.table + other.lineStrideElements * (clipped.getY() - other.bounds.getY()); - - for (i = top; i < bottom; ++i) - { - intersectWithEdgeTableLine (i, otherLine); - otherLine += other.lineStrideElements; - } - - needToCheckEmptinesss = true; - } -} - -void EdgeTable::clipLineToMask (int x, int y, const uint8* mask, int maskStride, int numPixels) throw() -{ - y -= bounds.getY(); - - if (y < 0 || y >= bounds.getHeight()) - return; - - needToCheckEmptinesss = true; - - if (numPixels <= 0) - { - table [lineStrideElements * y] = 0; - return; - } - - int* tempLine = (int*) alloca ((numPixels * 2 + 4) * sizeof (int)); - int destIndex = 0, lastLevel = 0; - - while (--numPixels >= 0) - { - const int alpha = *mask; - mask += maskStride; - - if (alpha != lastLevel) - { - tempLine[++destIndex] = (x << 8); - tempLine[++destIndex] = alpha; - lastLevel = alpha; - } - - ++x; - } - - if (lastLevel > 0) - { - tempLine[++destIndex] = (x << 8); - tempLine[++destIndex] = 0; - } - - tempLine[0] = destIndex >> 1; - - intersectWithEdgeTableLine (y, tempLine); -} - -bool EdgeTable::isEmpty() throw() -{ - if (needToCheckEmptinesss) - { - needToCheckEmptinesss = false; - int* t = table; - - for (int i = bounds.getHeight(); --i >= 0;) - { - if (t[0] > 1) - return false; - - t += lineStrideElements; - } - - bounds.setHeight (0); - } - - return bounds.getHeight() == 0; -} - -END_JUCE_NAMESPACE +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-10 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online at www.gnu.org/licenses. + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +#include "../../../core/juce_StandardHeader.h" + +BEGIN_JUCE_NAMESPACE + +#include "juce_EdgeTable.h" +#include "../geometry/juce_PathIterator.h" +#include "../imaging/juce_Image.h" +#include "../geometry/juce_RectangleList.h" + +const int juce_edgeTableDefaultEdgesPerLine = 32; + +//============================================================================== +EdgeTable::EdgeTable (const Rectangle& bounds_, + const Path& path, const AffineTransform& transform) + : bounds (bounds_), + maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), + lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), + needToCheckEmptinesss (true) +{ + table.malloc ((bounds.getHeight() + 1) * lineStrideElements); + int* t = table; + + for (int i = bounds.getHeight(); --i >= 0;) + { + *t = 0; + t += lineStrideElements; + } + + const int topLimit = bounds.getY() << 8; + const int heightLimit = bounds.getHeight() << 8; + const int leftLimit = bounds.getX() << 8; + const int rightLimit = bounds.getRight() << 8; + + PathFlatteningIterator iter (path, transform); + + while (iter.next()) + { + int y1 = roundToInt (iter.y1 * 256.0f); + int y2 = roundToInt (iter.y2 * 256.0f); + + if (y1 != y2) + { + y1 -= topLimit; + y2 -= topLimit; + + const int startY = y1; + int direction = -1; + + if (y1 > y2) + { + swapVariables (y1, y2); + direction = 1; + } + + if (y1 < 0) + y1 = 0; + + if (y2 > heightLimit) + y2 = heightLimit; + + if (y1 < y2) + { + const double startX = 256.0f * iter.x1; + const double multiplier = (iter.x2 - iter.x1) / (iter.y2 - iter.y1); + const int stepSize = jlimit (1, 256, 256 / (1 + (int) std::abs (multiplier))); + + do + { + const int step = jmin (stepSize, y2 - y1, 256 - (y1 & 255)); + int x = roundToInt (startX + multiplier * ((y1 + (step >> 1)) - startY)); + + if (x < leftLimit) + x = leftLimit; + else if (x >= rightLimit) + x = rightLimit - 1; + + addEdgePoint (x, y1 >> 8, direction * step); + y1 += step; + } + while (y1 < y2); + } + } + } + + sanitiseLevels (path.isUsingNonZeroWinding()); +} + +EdgeTable::EdgeTable (const Rectangle& rectangleToAdd) + : bounds (rectangleToAdd), + maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), + lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), + needToCheckEmptinesss (true) +{ + table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); + table[0] = 0; + + const int x1 = rectangleToAdd.getX() << 8; + const int x2 = rectangleToAdd.getRight() << 8; + + int* t = table; + for (int i = rectangleToAdd.getHeight(); --i >= 0;) + { + t[0] = 2; + t[1] = x1; + t[2] = 255; + t[3] = x2; + t[4] = 0; + t += lineStrideElements; + } +} + +EdgeTable::EdgeTable (const RectangleList& rectanglesToAdd) + : bounds (rectanglesToAdd.getBounds()), + maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), + lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), + needToCheckEmptinesss (true) +{ + table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); + + int* t = table; + for (int i = bounds.getHeight(); --i >= 0;) + { + *t = 0; + t += lineStrideElements; + } + + for (RectangleList::Iterator iter (rectanglesToAdd); iter.next();) + { + const Rectangle* const r = iter.getRectangle(); + + const int x1 = r->getX() << 8; + const int x2 = r->getRight() << 8; + int y = r->getY() - bounds.getY(); + + for (int j = r->getHeight(); --j >= 0;) + { + addEdgePoint (x1, y, 255); + addEdgePoint (x2, y, -255); + ++y; + } + } + + sanitiseLevels (true); +} + +EdgeTable::EdgeTable (const Rectangle& rectangleToAdd) + : bounds (Rectangle ((int) std::floor (rectangleToAdd.getX()), + roundToInt (rectangleToAdd.getY() * 256.0f) >> 8, + 2 + (int) rectangleToAdd.getWidth(), + 2 + (int) rectangleToAdd.getHeight())), + maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), + lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), + needToCheckEmptinesss (true) +{ + jassert (! rectangleToAdd.isEmpty()); + table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); + table[0] = 0; + + const int x1 = roundToInt (rectangleToAdd.getX() * 256.0f); + const int x2 = roundToInt (rectangleToAdd.getRight() * 256.0f); + + int y1 = roundToInt (rectangleToAdd.getY() * 256.0f) - (bounds.getY() << 8); + jassert (y1 < 256); + int y2 = roundToInt (rectangleToAdd.getBottom() * 256.0f) - (bounds.getY() << 8); + + if (x2 <= x1 || y2 <= y1) + { + bounds.setHeight (0); + return; + } + + int lineY = 0; + int* t = table; + + if ((y1 >> 8) == (y2 >> 8)) + { + t[0] = 2; + t[1] = x1; + t[2] = y2 - y1; + t[3] = x2; + t[4] = 0; + ++lineY; + t += lineStrideElements; + } + else + { + t[0] = 2; + t[1] = x1; + t[2] = 255 - (y1 & 255); + t[3] = x2; + t[4] = 0; + ++lineY; + t += lineStrideElements; + + while (lineY < (y2 >> 8)) + { + t[0] = 2; + t[1] = x1; + t[2] = 255; + t[3] = x2; + t[4] = 0; + ++lineY; + t += lineStrideElements; + } + + jassert (lineY < bounds.getHeight()); + t[0] = 2; + t[1] = x1; + t[2] = y2 & 255; + t[3] = x2; + t[4] = 0; + ++lineY; + t += lineStrideElements; + } + + while (lineY < bounds.getHeight()) + { + t[0] = 0; + t += lineStrideElements; + ++lineY; + } +} + +EdgeTable::EdgeTable (const EdgeTable& other) +{ + operator= (other); +} + +EdgeTable& EdgeTable::operator= (const EdgeTable& other) +{ + bounds = other.bounds; + maxEdgesPerLine = other.maxEdgesPerLine; + lineStrideElements = other.lineStrideElements; + needToCheckEmptinesss = other.needToCheckEmptinesss; + + table.malloc (jmax (1, bounds.getHeight()) * lineStrideElements); + copyEdgeTableData (table, lineStrideElements, other.table, lineStrideElements, bounds.getHeight()); + return *this; +} + +EdgeTable::~EdgeTable() +{ +} + +//============================================================================== +void EdgeTable::copyEdgeTableData (int* dest, const int destLineStride, const int* src, const int srcLineStride, int numLines) throw() +{ + while (--numLines >= 0) + { + memcpy (dest, src, (src[0] * 2 + 1) * sizeof (int)); + src += srcLineStride; + dest += destLineStride; + } +} + +void EdgeTable::sanitiseLevels (const bool useNonZeroWinding) throw() +{ + // Convert the table from relative windings to absolute levels.. + int* lineStart = table; + + for (int i = bounds.getHeight(); --i >= 0;) + { + int* line = lineStart; + lineStart += lineStrideElements; + + int num = *line; + if (num == 0) + continue; + + int level = 0; + + if (useNonZeroWinding) + { + while (--num > 0) + { + line += 2; + level += *line; + int corrected = abs (level); + if (corrected >> 8) + corrected = 255; + + *line = corrected; + } + } + else + { + while (--num > 0) + { + line += 2; + level += *line; + int corrected = abs (level); + if (corrected >> 8) + { + corrected &= 511; + if (corrected >> 8) + corrected = 511 - corrected; + } + + *line = corrected; + } + } + + line[2] = 0; // force the last level to 0, just in case something went wrong in creating the table + } +} + +void EdgeTable::remapTableForNumEdges (const int newNumEdgesPerLine) throw() +{ + if (newNumEdgesPerLine != maxEdgesPerLine) + { + maxEdgesPerLine = newNumEdgesPerLine; + + jassert (bounds.getHeight() > 0); + const int newLineStrideElements = maxEdgesPerLine * 2 + 1; + + HeapBlock newTable (bounds.getHeight() * newLineStrideElements); + + copyEdgeTableData (newTable, newLineStrideElements, table, lineStrideElements, bounds.getHeight()); + + table.swapWith (newTable); + lineStrideElements = newLineStrideElements; + } +} + +void EdgeTable::optimiseTable() throw() +{ + int maxLineElements = 0; + + for (int i = bounds.getHeight(); --i >= 0;) + maxLineElements = jmax (maxLineElements, table [i * lineStrideElements]); + + remapTableForNumEdges (maxLineElements); +} + +void EdgeTable::addEdgePoint (const int x, const int y, const int winding) throw() +{ + jassert (y >= 0 && y < bounds.getHeight()); + + int* line = table + lineStrideElements * y; + const int numPoints = line[0]; + int n = numPoints << 1; + + if (n > 0) + { + while (n > 0) + { + const int cx = line [n - 1]; + + if (cx <= x) + { + if (cx == x) + { + line [n] += winding; + return; + } + + break; + } + + n -= 2; + } + + if (numPoints >= maxEdgesPerLine) + { + remapTableForNumEdges (maxEdgesPerLine + juce_edgeTableDefaultEdgesPerLine); + jassert (numPoints < maxEdgesPerLine); + line = table + lineStrideElements * y; + } + + memmove (line + (n + 3), line + (n + 1), sizeof (int) * ((numPoints << 1) - n)); + } + + line [n + 1] = x; + line [n + 2] = winding; + line[0]++; +} + +void EdgeTable::translate (float dx, const int dy) throw() +{ + bounds.translate ((int) std::floor (dx), dy); + + int* lineStart = table; + const int intDx = (int) (dx * 256.0f); + + for (int i = bounds.getHeight(); --i >= 0;) + { + int* line = lineStart; + lineStart += lineStrideElements; + int num = *line++; + + while (--num >= 0) + { + *line += intDx; + line += 2; + } + } +} + +void EdgeTable::intersectWithEdgeTableLine (const int y, const int* otherLine) throw() +{ + jassert (y >= 0 && y < bounds.getHeight()); + + int* dest = table + lineStrideElements * y; + if (dest[0] == 0) + return; + + int otherNumPoints = *otherLine; + if (otherNumPoints == 0) + { + *dest = 0; + return; + } + + const int right = bounds.getRight() << 8; + + // optimise for the common case where our line lies entirely within a + // single pair of points, as happens when clipping to a simple rect. + if (otherNumPoints == 2 && otherLine[2] >= 255) + { + clipEdgeTableLineToRange (dest, otherLine[1], jmin (right, otherLine[3])); + return; + } + + ++otherLine; + const size_t lineSizeBytes = (dest[0] * 2 + 1) * sizeof (int); + int* temp = (int*) alloca (lineSizeBytes); + memcpy (temp, dest, lineSizeBytes); + + const int* src1 = temp; + int srcNum1 = *src1++; + int x1 = *src1++; + + const int* src2 = otherLine; + int srcNum2 = otherNumPoints; + int x2 = *src2++; + + int destIndex = 0, destTotal = 0; + int level1 = 0, level2 = 0; + int lastX = std::numeric_limits::min(), lastLevel = 0; + + while (srcNum1 > 0 && srcNum2 > 0) + { + int nextX; + + if (x1 < x2) + { + nextX = x1; + level1 = *src1++; + x1 = *src1++; + --srcNum1; + } + else if (x1 == x2) + { + nextX = x1; + level1 = *src1++; + level2 = *src2++; + x1 = *src1++; + x2 = *src2++; + --srcNum1; + --srcNum2; + } + else + { + nextX = x2; + level2 = *src2++; + x2 = *src2++; + --srcNum2; + } + + if (nextX > lastX) + { + if (nextX >= right) + break; + + lastX = nextX; + + const int nextLevel = (level1 * (level2 + 1)) >> 8; + jassert (((unsigned int) nextLevel) < (unsigned int) 256); + + if (nextLevel != lastLevel) + { + if (destTotal >= maxEdgesPerLine) + { + dest[0] = destTotal; + remapTableForNumEdges (maxEdgesPerLine + juce_edgeTableDefaultEdgesPerLine); + dest = table + lineStrideElements * y; + } + + ++destTotal; + lastLevel = nextLevel; + dest[++destIndex] = nextX; + dest[++destIndex] = nextLevel; + } + } + } + + if (lastLevel > 0) + { + if (destTotal >= maxEdgesPerLine) + { + dest[0] = destTotal; + remapTableForNumEdges (maxEdgesPerLine + juce_edgeTableDefaultEdgesPerLine); + dest = table + lineStrideElements * y; + } + + ++destTotal; + dest[++destIndex] = right; + dest[++destIndex] = 0; + } + + dest[0] = destTotal; + +#if JUCE_DEBUG + int last = std::numeric_limits::min(); + for (int i = 0; i < dest[0]; ++i) + { + jassert (dest[i * 2 + 1] > last); + last = dest[i * 2 + 1]; + } + + jassert (dest [dest[0] * 2] == 0); +#endif +} + +void EdgeTable::clipEdgeTableLineToRange (int* dest, const int x1, const int x2) throw() +{ + int* lastItem = dest + (dest[0] * 2 - 1); + + if (x2 < lastItem[0]) + { + if (x2 <= dest[1]) + { + dest[0] = 0; + return; + } + + while (x2 < lastItem[-2]) + { + --(dest[0]); + lastItem -= 2; + } + + lastItem[0] = x2; + lastItem[1] = 0; + } + + if (x1 > dest[1]) + { + while (lastItem[0] > x1) + lastItem -= 2; + + const int itemsRemoved = (int) (lastItem - (dest + 1)) / 2; + + if (itemsRemoved > 0) + { + dest[0] -= itemsRemoved; + memmove (dest + 1, lastItem, dest[0] * (sizeof (int) * 2)); + } + + dest[1] = x1; + } +} + + +//============================================================================== +void EdgeTable::clipToRectangle (const Rectangle& r) throw() +{ + const Rectangle clipped (r.getIntersection (bounds)); + + if (clipped.isEmpty()) + { + needToCheckEmptinesss = false; + bounds.setHeight (0); + } + else + { + const int top = clipped.getY() - bounds.getY(); + const int bottom = clipped.getBottom() - bounds.getY(); + + if (bottom < bounds.getHeight()) + bounds.setHeight (bottom); + + if (clipped.getRight() < bounds.getRight()) + bounds.setRight (clipped.getRight()); + + for (int i = top; --i >= 0;) + table [lineStrideElements * i] = 0; + + if (clipped.getX() > bounds.getX()) + { + const int x1 = clipped.getX() << 8; + const int x2 = jmin (bounds.getRight(), clipped.getRight()) << 8; + int* line = table + lineStrideElements * top; + + for (int i = bottom - top; --i >= 0;) + { + if (line[0] != 0) + clipEdgeTableLineToRange (line, x1, x2); + + line += lineStrideElements; + } + } + + needToCheckEmptinesss = true; + } +} + +void EdgeTable::excludeRectangle (const Rectangle& r) throw() +{ + const Rectangle clipped (r.getIntersection (bounds)); + + if (! clipped.isEmpty()) + { + const int top = clipped.getY() - bounds.getY(); + const int bottom = clipped.getBottom() - bounds.getY(); + + //XXX optimise here by shortening the table if it fills top or bottom + + const int rectLine[] = { 4, std::numeric_limits::min(), 255, + clipped.getX() << 8, 0, + clipped.getRight() << 8, 255, + std::numeric_limits::max(), 0 }; + + for (int i = top; i < bottom; ++i) + intersectWithEdgeTableLine (i, rectLine); + + needToCheckEmptinesss = true; + } +} + +void EdgeTable::clipToEdgeTable (const EdgeTable& other) +{ + const Rectangle clipped (other.bounds.getIntersection (bounds)); + + if (clipped.isEmpty()) + { + needToCheckEmptinesss = false; + bounds.setHeight (0); + } + else + { + const int top = clipped.getY() - bounds.getY(); + const int bottom = clipped.getBottom() - bounds.getY(); + + if (bottom < bounds.getHeight()) + bounds.setHeight (bottom); + + if (clipped.getRight() < bounds.getRight()) + bounds.setRight (clipped.getRight()); + + int i = 0; + for (i = top; --i >= 0;) + table [lineStrideElements * i] = 0; + + const int* otherLine = other.table + other.lineStrideElements * (clipped.getY() - other.bounds.getY()); + + for (i = top; i < bottom; ++i) + { + intersectWithEdgeTableLine (i, otherLine); + otherLine += other.lineStrideElements; + } + + needToCheckEmptinesss = true; + } +} + +void EdgeTable::clipLineToMask (int x, int y, const uint8* mask, int maskStride, int numPixels) throw() +{ + y -= bounds.getY(); + + if (y < 0 || y >= bounds.getHeight()) + return; + + needToCheckEmptinesss = true; + + if (numPixels <= 0) + { + table [lineStrideElements * y] = 0; + return; + } + + int* tempLine = (int*) alloca ((numPixels * 2 + 4) * sizeof (int)); + int destIndex = 0, lastLevel = 0; + + while (--numPixels >= 0) + { + const int alpha = *mask; + mask += maskStride; + + if (alpha != lastLevel) + { + tempLine[++destIndex] = (x << 8); + tempLine[++destIndex] = alpha; + lastLevel = alpha; + } + + ++x; + } + + if (lastLevel > 0) + { + tempLine[++destIndex] = (x << 8); + tempLine[++destIndex] = 0; + } + + tempLine[0] = destIndex >> 1; + + intersectWithEdgeTableLine (y, tempLine); +} + +bool EdgeTable::isEmpty() throw() +{ + if (needToCheckEmptinesss) + { + needToCheckEmptinesss = false; + int* t = table; + + for (int i = bounds.getHeight(); --i >= 0;) + { + if (t[0] > 1) + return false; + + t += lineStrideElements; + } + + bounds.setHeight (0); + } + + return bounds.getHeight() == 0; +} + +END_JUCE_NAMESPACE diff --git a/src/gui/graphics/contexts/juce_EdgeTable.h b/src/gui/graphics/contexts/juce_EdgeTable.h index 25b41c28b5..0147bde86e 100644 --- a/src/gui/graphics/contexts/juce_EdgeTable.h +++ b/src/gui/graphics/contexts/juce_EdgeTable.h @@ -1,211 +1,211 @@ -/* - ============================================================================== - - This file is part of the JUCE library - "Jules' Utility Class Extensions" - Copyright 2004-10 by Raw Material Software Ltd. - - ------------------------------------------------------------------------------ - - JUCE can be redistributed and/or modified under the terms of the GNU General - Public License (Version 2), as published by the Free Software Foundation. - A copy of the license is included in the JUCE distribution, or can be found - online at www.gnu.org/licenses. - - JUCE is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ------------------------------------------------------------------------------ - - To release a closed-source product which uses JUCE, commercial licenses are - available: visit www.rawmaterialsoftware.com/juce for more information. - - ============================================================================== -*/ - -#ifndef __JUCE_EDGETABLE_JUCEHEADER__ -#define __JUCE_EDGETABLE_JUCEHEADER__ - -#include "../geometry/juce_AffineTransform.h" -#include "../geometry/juce_Rectangle.h" -#include "../geometry/juce_RectangleList.h" -#include "../../../containers/juce_MemoryBlock.h" -class Path; -class Image; - - -//============================================================================== -/** - A table of horizontal scan-line segments - used for rasterising Paths. - - @see Path, Graphics -*/ -class JUCE_API EdgeTable -{ -public: - //============================================================================== - /** Creates an edge table containing a path. - - A table is created with a fixed vertical range, and only sections of the path - which lie within this range will be added to the table. - - @param clipLimits only the region of the path that lies within this area will be added - @param pathToAdd the path to add to the table - @param transform a transform to apply to the path being added - */ - EdgeTable (const Rectangle& clipLimits, - const Path& pathToAdd, - const AffineTransform& transform); - - /** Creates an edge table containing a rectangle. - */ - EdgeTable (const Rectangle& rectangleToAdd); - - /** Creates an edge table containing a rectangle list. - */ - EdgeTable (const RectangleList& rectanglesToAdd); - - /** Creates an edge table containing a rectangle. - */ - EdgeTable (const Rectangle& rectangleToAdd); - - /** Creates a copy of another edge table. */ - EdgeTable (const EdgeTable& other); - - /** Copies from another edge table. */ - EdgeTable& operator= (const EdgeTable& other); - - /** Destructor. */ - ~EdgeTable(); - - //============================================================================== - void clipToRectangle (const Rectangle& r) throw(); - void excludeRectangle (const Rectangle& r) throw(); - void clipToEdgeTable (const EdgeTable& other); - void clipLineToMask (int x, int y, const uint8* mask, int maskStride, int numPixels) throw(); - bool isEmpty() throw(); - const Rectangle& getMaximumBounds() const throw() { return bounds; } - void translate (float dx, int dy) throw(); - - /** Reduces the amount of space the table has allocated. - - This will shrink the table down to use as little memory as possible - useful for - read-only tables that get stored and re-used for rendering. - */ - void optimiseTable() throw(); - - - //============================================================================== - /** Iterates the lines in the table, for rendering. - - This function will iterate each line in the table, and call a user-defined class - to render each pixel or continuous line of pixels that the table contains. - - @param iterationCallback this templated class must contain the following methods: - @code - inline void setEdgeTableYPos (int y); - inline void handleEdgeTablePixel (int x, int alphaLevel) const; - inline void handleEdgeTableLine (int x, int width, int alphaLevel) const; - @endcode - (these don't necessarily have to be 'const', but it might help it go faster) - */ - template - void iterate (EdgeTableIterationCallback& iterationCallback) const throw() - { - const int* lineStart = table; - - for (int y = 0; y < bounds.getHeight(); ++y) - { - const int* line = lineStart; - lineStart += lineStrideElements; - int numPoints = line[0]; - - if (--numPoints > 0) - { - int x = *++line; - jassert ((x >> 8) >= bounds.getX() && (x >> 8) < bounds.getRight()); - int levelAccumulator = 0; - - iterationCallback.setEdgeTableYPos (bounds.getY() + y); - - while (--numPoints >= 0) - { - const int level = *++line; - jassert (((unsigned int) level) < (unsigned int) 256); - const int endX = *++line; - jassert (endX >= x); - const int endOfRun = (endX >> 8); - - if (endOfRun == (x >> 8)) - { - // small segment within the same pixel, so just save it for the next - // time round.. - levelAccumulator += (endX - x) * level; - } - else - { - // plot the fist pixel of this segment, including any accumulated - // levels from smaller segments that haven't been drawn yet - levelAccumulator += (0xff - (x & 0xff)) * level; - levelAccumulator >>= 8; - x >>= 8; - - if (levelAccumulator > 0) - { - if (levelAccumulator >> 8) - levelAccumulator = 0xff; - - iterationCallback.handleEdgeTablePixel (x, levelAccumulator); - } - - // if there's a run of similar pixels, do it all in one go.. - if (level > 0) - { - jassert (endOfRun <= bounds.getRight()); - const int numPix = endOfRun - ++x; - - if (numPix > 0) - iterationCallback.handleEdgeTableLine (x, numPix, level); - } - - // save the bit at the end to be drawn next time round the loop. - levelAccumulator = (endX & 0xff) * level; - } - - x = endX; - } - - if (levelAccumulator > 0) - { - levelAccumulator >>= 8; - if (levelAccumulator >> 8) - levelAccumulator = 0xff; - - x >>= 8; - jassert (x >= bounds.getX() && x < bounds.getRight()); - iterationCallback.handleEdgeTablePixel (x, levelAccumulator); - } - } - } - } - - //============================================================================== - juce_UseDebuggingNewOperator - -private: - // table line format: number of points; point0 x, point0 levelDelta, point1 x, point1 levelDelta, etc - HeapBlock table; - Rectangle bounds; - int maxEdgesPerLine, lineStrideElements; - bool needToCheckEmptinesss; - - void addEdgePoint (int x, int y, int winding) throw(); - void remapTableForNumEdges (int newNumEdgesPerLine) throw(); - void intersectWithEdgeTableLine (int y, const int* otherLine) throw(); - void clipEdgeTableLineToRange (int* line, int x1, int x2) throw(); - void sanitiseLevels (bool useNonZeroWinding) throw(); - static void copyEdgeTableData (int* dest, int destLineStride, const int* src, int srcLineStride, int numLines) throw(); -}; - - -#endif // __JUCE_EDGETABLE_JUCEHEADER__ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-10 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online at www.gnu.org/licenses. + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +#ifndef __JUCE_EDGETABLE_JUCEHEADER__ +#define __JUCE_EDGETABLE_JUCEHEADER__ + +#include "../geometry/juce_AffineTransform.h" +#include "../geometry/juce_Rectangle.h" +#include "../geometry/juce_RectangleList.h" +#include "../../../containers/juce_MemoryBlock.h" +class Path; +class Image; + + +//============================================================================== +/** + A table of horizontal scan-line segments - used for rasterising Paths. + + @see Path, Graphics +*/ +class JUCE_API EdgeTable +{ +public: + //============================================================================== + /** Creates an edge table containing a path. + + A table is created with a fixed vertical range, and only sections of the path + which lie within this range will be added to the table. + + @param clipLimits only the region of the path that lies within this area will be added + @param pathToAdd the path to add to the table + @param transform a transform to apply to the path being added + */ + EdgeTable (const Rectangle& clipLimits, + const Path& pathToAdd, + const AffineTransform& transform); + + /** Creates an edge table containing a rectangle. + */ + EdgeTable (const Rectangle& rectangleToAdd); + + /** Creates an edge table containing a rectangle list. + */ + EdgeTable (const RectangleList& rectanglesToAdd); + + /** Creates an edge table containing a rectangle. + */ + EdgeTable (const Rectangle& rectangleToAdd); + + /** Creates a copy of another edge table. */ + EdgeTable (const EdgeTable& other); + + /** Copies from another edge table. */ + EdgeTable& operator= (const EdgeTable& other); + + /** Destructor. */ + ~EdgeTable(); + + //============================================================================== + void clipToRectangle (const Rectangle& r) throw(); + void excludeRectangle (const Rectangle& r) throw(); + void clipToEdgeTable (const EdgeTable& other); + void clipLineToMask (int x, int y, const uint8* mask, int maskStride, int numPixels) throw(); + bool isEmpty() throw(); + const Rectangle& getMaximumBounds() const throw() { return bounds; } + void translate (float dx, int dy) throw(); + + /** Reduces the amount of space the table has allocated. + + This will shrink the table down to use as little memory as possible - useful for + read-only tables that get stored and re-used for rendering. + */ + void optimiseTable() throw(); + + + //============================================================================== + /** Iterates the lines in the table, for rendering. + + This function will iterate each line in the table, and call a user-defined class + to render each pixel or continuous line of pixels that the table contains. + + @param iterationCallback this templated class must contain the following methods: + @code + inline void setEdgeTableYPos (int y); + inline void handleEdgeTablePixel (int x, int alphaLevel) const; + inline void handleEdgeTableLine (int x, int width, int alphaLevel) const; + @endcode + (these don't necessarily have to be 'const', but it might help it go faster) + */ + template + void iterate (EdgeTableIterationCallback& iterationCallback) const throw() + { + const int* lineStart = table; + + for (int y = 0; y < bounds.getHeight(); ++y) + { + const int* line = lineStart; + lineStart += lineStrideElements; + int numPoints = line[0]; + + if (--numPoints > 0) + { + int x = *++line; + jassert ((x >> 8) >= bounds.getX() && (x >> 8) < bounds.getRight()); + int levelAccumulator = 0; + + iterationCallback.setEdgeTableYPos (bounds.getY() + y); + + while (--numPoints >= 0) + { + const int level = *++line; + jassert (((unsigned int) level) < (unsigned int) 256); + const int endX = *++line; + jassert (endX >= x); + const int endOfRun = (endX >> 8); + + if (endOfRun == (x >> 8)) + { + // small segment within the same pixel, so just save it for the next + // time round.. + levelAccumulator += (endX - x) * level; + } + else + { + // plot the fist pixel of this segment, including any accumulated + // levels from smaller segments that haven't been drawn yet + levelAccumulator += (0xff - (x & 0xff)) * level; + levelAccumulator >>= 8; + x >>= 8; + + if (levelAccumulator > 0) + { + if (levelAccumulator >> 8) + levelAccumulator = 0xff; + + iterationCallback.handleEdgeTablePixel (x, levelAccumulator); + } + + // if there's a run of similar pixels, do it all in one go.. + if (level > 0) + { + jassert (endOfRun <= bounds.getRight()); + const int numPix = endOfRun - ++x; + + if (numPix > 0) + iterationCallback.handleEdgeTableLine (x, numPix, level); + } + + // save the bit at the end to be drawn next time round the loop. + levelAccumulator = (endX & 0xff) * level; + } + + x = endX; + } + + if (levelAccumulator > 0) + { + levelAccumulator >>= 8; + if (levelAccumulator >> 8) + levelAccumulator = 0xff; + + x >>= 8; + jassert (x >= bounds.getX() && x < bounds.getRight()); + iterationCallback.handleEdgeTablePixel (x, levelAccumulator); + } + } + } + } + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + // table line format: number of points; point0 x, point0 levelDelta, point1 x, point1 levelDelta, etc + HeapBlock table; + Rectangle bounds; + int maxEdgesPerLine, lineStrideElements; + bool needToCheckEmptinesss; + + void addEdgePoint (int x, int y, int winding) throw(); + void remapTableForNumEdges (int newNumEdgesPerLine) throw(); + void intersectWithEdgeTableLine (int y, const int* otherLine) throw(); + void clipEdgeTableLineToRange (int* line, int x1, int x2) throw(); + void sanitiseLevels (bool useNonZeroWinding) throw(); + static void copyEdgeTableData (int* dest, int destLineStride, const int* src, int srcLineStride, int numLines) throw(); +}; + + +#endif // __JUCE_EDGETABLE_JUCEHEADER__ diff --git a/src/gui/graphics/contexts/juce_Graphics.cpp b/src/gui/graphics/contexts/juce_Graphics.cpp index 7191a21efd..77e791952c 100644 --- a/src/gui/graphics/contexts/juce_Graphics.cpp +++ b/src/gui/graphics/contexts/juce_Graphics.cpp @@ -532,7 +532,7 @@ void Graphics::drawHorizontalLine (const int y, float left, float right) const void Graphics::drawLine (float x1, float y1, float x2, float y2) const { - context->drawLine (x1, y1, x2, y2); + context->drawLine (Line (x1, y1, x2, y2)); } void Graphics::drawLine (const float startX, const float startY, diff --git a/src/gui/graphics/contexts/juce_LowLevelGraphicsContext.h b/src/gui/graphics/contexts/juce_LowLevelGraphicsContext.h index 6c836e10c8..91c5453b05 100644 --- a/src/gui/graphics/contexts/juce_LowLevelGraphicsContext.h +++ b/src/gui/graphics/contexts/juce_LowLevelGraphicsContext.h @@ -91,9 +91,9 @@ public: virtual void drawImage (const Image& sourceImage, const Rectangle& srcClip, const AffineTransform& transform, bool fillEntireClipAsTiles) = 0; - virtual void drawLine (double x1, double y1, double x2, double y2) = 0; - virtual void drawVerticalLine (int x, double top, double bottom) = 0; - virtual void drawHorizontalLine (int y, double left, double right) = 0; + virtual void drawLine (const Line & line) = 0; + virtual void drawVerticalLine (int x, float top, float bottom) = 0; + virtual void drawHorizontalLine (int y, float left, float right) = 0; virtual void setFont (const Font& newFont) = 0; virtual const Font getFont() = 0; diff --git a/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp b/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp index 5c6c2d73ed..dcf89b0369 100644 --- a/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp +++ b/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp @@ -499,22 +499,21 @@ void LowLevelGraphicsPostScriptRenderer::drawImage (const Image& sourceImage, co //============================================================================== -void LowLevelGraphicsPostScriptRenderer::drawLine (double x1, double y1, double x2, double y2) +void LowLevelGraphicsPostScriptRenderer::drawLine (const Line & line) { Path p; - p.addLineSegment ((float) x1, (float) y1, (float) x2, (float) y2, 1.0f); + p.addLineSegment (line.getStartX(), line.getStartY(), line.getEndX(), line.getEndY(), 1.0f); fillPath (p, AffineTransform::identity); } -void LowLevelGraphicsPostScriptRenderer::drawVerticalLine (const int x, double top, double bottom) +void LowLevelGraphicsPostScriptRenderer::drawVerticalLine (const int x, float top, float bottom) { - drawLine (x, top, x, bottom); + drawLine (Line ((float) x, top, (float) x, bottom)); } - -void LowLevelGraphicsPostScriptRenderer::drawHorizontalLine (const int y, double left, double right) +void LowLevelGraphicsPostScriptRenderer::drawHorizontalLine (const int y, float left, float right) { - drawLine (left, y, right, y); + drawLine (Line (left, (float) y, right, (float) y)); } //============================================================================== diff --git a/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h b/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h index e2490f182b..2d505328f3 100644 --- a/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h +++ b/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h @@ -75,10 +75,10 @@ public: void drawImage (const Image& sourceImage, const Rectangle& srcClip, const AffineTransform& transform, bool fillEntireClipAsTiles); - void drawLine (double x1, double y1, double x2, double y2); + void drawLine (const Line & line); - void drawVerticalLine (int x, double top, double bottom); - void drawHorizontalLine (int x, double top, double bottom); + void drawVerticalLine (int x, float top, float bottom); + void drawHorizontalLine (int x, float top, float bottom); //============================================================================== const Font getFont(); diff --git a/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp b/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp index 3c9c41e38d..0ae183fe57 100644 --- a/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp +++ b/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp @@ -42,15 +42,18 @@ BEGIN_JUCE_NAMESPACE #endif #if JUCE_MSVC + #pragma warning (push) + #pragma warning (disable: 4127) // "expression is constant" warning + #if JUCE_DEBUG #pragma optimize ("t", on) // optimise just this file, to avoid sluggish graphics when debugging #pragma warning (disable: 4714) // warning about forcedinline methods not being inlined #endif - - #pragma warning (push) - #pragma warning (disable: 4127) // "expression is constant" warning #endif +namespace SoftwareRendererClasses +{ + //============================================================================== template class SolidColourEdgeTableRenderer @@ -899,7 +902,7 @@ public: virtual const Ptr clone() const = 0; - const Ptr clipTo (ClipRegionBase* other); + virtual const Ptr applyClipTo (const Ptr& target) const = 0; virtual const Ptr clipToRectangle (const Rectangle& r) = 0; virtual const Ptr clipToRectangleList (const RectangleList& r) = 0; virtual const Ptr excludeClipRectangle (const Rectangle& r) = 0; @@ -914,14 +917,14 @@ public: virtual void fillRectWithColour (Image::BitmapData& destData, const Rectangle& area, const PixelARGB& colour) const = 0; virtual void fillAllWithColour (Image::BitmapData& destData, const PixelARGB& colour, bool replaceContents) const = 0; virtual void fillAllWithGradient (Image::BitmapData& destData, ColourGradient& gradient, const AffineTransform& transform, bool isIdentity) const = 0; - virtual void renderImageTransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const Rectangle& srcClip, const int alpha, const AffineTransform& t, bool betterQuality, bool tiledFill) const = 0; - virtual void renderImageUntransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const Rectangle& srcClip, const int alpha, int x, int y, bool tiledFill) const = 0; + virtual void renderImageTransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const int alpha, const AffineTransform& t, bool betterQuality, bool tiledFill) const = 0; + virtual void renderImageUntransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const int alpha, int x, int y, bool tiledFill) const = 0; protected: //============================================================================== template static void renderImageTransformedInternal (Iterator& iter, const Image::BitmapData& destData, const Image::BitmapData& srcData, - const Rectangle& srcClip, const int alpha, const AffineTransform& transform, bool betterQuality, bool tiledFill) + const int alpha, const AffineTransform& transform, bool betterQuality, bool tiledFill) { switch (destData.pixelFormat) { @@ -982,7 +985,7 @@ protected: } template - static void renderImageUntransformedInternal (Iterator& iter, const Image::BitmapData& destData, const Image::BitmapData& srcData, const Rectangle& srcClip, const int alpha, int x, int y, bool tiledFill) + static void renderImageUntransformedInternal (Iterator& iter, const Image::BitmapData& destData, const Image::BitmapData& srcData, const int alpha, int x, int y, bool tiledFill) { switch (destData.pixelFormat) { @@ -1102,6 +1105,11 @@ public: return new ClipRegion_EdgeTable (*this); } + const Ptr applyClipTo (const Ptr& target) const + { + return target->clipToEdgeTable (edgeTable); + } + const Ptr clipToRectangle (const Rectangle& r) { edgeTable.clipToRectangle (r); @@ -1239,14 +1247,14 @@ public: } } - void renderImageTransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const Rectangle& srcClip, const int alpha, const AffineTransform& transform, bool betterQuality, bool tiledFill) const + void renderImageTransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const int alpha, const AffineTransform& transform, bool betterQuality, bool tiledFill) const { - renderImageTransformedInternal (edgeTable, destData, srcData, srcClip, alpha, transform, betterQuality, tiledFill); + renderImageTransformedInternal (edgeTable, destData, srcData, alpha, transform, betterQuality, tiledFill); } - void renderImageUntransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const Rectangle& srcClip, const int alpha, int x, int y, bool tiledFill) const + void renderImageUntransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const int alpha, int x, int y, bool tiledFill) const { - renderImageUntransformedInternal (edgeTable, destData, srcData, srcClip, alpha, x, y, tiledFill); + renderImageUntransformedInternal (edgeTable, destData, srcData, alpha, x, y, tiledFill); } EdgeTable edgeTable; @@ -1293,6 +1301,11 @@ public: return new ClipRegion_RectangleList (*this); } + const Ptr applyClipTo (const Ptr& target) const + { + return target->clipToRectangleList (clip); + } + const Ptr clipToRectangle (const Rectangle& r) { clip.clipTo (r); @@ -1384,14 +1397,14 @@ public: } } - void renderImageTransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const Rectangle& srcClip, const int alpha, const AffineTransform& transform, bool betterQuality, bool tiledFill) const + void renderImageTransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const int alpha, const AffineTransform& transform, bool betterQuality, bool tiledFill) const { - renderImageTransformedInternal (*this, destData, srcData, srcClip, alpha, transform, betterQuality, tiledFill); + renderImageTransformedInternal (*this, destData, srcData, alpha, transform, betterQuality, tiledFill); } - void renderImageUntransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const Rectangle& srcClip, const int alpha, int x, int y, bool tiledFill) const + void renderImageUntransformed (const Image::BitmapData& destData, const Image::BitmapData& srcData, const int alpha, int x, int y, bool tiledFill) const { - renderImageUntransformedInternal (*this, destData, srcData, srcClip, alpha, x, y, tiledFill); + renderImageUntransformedInternal (*this, destData, srcData, alpha, x, y, tiledFill); } RectangleList clip; @@ -1455,6 +1468,9 @@ private: private: const RectangleList& clip; const Rectangle area; + + SubRectangleIterator (const SubRectangleIterator&); + SubRectangleIterator& operator= (const SubRectangleIterator&); }; //============================================================================== @@ -1618,55 +1634,39 @@ private: private: const RectangleList& clip; const Rectangle& area; + + SubRectangleIteratorFloat (const SubRectangleIteratorFloat&); + SubRectangleIteratorFloat& operator= (const SubRectangleIteratorFloat&); }; ClipRegion_RectangleList& operator= (const ClipRegion_RectangleList&); }; -//============================================================================== -const ClipRegionBase::Ptr ClipRegionBase::clipTo (ClipRegionBase* const other) -{ - ClipRegion_EdgeTable* et = dynamic_cast (other); - - if (et != 0) - return clipToEdgeTable (et->edgeTable); - - ClipRegion_RectangleList* rl = dynamic_cast (other); - - if (rl != 0) - return clipToRectangleList (rl->clip); - - jassertfalse - return 0; } - //============================================================================== -class LLGCSavedState +class LowLevelGraphicsSoftwareRenderer::SavedState { public: - LLGCSavedState (const Rectangle& clip_, const int xOffset_, const int yOffset_) - : clip (new ClipRegion_RectangleList (clip_)), - xOffset (xOffset_), yOffset (yOffset_), - interpolationQuality (Graphics::mediumResamplingQuality) + SavedState (const Rectangle& clip_, const int xOffset_, const int yOffset_) + : clip (new SoftwareRendererClasses::ClipRegion_RectangleList (clip_)), + xOffset (xOffset_), yOffset (yOffset_), interpolationQuality (Graphics::mediumResamplingQuality) { } - LLGCSavedState (const RectangleList& clip_, const int xOffset_, const int yOffset_) - : clip (new ClipRegion_RectangleList (clip_)), - xOffset (xOffset_), yOffset (yOffset_), - interpolationQuality (Graphics::mediumResamplingQuality) + SavedState (const RectangleList& clip_, const int xOffset_, const int yOffset_) + : clip (new SoftwareRendererClasses::ClipRegion_RectangleList (clip_)), + xOffset (xOffset_), yOffset (yOffset_), interpolationQuality (Graphics::mediumResamplingQuality) { } - LLGCSavedState (const LLGCSavedState& other) - : clip (other.clip), xOffset (other.xOffset), - yOffset (other.yOffset), font (other.font), + SavedState (const SavedState& other) + : clip (other.clip), xOffset (other.xOffset), yOffset (other.yOffset), font (other.font), fillType (other.fillType), interpolationQuality (other.interpolationQuality) { } - ~LLGCSavedState() + ~SavedState() { } @@ -1766,7 +1766,7 @@ public: const Rectangle clipped (totalClip.getIntersection (r.translated (xOffset, yOffset))); if (! clipped.isEmpty()) - fillShape (image, new ClipRegion_RectangleList (clipped), false); + fillShape (image, new SoftwareRendererClasses::ClipRegion_RectangleList (clipped), false); } } } @@ -1786,7 +1786,7 @@ public: const Rectangle clipped (totalClip.getIntersection (r.translated ((float) xOffset, (float) yOffset))); if (! clipped.isEmpty()) - fillShape (image, new ClipRegion_EdgeTable (clipped), false); + fillShape (image, new SoftwareRendererClasses::ClipRegion_EdgeTable (clipped), false); } } } @@ -1794,31 +1794,31 @@ public: void fillPath (Image& image, const Path& path, const AffineTransform& transform) { if (clip != 0) - fillShape (image, new ClipRegion_EdgeTable (clip->getClipBounds(), path, transform.translated ((float) xOffset, (float) yOffset)), false); + fillShape (image, new SoftwareRendererClasses::ClipRegion_EdgeTable (clip->getClipBounds(), path, transform.translated ((float) xOffset, (float) yOffset)), false); } void fillEdgeTable (Image& image, const EdgeTable& edgeTable, const float x, const int y) { if (clip != 0) { - ClipRegion_EdgeTable* edgeTableClip = new ClipRegion_EdgeTable (edgeTable); - ClipRegionBase::Ptr shapeToFill (edgeTableClip); + SoftwareRendererClasses::ClipRegion_EdgeTable* edgeTableClip = new SoftwareRendererClasses::ClipRegion_EdgeTable (edgeTable); + SoftwareRendererClasses::ClipRegionBase::Ptr shapeToFill (edgeTableClip); edgeTableClip->edgeTable.translate (x + xOffset, y + yOffset); fillShape (image, shapeToFill, false); } } - void fillShape (Image& image, ClipRegionBase::Ptr shapeToFill, const bool replaceContents) + void fillShape (Image& image, SoftwareRendererClasses::ClipRegionBase::Ptr shapeToFill, const bool replaceContents) { jassert (clip != 0); - shapeToFill = shapeToFill->clipTo (clip); + shapeToFill = clip->applyClipTo (shapeToFill); if (shapeToFill != 0) fillShapeWithoutClipping (image, shapeToFill, replaceContents); } - void fillShapeWithoutClipping (Image& image, const ClipRegionBase::Ptr& shapeToFill, const bool replaceContents) + void fillShapeWithoutClipping (Image& image, const SoftwareRendererClasses::ClipRegionBase::Ptr& shapeToFill, const bool replaceContents) { Image::BitmapData destData (image, 0, 0, image.getWidth(), image.getHeight(), true); @@ -1855,7 +1855,7 @@ public: //============================================================================== void renderImage (Image& destImage, const Image& sourceImage, const Rectangle& srcClip, - const AffineTransform& t, const ClipRegionBase* const tiledFillClipRegion) + const AffineTransform& t, const SoftwareRendererClasses::ClipRegionBase* const tiledFillClipRegion) { const AffineTransform transform (t.translated ((float) xOffset, (float) yOffset)); @@ -1877,15 +1877,15 @@ public: if (tiledFillClipRegion != 0) { - tiledFillClipRegion->renderImageUntransformed (destData, srcData, srcClip, alpha, tx, ty, true); + tiledFillClipRegion->renderImageUntransformed (destData, srcData, alpha, tx, ty, true); } else { - ClipRegionBase::Ptr c (new ClipRegion_EdgeTable (Rectangle (tx, ty, srcClip.getWidth(), srcClip.getHeight()).getIntersection (destImage.getBounds()))); - c = c->clipTo (clip); + SoftwareRendererClasses::ClipRegionBase::Ptr c (new SoftwareRendererClasses::ClipRegion_EdgeTable (Rectangle (tx, ty, srcClip.getWidth(), srcClip.getHeight()).getIntersection (destImage.getBounds()))); + c = clip->applyClipTo (c); if (c != 0) - c->renderImageUntransformed (destData, srcData, srcClip, alpha, tx, ty, false); + c->renderImageUntransformed (destData, srcData, alpha, tx, ty, false); } return; @@ -1897,23 +1897,23 @@ public: if (tiledFillClipRegion != 0) { - tiledFillClipRegion->renderImageTransformed (destData, srcData, srcClip, alpha, transform, betterQuality, true); + tiledFillClipRegion->renderImageTransformed (destData, srcData, alpha, transform, betterQuality, true); } else { Path p; p.addRectangle (0.0f, 0.0f, (float) srcClip.getWidth(), (float) srcClip.getHeight()); - ClipRegionBase::Ptr c (clip->clone()); + SoftwareRendererClasses::ClipRegionBase::Ptr c (clip->clone()); c = c->clipToPath (p, transform); if (c != 0) - c->renderImageTransformed (destData, srcData, srcClip, alpha, transform, betterQuality, true); + c->renderImageTransformed (destData, srcData, alpha, transform, betterQuality, true); } } //============================================================================== - ClipRegionBase::Ptr clip; + SoftwareRendererClasses::ClipRegionBase::Ptr clip; int xOffset, yOffset; Font font; FillType fillType; @@ -1926,7 +1926,7 @@ private: clip = clip->clone(); } - LLGCSavedState& operator= (const LLGCSavedState&); + SavedState& operator= (const SavedState&); }; @@ -1934,14 +1934,14 @@ private: LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (Image& image_) : image (image_) { - currentState = new LLGCSavedState (image_.getBounds(), 0, 0); + currentState = new SavedState (image_.getBounds(), 0, 0); } LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (Image& image_, const int xOffset, const int yOffset, const RectangleList& initialClip) : image (image_) { - currentState = new LLGCSavedState (initialClip, xOffset, yOffset); + currentState = new SavedState (initialClip, xOffset, yOffset); } LowLevelGraphicsSoftwareRenderer::~LowLevelGraphicsSoftwareRenderer() @@ -2002,12 +2002,12 @@ bool LowLevelGraphicsSoftwareRenderer::isClipEmpty() const //============================================================================== void LowLevelGraphicsSoftwareRenderer::saveState() { - stateStack.add (new LLGCSavedState (*currentState)); + stateStack.add (new SavedState (*currentState)); } void LowLevelGraphicsSoftwareRenderer::restoreState() { - LLGCSavedState* const top = stateStack.getLast(); + SavedState* const top = stateStack.getLast(); if (top != 0) { @@ -2056,28 +2056,73 @@ void LowLevelGraphicsSoftwareRenderer::drawImage (const Image& sourceImage, cons fillEntireClipAsTiles ? currentState->clip : 0); } -//============================================================================== -void LowLevelGraphicsSoftwareRenderer::drawLine (double x1, double y1, double x2, double y2) +void LowLevelGraphicsSoftwareRenderer::drawLine (const Line & line) { Path p; - p.addLineSegment ((float) x1, (float) y1, (float) x2, (float) y2, 1.0f); + p.addLineSegment (line.getStartX(), line.getStartY(), line.getEndX(), line.getEndY(), 1.0f); fillPath (p, AffineTransform::identity); } -void LowLevelGraphicsSoftwareRenderer::drawVerticalLine (const int x, double top, double bottom) +void LowLevelGraphicsSoftwareRenderer::drawVerticalLine (const int x, float top, float bottom) { if (bottom > top) - currentState->fillRect (image, Rectangle ((float) x, (float) top, 1.0f, (float) (bottom - top))); + currentState->fillRect (image, Rectangle ((float) x, top, 1.0f, bottom - top)); } -void LowLevelGraphicsSoftwareRenderer::drawHorizontalLine (const int y, double left, double right) +void LowLevelGraphicsSoftwareRenderer::drawHorizontalLine (const int y, float left, float right) { if (right > left) - currentState->fillRect (image, Rectangle ((float) left, (float) y, (float) (right - left), 1.0f)); + currentState->fillRect (image, Rectangle (left, (float) y, right - left, 1.0f)); } //============================================================================== -class GlyphCache : private DeletedAtShutdown +class LowLevelGraphicsSoftwareRenderer::CachedGlyph +{ +public: + CachedGlyph() : glyph (0), lastAccessCount (0) {} + ~CachedGlyph() {} + + void draw (SavedState& state, Image& image, const float x, const float y) const + { + if (edgeTable != 0) + state.fillEdgeTable (image, *edgeTable, x, roundToInt (y)); + } + + void generate (const Font& newFont, const int glyphNumber) + { + font = newFont; + glyph = glyphNumber; + edgeTable = 0; + + Path glyphPath; + font.getTypeface()->getOutlineForGlyph (glyphNumber, glyphPath); + + if (! glyphPath.isEmpty()) + { + const float fontHeight = font.getHeight(); + const AffineTransform transform (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight) + .translated (0.0f, -0.5f)); + + edgeTable = new EdgeTable (glyphPath.getBoundsTransformed (transform).getSmallestIntegerContainer().expanded (1, 0), + glyphPath, transform); + } + } + + int glyph, lastAccessCount; + Font font; + + //============================================================================== + juce_UseDebuggingNewOperator + +private: + ScopedPointer edgeTable; + + CachedGlyph (const CachedGlyph&); + CachedGlyph& operator= (const CachedGlyph&); +}; + +//============================================================================== +class LowLevelGraphicsSoftwareRenderer::GlyphCache : private DeletedAtShutdown { public: GlyphCache() @@ -2095,7 +2140,7 @@ public: juce_DeclareSingleton_SingleThreaded_Minimal (GlyphCache); //============================================================================== - void drawGlyph (LLGCSavedState& state, Image& image, const Font& font, const int glyphNumber, float x, float y) + void drawGlyph (SavedState& state, Image& image, const Font& font, const int glyphNumber, float x, float y) { ++accessCounter; int oldestCounter = std::numeric_limits::max(); @@ -2138,56 +2183,11 @@ public: oldest->draw (state, image, x, y); } - //============================================================================== - class CachedGlyph - { - public: - CachedGlyph() : glyph (0), lastAccessCount (0) {} - ~CachedGlyph() {} - - void draw (LLGCSavedState& state, Image& image, const float x, const float y) const - { - if (edgeTable != 0) - state.fillEdgeTable (image, *edgeTable, x, roundToInt (y)); - } - - void generate (const Font& newFont, const int glyphNumber) - { - font = newFont; - glyph = glyphNumber; - edgeTable = 0; - - Path glyphPath; - font.getTypeface()->getOutlineForGlyph (glyphNumber, glyphPath); - - if (! glyphPath.isEmpty()) - { - const float fontHeight = font.getHeight(); - const AffineTransform transform (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight) - .translated (0.0f, -0.5f)); - - edgeTable = new EdgeTable (glyphPath.getBoundsTransformed (transform).getSmallestIntegerContainer().expanded (1, 0), - glyphPath, transform); - } - } - - int glyph, lastAccessCount; - Font font; - - //============================================================================== - juce_UseDebuggingNewOperator - - private: - ScopedPointer edgeTable; - - CachedGlyph (const CachedGlyph&); - CachedGlyph& operator= (const CachedGlyph&); - }; - //============================================================================== juce_UseDebuggingNewOperator private: + friend class OwnedArray ; OwnedArray glyphs; int accessCounter, hits, misses; @@ -2195,7 +2195,7 @@ private: GlyphCache& operator= (const GlyphCache&); }; -juce_ImplementSingleton_SingleThreaded (GlyphCache); +juce_ImplementSingleton_SingleThreaded (LowLevelGraphicsSoftwareRenderer::GlyphCache); void LowLevelGraphicsSoftwareRenderer::setFont (const Font& newFont) diff --git a/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h b/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h index 3baccc4c9a..8cbb3f235d 100644 --- a/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h +++ b/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h @@ -27,7 +27,7 @@ #define __JUCE_LOWLEVELGRAPHICSSOFTWARERENDERER_JUCEHEADER__ #include "juce_LowLevelGraphicsContext.h" -class LLGCSavedState; + //============================================================================== /** @@ -75,10 +75,10 @@ public: void drawImage (const Image& sourceImage, const Rectangle& srcClip, const AffineTransform& transform, bool fillEntireClipAsTiles); - void drawLine (double x1, double y1, double x2, double y2); + void drawLine (const Line & line); - void drawVerticalLine (int x, double top, double bottom); - void drawHorizontalLine (int x, double top, double bottom); + void drawVerticalLine (int x, float top, float bottom); + void drawHorizontalLine (int x, float top, float bottom); //============================================================================== void setFont (const Font& newFont); @@ -93,8 +93,14 @@ protected: //============================================================================== Image& image; - ScopedPointer currentState; - OwnedArray stateStack; + class GlyphCache; + class CachedGlyph; + class SavedState; + friend class ScopedPointer ; + friend class OwnedArray ; + friend class OwnedArray ; + ScopedPointer currentState; + OwnedArray stateStack; LowLevelGraphicsSoftwareRenderer (const LowLevelGraphicsSoftwareRenderer& other); LowLevelGraphicsSoftwareRenderer& operator= (const LowLevelGraphicsSoftwareRenderer&); diff --git a/src/gui/graphics/effects/juce_DropShadowEffect.cpp b/src/gui/graphics/effects/juce_DropShadowEffect.cpp index 628c7b6aad..839d658624 100644 --- a/src/gui/graphics/effects/juce_DropShadowEffect.cpp +++ b/src/gui/graphics/effects/juce_DropShadowEffect.cpp @@ -31,11 +31,10 @@ BEGIN_JUCE_NAMESPACE #include "../imaging/juce_Image.h" #include "../colour/juce_PixelFormats.h" -#if JUCE_MSVC - #pragma optimize ("t", on) // try to avoid slowing everything down in debug builds +#if JUCE_MSVC && JUCE_DEBUG + #pragma optimize ("t", on) #endif - //============================================================================== DropShadowEffect::DropShadowEffect() : offsetX (0), @@ -109,4 +108,8 @@ void DropShadowEffect::applyEffect (Image& image, Graphics& g) g.drawImageAt (&image, 0, 0); } +#if JUCE_MSVC && JUCE_DEBUG + #pragma optimize ("", on) // resets optimisations to the project defaults +#endif + END_JUCE_NAMESPACE diff --git a/src/gui/graphics/geometry/juce_AffineTransform.h b/src/gui/graphics/geometry/juce_AffineTransform.h index eda4ae902d..4e6ea96699 100644 --- a/src/gui/graphics/geometry/juce_AffineTransform.h +++ b/src/gui/graphics/geometry/juce_AffineTransform.h @@ -170,9 +170,6 @@ public: */ float getTranslationY() const throw() { return mat12; } - //============================================================================== - juce_UseDebuggingNewOperator - //============================================================================== /* The transform matrix is: @@ -183,6 +180,10 @@ public: float mat00, mat01, mat02; float mat10, mat11, mat12; + + //============================================================================== + juce_UseDebuggingNewOperator + private: //============================================================================== const AffineTransform followedBy (float mat00, float mat01, float mat02, diff --git a/src/gui/graphics/geometry/juce_PathIterator.cpp b/src/gui/graphics/geometry/juce_PathIterator.cpp index 67bde7ae79..08d3193311 100644 --- a/src/gui/graphics/geometry/juce_PathIterator.cpp +++ b/src/gui/graphics/geometry/juce_PathIterator.cpp @@ -30,7 +30,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_PathIterator.h" -#if JUCE_MSVC +#if JUCE_MSVC && JUCE_DEBUG #pragma optimize ("t", on) #endif @@ -288,4 +288,8 @@ bool PathFlatteningIterator::next() } } +#if JUCE_MSVC && JUCE_DEBUG + #pragma optimize ("", on) // resets optimisations to the project defaults +#endif + END_JUCE_NAMESPACE diff --git a/src/gui/graphics/geometry/juce_PathIterator.h b/src/gui/graphics/geometry/juce_PathIterator.h index c43306cf17..c61818f64e 100644 --- a/src/gui/graphics/geometry/juce_PathIterator.h +++ b/src/gui/graphics/geometry/juce_PathIterator.h @@ -71,14 +71,10 @@ public: */ bool next(); - /** The x position of the start of the current line segment. */ - float x1; - /** The y position of the start of the current line segment. */ - float y1; - /** The x position of the end of the current line segment. */ - float x2; - /** The y position of the end of the current line segment. */ - float y2; + float x1; /**< The x position of the start of the current line segment. */ + float y1; /**< The y position of the start of the current line segment. */ + float x2; /**< The x position of the end of the current line segment. */ + float y2; /**< The y position of the end of the current line segment. */ /** Indicates whether the current line segment is closing a sub-path. @@ -95,10 +91,8 @@ public: int subPathIndex; /** Returns true if the current segment is the last in the current sub-path. */ - bool isLastInSubpath() const { return stackPos == stackBase.getData() - && (index >= path.numElements - || points [index] == Path::moveMarker); } - + bool isLastInSubpath() const throw() { return stackPos == stackBase.getData() + && (index >= path.numElements || points [index] == Path::moveMarker); } //============================================================================== juce_UseDebuggingNewOperator diff --git a/src/gui/graphics/imaging/image_file_formats/juce_PNGLoader.cpp b/src/gui/graphics/imaging/image_file_formats/juce_PNGLoader.cpp index 79572b463f..ee2f6aacfd 100644 --- a/src/gui/graphics/imaging/image_file_formats/juce_PNGLoader.cpp +++ b/src/gui/graphics/imaging/image_file_formats/juce_PNGLoader.cpp @@ -25,7 +25,7 @@ #include "../../../../core/juce_StandardHeader.h" -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (push) #pragma warning (disable: 4390 4611) #endif @@ -93,7 +93,7 @@ namespace pnglibNamespace #undef max #undef min -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (pop) #endif diff --git a/src/io/network/juce_Socket.cpp b/src/io/network/juce_Socket.cpp index 3061c19c0c..051456c2be 100644 --- a/src/io/network/juce_Socket.cpp +++ b/src/io/network/juce_Socket.cpp @@ -28,7 +28,8 @@ #if JUCE_WINDOWS #include - #ifdef _MSC_VER + #if JUCE_MSVC + #pragma warning (push) #pragma warning (disable : 4127 4389 4018) #endif @@ -631,5 +632,8 @@ bool DatagramSocket::isLocal() const throw() return hostName == "127.0.0.1"; } +#if JUCE_MSVC + #pragma warning (pop) +#endif END_JUCE_NAMESPACE diff --git a/src/native/juce_win32_NativeCode.cpp b/src/native/juce_win32_NativeCode.cpp index 474ce1bd37..9222f925e0 100644 --- a/src/native/juce_win32_NativeCode.cpp +++ b/src/native/juce_win32_NativeCode.cpp @@ -84,7 +84,6 @@ BEGIN_JUCE_NAMESPACE #include "../audio/devices/juce_MidiOutput.h" #include "../audio/devices/juce_MidiInput.h" - //============================================================================== #define JUCE_INCLUDED_FILE 1 diff --git a/src/native/mac/juce_mac_CoreGraphicsContext.mm b/src/native/mac/juce_mac_CoreGraphicsContext.mm index bc74021ba9..a98d5c74b8 100644 --- a/src/native/mac/juce_mac_CoreGraphicsContext.mm +++ b/src/native/mac/juce_mac_CoreGraphicsContext.mm @@ -449,7 +449,7 @@ public: } //============================================================================== - void drawLine (double x1, double y1, double x2, double y2) + void drawLine (const Line& line) { CGContextSetLineCap (context, kCGLineCapSquare); CGContextSetLineWidth (context, 1.0f); @@ -457,31 +457,31 @@ public: state->fillType.colour.getFloatRed(), state->fillType.colour.getFloatGreen(), state->fillType.colour.getFloatBlue(), state->fillType.colour.getFloatAlpha()); - CGPoint line[] = { { (CGFloat) x1, flipHeight - (CGFloat) y1 }, - { (CGFloat) x2, flipHeight - (CGFloat) y2 } }; + CGPoint cgLine[] = { { (CGFloat) line.getStartX(), flipHeight - (CGFloat) line.getStartY() }, + { (CGFloat) line.getEndX(), flipHeight - (CGFloat) line.getEndY() } }; - CGContextStrokeLineSegments (context, line, 1); + CGContextStrokeLineSegments (context, cgLine, 1); } - void drawVerticalLine (const int x, double top, double bottom) + void drawVerticalLine (const int x, float top, float bottom) { #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 - CGContextFillRect (context, CGRectMake (x, flipHeight - (float) bottom, 1.0f, (float) (bottom - top))); + CGContextFillRect (context, CGRectMake (x, flipHeight - bottom, 1.0f, bottom - top)); #else // On Leopard, unless both co-ordinates are non-integer, it disables anti-aliasing, so nudge // the x co-ord slightly to trick it.. - CGContextFillRect (context, CGRectMake (x + 1.0f / 256.0f, flipHeight - (float) bottom, 1.0f + 1.0f / 256.0f, (float) (bottom - top))); + CGContextFillRect (context, CGRectMake (x + 1.0f / 256.0f, flipHeight - bottom, 1.0f + 1.0f / 256.0f, bottom - top)); #endif } - void drawHorizontalLine (const int y, double left, double right) + void drawHorizontalLine (const int y, float left, float right) { #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 - CGContextFillRect (context, CGRectMake ((float) left, flipHeight - (y + 1.0f), (float) (right - left), 1.0f)); + CGContextFillRect (context, CGRectMake (left, flipHeight - (y + 1.0f), right - left, 1.0f)); #else // On Leopard, unless both co-ordinates are non-integer, it disables anti-aliasing, so nudge // the x co-ord slightly to trick it.. - CGContextFillRect (context, CGRectMake ((float) left, flipHeight - (y + (1.0f + 1.0f / 256.0f)), (float) (right - left), 1.0f + 1.0f / 256.0f)); + CGContextFillRect (context, CGRectMake (left, flipHeight - (y + (1.0f + 1.0f / 256.0f)), right - left, 1.0f + 1.0f / 256.0f)); #endif } @@ -646,23 +646,12 @@ private: { switch (i.elementType) { - case Path::Iterator::startNewSubPath: - CGContextMoveToPoint (context, i.x1, i.y1); - break; - case Path::Iterator::lineTo: - CGContextAddLineToPoint (context, i.x1, i.y1); - break; - case Path::Iterator::quadraticTo: - CGContextAddQuadCurveToPoint (context, i.x1, i.y1, i.x2, i.y2); - break; - case Path::Iterator::cubicTo: - CGContextAddCurveToPoint (context, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); - break; - case Path::Iterator::closePath: - CGContextClosePath (context); break; - default: - jassertfalse - break; + case Path::Iterator::startNewSubPath: CGContextMoveToPoint (context, i.x1, i.y1); break; + case Path::Iterator::lineTo: CGContextAddLineToPoint (context, i.x1, i.y1); break; + case Path::Iterator::quadraticTo: CGContextAddQuadCurveToPoint (context, i.x1, i.y1, i.x2, i.y2); break; + case Path::Iterator::cubicTo: CGContextAddCurveToPoint (context, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); break; + case Path::Iterator::closePath: CGContextClosePath (context); break; + default: jassertfalse; break; } } } diff --git a/src/native/windows/juce_win32_NativeIncludes.h b/src/native/windows/juce_win32_NativeIncludes.h index d513fb5806..5e7ad5bb02 100644 --- a/src/native/windows/juce_win32_NativeIncludes.h +++ b/src/native/windows/juce_win32_NativeIncludes.h @@ -38,7 +38,7 @@ #undef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (push) #pragma warning (disable : 4100 4201 4514 4312 4995) #endif @@ -179,7 +179,7 @@ #endif //============================================================================== -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (pop) #endif diff --git a/src/native/windows/juce_win32_Windowing.cpp b/src/native/windows/juce_win32_Windowing.cpp index 9c35d9ee69..e6fe79aed1 100644 --- a/src/native/windows/juce_win32_Windowing.cpp +++ b/src/native/windows/juce_win32_Windowing.cpp @@ -940,7 +940,6 @@ private: if (hasTitleBar()) { type |= WS_OVERLAPPED; - exstyle |= WS_EX_APPWINDOW; if ((styleFlags & windowHasCloseButton) != 0) { @@ -958,13 +957,13 @@ private: else { type |= WS_POPUP | WS_SYSMENU; - - if ((styleFlags & windowAppearsOnTaskbar) == 0) - exstyle |= WS_EX_TOOLWINDOW; - else - exstyle |= WS_EX_APPWINDOW; } + if ((styleFlags & windowAppearsOnTaskbar) == 0) + exstyle |= WS_EX_TOOLWINDOW; + else + exstyle |= WS_EX_APPWINDOW; + if ((styleFlags & windowHasMinimiseButton) != 0) type |= WS_MINIMIZEBOX; diff --git a/src/text/juce_CharacterFunctions.cpp b/src/text/juce_CharacterFunctions.cpp index d084976484..5b405b75a3 100644 --- a/src/text/juce_CharacterFunctions.cpp +++ b/src/text/juce_CharacterFunctions.cpp @@ -23,20 +23,17 @@ ============================================================================== */ -#ifdef _MSC_VER - #pragma warning (disable: 4514 4996) +#include "../core/juce_StandardHeader.h" + +#if JUCE_MSVC #pragma warning (push) + #pragma warning (disable: 4514 4996) #endif -#include "../core/juce_StandardHeader.h" #include #include #include -#ifdef _MSC_VER - #pragma warning (pop) -#endif - BEGIN_JUCE_NAMESPACE #include "juce_CharacterFunctions.h" @@ -794,5 +791,8 @@ int CharacterFunctions::getHexDigitValue (const juce_wchar digit) throw() return -1; } +#if JUCE_MSVC + #pragma warning (pop) +#endif END_JUCE_NAMESPACE diff --git a/src/text/juce_String.cpp b/src/text/juce_String.cpp index ab1ce6488e..036177101d 100644 --- a/src/text/juce_String.cpp +++ b/src/text/juce_String.cpp @@ -23,25 +23,22 @@ ============================================================================== */ -#ifdef _MSC_VER - #pragma warning (push) - #pragma warning (disable: 4514) -#endif -#include - #include "../core/juce_StandardHeader.h" #if JUCE_MSVC - #include + #pragma warning (push) + #pragma warning (disable: 4514) #endif +#include + BEGIN_JUCE_NAMESPACE #include "juce_String.h" #include "../core/juce_Atomic.h" #include "../io/streams/juce_OutputStream.h" -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (pop) #endif @@ -1689,12 +1686,12 @@ const String String::formatted (const juce_wchar* const pf, ... ) const int num = (int) vswprintf (result.text, bufferSize - 1, pf, tempArgs); va_end (tempArgs); #elif JUCE_WINDOWS - #ifdef _MSC_VER + #if JUCE_MSVC #pragma warning (push) #pragma warning (disable: 4996) #endif const int num = (int) _vsnwprintf (result.text, bufferSize - 1, pf, args); - #ifdef _MSC_VER + #if JUCE_MSVC #pragma warning (pop) #endif #else @@ -2133,9 +2130,9 @@ const char* String::toCString() const } } -#ifdef _MSC_VER - #pragma warning (disable: 4514 4996) +#if JUCE_MSVC #pragma warning (push) + #pragma warning (disable: 4514 4996) #endif int String::getNumBytesAsCString() const throw() @@ -2153,7 +2150,7 @@ int String::copyToCString (char* destBuffer, const int maxBufferSizeBytes) const return numBytes; } -#ifdef _MSC_VER +#if JUCE_MSVC #pragma warning (pop) #endif