From 4d000ff593cee81d93069d102af69fec7e86cbde Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Mon, 9 Nov 2009 22:46:18 +0000 Subject: [PATCH] Rewrote EdgeTable so that it now always renders in perfect quality - this makes the old oversampling quality options defunct and I've removed them. --- juce_amalgamated.cpp | 403 ++++--- juce_amalgamated.h | 1000 ++++++++--------- src/cryptography/juce_RSAKey.h | 8 +- .../graphics/brushes/juce_GradientBrush.cpp | 2 +- src/gui/graphics/brushes/juce_ImageBrush.cpp | 2 +- .../brushes/juce_SolidColourBrush.cpp | 2 +- src/gui/graphics/contexts/juce_EdgeTable.cpp | 101 +- src/gui/graphics/contexts/juce_EdgeTable.h | 154 +-- src/gui/graphics/contexts/juce_Graphics.cpp | 2 +- src/gui/graphics/contexts/juce_Graphics.h | 27 + .../contexts/juce_LowLevelGraphicsContext.h | 7 +- ...uce_LowLevelGraphicsPostScriptRenderer.cpp | 10 +- .../juce_LowLevelGraphicsPostScriptRenderer.h | 4 +- .../juce_LowLevelGraphicsSoftwareRenderer.cpp | 92 +- .../juce_LowLevelGraphicsSoftwareRenderer.h | 8 +- src/gui/graphics/fonts/juce_Font.cpp | 117 +- src/gui/graphics/geometry/juce_Path.cpp | 69 ++ src/gui/graphics/geometry/juce_Path.h | 20 +- .../mac/juce_mac_CoreGraphicsContext.mm | 4 +- src/native/mac/juce_mac_OpenGLComponent.mm | 2 +- 20 files changed, 1050 insertions(+), 984 deletions(-) diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 7373863c09..258232e67e 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -77531,7 +77531,7 @@ void GradientBrush::paintPath (LowLevelGraphicsContext& context, const Path& path, const AffineTransform& transform) throw() { context.setGradient (gradient); - context.fillPath (path, transform, EdgeTable::Oversampling_4times); + context.fillPath (path, transform); } void GradientBrush::paintRectangle (LowLevelGraphicsContext& context, @@ -77699,7 +77699,7 @@ void ImageBrush::paintPath (LowLevelGraphicsContext& context, while (x < right) { - context.fillPathWithImage (path, transform, *image, x, y, EdgeTable::Oversampling_4times); + context.fillPathWithImage (path, transform, *image, x, y); x += iw; } @@ -77792,7 +77792,7 @@ void SolidColourBrush::paintPath (LowLevelGraphicsContext& context, const Path& path, const AffineTransform& transform) throw() { context.setColour (colour); - context.fillPath (path, transform, EdgeTable::Oversampling_4times); + context.fillPath (path, transform); } void SolidColourBrush::paintRectangle (LowLevelGraphicsContext& context, @@ -78823,18 +78823,16 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -EdgeTable::EdgeTable (const int top_, - const int height_, - const OversamplingLevel oversampling_, - const int expectedEdgesPerLine) throw() +const int juce_edgeTableDefaultEdgesPerLine = 32; + +EdgeTable::EdgeTable (const int top_, const int height_) throw() : top (top_), height (height_), - maxEdgesPerLine (expectedEdgesPerLine), - lineStrideElements ((expectedEdgesPerLine << 1) + 1), - oversampling (oversampling_) + maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), + lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), + nonZeroWinding (true) { - table = (int*) juce_calloc ((height << (int)oversampling_) - * lineStrideElements * sizeof (int)); + table = (int*) juce_calloc (height * lineStrideElements * sizeof (int)); } EdgeTable::EdgeTable (const EdgeTable& other) throw() @@ -78851,11 +78849,9 @@ const EdgeTable& EdgeTable::operator= (const EdgeTable& other) throw() height = other.height; maxEdgesPerLine = other.maxEdgesPerLine; lineStrideElements = other.lineStrideElements; - oversampling = other.oversampling; - - const int tableSize = (height << (int)oversampling) - * lineStrideElements * sizeof (int); + nonZeroWinding = other.nonZeroWinding; + const int tableSize = height * lineStrideElements * sizeof (int); table = (int*) juce_malloc (tableSize); memcpy (table, other.table, tableSize); @@ -78874,10 +78870,9 @@ void EdgeTable::remapTableForNumEdges (const int newNumEdgesPerLine) throw() maxEdgesPerLine = newNumEdgesPerLine; const int newLineStrideElements = maxEdgesPerLine * 2 + 1; - int* const newTable = (int*) juce_malloc ((height << (int) oversampling) - * newLineStrideElements * sizeof (int)); + int* const newTable = (int*) juce_malloc (height * newLineStrideElements * sizeof (int)); - for (int i = 0; i < (height << (int) oversampling); ++i) + for (int i = 0; i < height; ++i) { const int* srcLine = table + lineStrideElements * i; int* dstLine = newTable + newLineStrideElements * i; @@ -78909,7 +78904,7 @@ void EdgeTable::optimiseTable() throw() void EdgeTable::addEdgePoint (const int x, const int y, const int winding) throw() { - jassert (y >= 0 && y < (height << oversampling)) + jassert (y >= 0 && y < height) int* lineStart = table + lineStrideElements * y; int n = lineStart[0]; @@ -78946,39 +78941,28 @@ void EdgeTable::addEdgePoint (const int x, const int y, const int winding) throw void EdgeTable::addPath (const Path& path, const AffineTransform& transform) throw() { - const int windingAmount = 256 / (1 << (int) oversampling); - const float timesOversampling = (float) (1 << (int) oversampling); - - const int bottomLimit = (height << (int) oversampling); + nonZeroWinding = path.isUsingNonZeroWinding(); + const int bottomLimit = height << 8; PathFlatteningIterator iter (path, transform); while (iter.next()) { - int y1 = roundFloatToInt (iter.y1 * timesOversampling) - (top << (int) oversampling); - int y2 = roundFloatToInt (iter.y2 * timesOversampling) - (top << (int) oversampling); + int y1 = roundFloatToInt (iter.y1 * 256.0f) - (top << 8); + int y2 = roundFloatToInt (iter.y2 * 256.0f) - (top << 8); if (y1 != y2) { const double x1 = 256.0 * iter.x1; const double x2 = 256.0 * iter.x2; - const double multiplier = (x2 - x1) / (y2 - y1); - - const int oldY1 = y1; - int winding; + int winding = -1; if (y1 > y2) { swapVariables (y1, y2); - winding = windingAmount; + winding = 1; } - else - { - winding = -windingAmount; - } - - jassert (y1 < y2); if (y1 < 0) y1 = 0; @@ -78986,46 +78970,34 @@ void EdgeTable::addPath (const Path& path, if (y2 > bottomLimit) y2 = bottomLimit; + const int oldY1 = y1; + const int stepSize = jlimit (1, 256, 256 / (1 + abs ((int) multiplier))); + while (y1 < y2) { + const int step = jmin (stepSize, y2 - y1, 256 - (y1 & 255)); + addEdgePoint (roundDoubleToInt (x1 + multiplier * (y1 - oldY1)), - y1, - winding); + y1 >> 8, winding * step); - ++y1; - } - } - } - - if (! path.isUsingNonZeroWinding()) - { - // if it's an alternate-winding path, we need to go through and - // make sure all the windings are alternating. - - int* lineStart = table; - - for (int i = height << (int) oversampling; --i >= 0;) - { - int* line = lineStart; - lineStart += lineStrideElements; - - int num = *line; - - while (--num >= 0) - { - line += 2; - *line = abs (*line); - - if (--num >= 0) - { - line += 2; - *line = -abs (*line); - } + y1 += step; } } } } +/*void EdgeTable::clipToRectangle (const Rectangle& r) throw() +{ +} + +void EdgeTable::intersectWith (const EdgeTable& other) +{ +} + +void EdgeTable::generateFromImageAlpha (Image& image, int x, int y) throw() +{ +}*/ + END_JUCE_NAMESPACE /********* End of inlined file: juce_EdgeTable.cpp *********/ @@ -79436,7 +79408,7 @@ void Graphics::fillPath (const Path& path, if ((! context->isClipEmpty()) && ! path.isEmpty()) { if (state->brush == 0) - context->fillPath (path, transform, EdgeTable::Oversampling_4times); + context->fillPath (path, transform); else state->brush->paintPath (*context, path, transform); } @@ -80439,13 +80411,12 @@ void LowLevelGraphicsPostScriptRenderer::fillRect (int x, int y, int w, int h, c { Path p; p.addRectangle ((float) x, (float) y, (float) w, (float) h); - fillPath (p, AffineTransform::identity, EdgeTable::Oversampling_256times); + fillPath (p, AffineTransform::identity); } } -void LowLevelGraphicsPostScriptRenderer::fillPath (const Path& path, const AffineTransform& t, - EdgeTable::OversamplingLevel /*quality*/) +void LowLevelGraphicsPostScriptRenderer::fillPath (const Path& path, const AffineTransform& t) { if (gradient == 0) { @@ -80488,8 +80459,7 @@ void LowLevelGraphicsPostScriptRenderer::fillPath (const Path& path, const Affin void LowLevelGraphicsPostScriptRenderer::fillPathWithImage (const Path& path, const AffineTransform& transform, const Image& sourceImage, - int imageX, int imageY, - EdgeTable::OversamplingLevel /*quality*/) + int imageX, int imageY) { writeClip(); @@ -80651,7 +80621,7 @@ void LowLevelGraphicsPostScriptRenderer::drawLine (double x1, double y1, double { Path p; p.addLineSegment ((float) x1, (float) y1, (float) x2, (float) y2, 1.0f); - fillPath (p, AffineTransform::identity, EdgeTable::Oversampling_256times); + fillPath (p, AffineTransform::identity); } void LowLevelGraphicsPostScriptRenderer::drawVerticalLine (const int x, double top, double bottom) @@ -81702,6 +81672,79 @@ static void renderAlphaMap (DestPixelType* destPixels, } } +/*class ClippingPath +{ +public: + ClippingPath (const Rectangle& r) throw() + : rectangles (r) + { + } + + ClippingPath (const ClippingPath& other) throw() + : rectangles (other.rectangles), mask (other.mask) + { + } + + ~ClippingPath() throw() + { + delete mask; + } + + bool reduce (int x, int y, int w, int h) throw() + { + return clip.clipTo (Rectangle (x, y, w, h)); + } + + bool exclude (int x, int y, int w, int h) throw() + { + return clip.subtract (Rectangle (x, y, w, h)); + } + + bool reduce (const Path& p, const AffineTransform& transform) + { + float px, py, pw, ph; + p.getBoundsTransformed (transform, px, py, pw, ph); + + Rectangle pathBounds ((int) px - 1, (int) py - 1, (int) pw + 3, (int) ph + 3); + + if (clip.clipTo (pathBounds)) + { + } + } + + bool reduce (Image& image, int x, int y) + { + } + + bool reduce (Image& image, const AffineTransform& transform) + { + } + + class MaskImage : public ReferenceCountedObject + { + public: + MaskImage (int x_, int y_, int w, int h) throw() + : x (x_), y (y_) + { + image = new Image (Image::SingleChannel, w, h, true); + } + + ~MaskImage() throw() + { + delete image; + } + + Image* image; + int x, y; + }; + + RectangleList clip; + ReferenceCountedObjectPtr mask; + +private: +}; +*/ + LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (Image& image_) : image (image_), xOffset (0), @@ -81846,7 +81889,7 @@ void LowLevelGraphicsSoftwareRenderer::fillRect (int x, int y, int w, int h, con Path p; p.addRectangle ((float) x, (float) y, (float) w, (float) h); - fillPath (p, AffineTransform::identity, EdgeTable::Oversampling_none); + fillPath (p, AffineTransform::identity); } else { @@ -81907,26 +81950,26 @@ bool LowLevelGraphicsSoftwareRenderer::getPathBounds (int clipX, int clipY, int return Rectangle::intersectRectangles (x, y, w, h, clipX, clipY, clipW, clipH); } -void LowLevelGraphicsSoftwareRenderer::fillPath (const Path& path, const AffineTransform& transform, EdgeTable::OversamplingLevel quality) +void LowLevelGraphicsSoftwareRenderer::fillPath (const Path& path, const AffineTransform& transform) { for (RectangleList::Iterator i (*clip); i.next();) { const Rectangle& r = *i.getRectangle(); clippedFillPath (r.getX(), r.getY(), r.getWidth(), r.getHeight(), - path, transform, quality); + path, transform); } } void LowLevelGraphicsSoftwareRenderer::clippedFillPath (int clipX, int clipY, int clipW, int clipH, const Path& path, - const AffineTransform& t, EdgeTable::OversamplingLevel quality) + const AffineTransform& t) { const AffineTransform transform (t.translated ((float) xOffset, (float) yOffset)); int cx, cy, cw, ch; if (getPathBounds (clipX, clipY, clipW, clipH, path, transform, cx, cy, cw, ch)) { - EdgeTable edgeTable (0, ch, quality); + EdgeTable edgeTable (0, ch); edgeTable.addPath (path, transform.translated ((float) -cx, (float) -cy)); int stride, pixelStride; @@ -82034,7 +82077,7 @@ void LowLevelGraphicsSoftwareRenderer::clippedFillPath (int clipX, int clipY, in } void LowLevelGraphicsSoftwareRenderer::fillPathWithImage (const Path& path, const AffineTransform& transform, - const Image& sourceImage, int imageX, int imageY, EdgeTable::OversamplingLevel quality) + const Image& sourceImage, int imageX, int imageY) { imageX += xOffset; imageY += yOffset; @@ -82045,16 +82088,16 @@ void LowLevelGraphicsSoftwareRenderer::fillPathWithImage (const Path& path, cons clippedFillPathWithImage (r.getX(), r.getY(), r.getWidth(), r.getHeight(), path, transform, sourceImage, imageX, imageY, - colour.getFloatAlpha(), quality); + colour.getFloatAlpha()); } } void LowLevelGraphicsSoftwareRenderer::clippedFillPathWithImage (int x, int y, int w, int h, const Path& path, const AffineTransform& transform, - const Image& sourceImage, int imageX, int imageY, float opacity, EdgeTable::OversamplingLevel quality) + const Image& sourceImage, int imageX, int imageY, float opacity) { if (Rectangle::intersectRectangles (x, y, w, h, imageX, imageY, sourceImage.getWidth(), sourceImage.getHeight())) { - EdgeTable edgeTable (0, h, quality); + EdgeTable edgeTable (0, h); edgeTable.addPath (path, transform.translated ((float) (xOffset - x), (float) (yOffset - y))); int stride, pixelStride; @@ -85980,27 +86023,27 @@ class FontGlyphAlphaMap public: FontGlyphAlphaMap() throw() - : glyph (0), lastAccessCount (0), - bitmap1 (0), bitmap2 (0) + : glyph (0), lastAccessCount (0) { + bitmap[0] = bitmap[1] = 0; } ~FontGlyphAlphaMap() throw() { - delete bitmap1; - delete bitmap2; + delete bitmap[0]; + delete bitmap[1]; } void draw (LowLevelGraphicsContext& g, float x, const float y) const throw() { - if (bitmap1 != 0) + if (bitmap[0] != 0) { - x += xOrigin; const float xFloor = floorf (x); - const int intX = (int) xFloor; + const int bitmapToUse = ((x - xFloor) >= 0.5f && bitmap[1] != 0) ? 1 : 0; - g.fillAlphaChannel (((x - xFloor) >= 0.5f && bitmap2 != 0) ? *bitmap2 : *bitmap1, - intX, (int) floorf (y + yOrigin)); + g.fillAlphaChannel (*bitmap [bitmapToUse], + xOrigin [bitmapToUse] + (int) xFloor, + yOrigin [bitmapToUse] + (int) floorf (y)); } } @@ -86009,8 +86052,8 @@ public: font = font_; glyph = glyph_; - deleteAndZero (bitmap1); - deleteAndZero (bitmap2); + deleteAndZero (bitmap[0]); + deleteAndZero (bitmap[1]); Path glyphPath; font.getTypeface()->getOutlineForGlyph (glyph_, glyphPath); @@ -86019,15 +86062,19 @@ public: { const float fontHeight = font.getHeight(); const float fontHScale = fontHeight * font.getHorizontalScale(); + AffineTransform transform (AffineTransform::scale (fontHScale, fontHeight)); + Rectangle clip (-2048, -2048, 4096, 4096), pos; - bitmap1 = createAlphaMapFromPath (glyphPath, xOrigin, yOrigin, fontHScale, fontHeight, 0.0f); + bitmap[0] = glyphPath.createMaskBitmap (transform, clip, pos); + xOrigin[0] = pos.getX(); + yOrigin[0] = pos.getY(); - if (fontHScale < 24.0f) - bitmap2 = createAlphaMapFromPath (glyphPath, xOrigin, yOrigin, fontHScale, fontHeight, 0.5f); - } - else - { - xOrigin = yOrigin = 0; + if (fontHScale < 30.0f) + { + bitmap[1] = glyphPath.createMaskBitmap (transform.translated (0.5f, 0.0f), clip, pos); + xOrigin[1] = pos.getX(); + yOrigin[1] = pos.getY(); + } } } @@ -86037,78 +86084,8 @@ public: juce_UseDebuggingNewOperator private: - Image* bitmap1; - Image* bitmap2; - float xOrigin, yOrigin; - - class AlphaBitmapRenderer - { - public: - AlphaBitmapRenderer (uint8* const data_, const int stride_) throw() - : data (data_), stride (stride_) - { - } - - forcedinline void setEdgeTableYPos (const int y) throw() - { - lineStart = data + (stride * y); - } - - forcedinline void handleEdgeTablePixel (const int x, const int alphaLevel) const throw() - { - lineStart [x] = (uint8) alphaLevel; - } - - forcedinline void handleEdgeTableLine (const int x, int width, const int alphaLevel) const throw() - { - uint8* d = lineStart + x; - - while (--width >= 0) - *d++ = (uint8) alphaLevel; - } - - private: - uint8* const data; - const int stride; - uint8* lineStart; - - AlphaBitmapRenderer (const AlphaBitmapRenderer&); - const AlphaBitmapRenderer& operator= (const AlphaBitmapRenderer&); - }; - - Image* createAlphaMapFromPath (const Path& path, - float& topLeftX, float& topLeftY, - float xScale, float yScale, - const float subPixelOffsetX) throw() - { - Image* im = 0; - - float px, py, pw, ph; - path.getBounds (px, py, pw, ph); - - topLeftX = floorf (px * xScale); - topLeftY = floorf (py * yScale); - - const int bitmapWidth = roundFloatToInt (pw * xScale) + 2; - const int bitmapHeight = roundFloatToInt (ph * yScale) + 2; - - im = new Image (Image::SingleChannel, bitmapWidth, bitmapHeight, true); - - EdgeTable edgeTable (0, bitmapHeight, EdgeTable::Oversampling_16times); - - edgeTable.addPath (path, AffineTransform::scale (xScale, yScale) - .translated (subPixelOffsetX - topLeftX, -topLeftY)); - - int stride, pixelStride; - uint8* const pixels = (uint8*) im->lockPixelDataReadWrite (0, 0, bitmapWidth, bitmapHeight, stride, pixelStride); - - jassert (pixelStride == 1); - AlphaBitmapRenderer renderer (pixels, stride); - edgeTable.iterate (renderer, 0, 0, bitmapWidth, bitmapHeight, 0); - - im->releasePixelDataReadWrite (pixels); - return im; - } + Image* bitmap[2]; + int xOrigin[2], yOrigin[2]; FontGlyphAlphaMap (const FontGlyphAlphaMap&); const FontGlyphAlphaMap& operator= (const FontGlyphAlphaMap&); @@ -86215,8 +86192,7 @@ void Font::renderGlyphIndirectly (LowLevelGraphicsContext& g, int glyphNumber, c getTypeface()->getOutlineForGlyph (glyphNumber, p); g.fillPath (p, AffineTransform::scale (font->height * font->horizontalScale, font->height) - .followedBy (transform), - EdgeTable::Oversampling_16times); + .followedBy (transform)); } END_JUCE_NAMESPACE @@ -89928,6 +89904,73 @@ bool Path::Iterator::next() return false; } +class MaskBitmapRenderer +{ +public: + MaskBitmapRenderer (uint8* const data_, const int stride_) throw() + : data (data_), stride (stride_) + { + } + + forcedinline void setEdgeTableYPos (const int y) throw() + { + lineStart = data + (stride * y); + } + + forcedinline void handleEdgeTablePixel (const int x, const int alphaLevel) const throw() + { + lineStart [x] = (uint8) alphaLevel; + } + + forcedinline void handleEdgeTableLine (const int x, int width, const int alphaLevel) const throw() + { + uint8* d = lineStart + x; + + while (--width >= 0) + *d++ = (uint8) alphaLevel; + } + +private: + uint8* const data; + const int stride; + uint8* lineStart; + + MaskBitmapRenderer (const MaskBitmapRenderer&); + const MaskBitmapRenderer& operator= (const MaskBitmapRenderer&); +}; + +Image* Path::createMaskBitmap (const AffineTransform& transform, + const Rectangle& clipRegion, + Rectangle& imagePosition) const throw() +{ + if (isEmpty()) + return 0; + + float px, py, pw, ph; + getBoundsTransformed (transform, px, py, pw, ph); + + imagePosition = clipRegion.getIntersection (Rectangle ((int) floorf (px), (int) floorf (py), + roundFloatToInt (pw) + 2, roundFloatToInt (ph) + 2)); + + if (imagePosition.isEmpty()) + return 0; + + Image* im = new Image (Image::SingleChannel, imagePosition.getWidth(), imagePosition.getHeight(), true); + + EdgeTable edgeTable (0, imagePosition.getHeight()); + edgeTable.addPath (*this, transform.translated (-imagePosition.getX(), -imagePosition.getY())); + + int stride, pixelStride; + uint8* const pixels = (uint8*) im->lockPixelDataReadWrite (0, 0, imagePosition.getWidth(), imagePosition.getHeight(), stride, pixelStride); + + jassert (pixelStride == 1); + MaskBitmapRenderer renderer (pixels, stride); + edgeTable.iterate (renderer, 0, 0, imagePosition.getWidth(), imagePosition.getHeight(), 0); + + im->releasePixelDataReadWrite (pixels); + return im; +} + END_JUCE_NAMESPACE /********* End of inlined file: juce_Path.cpp *********/ @@ -263700,7 +263743,7 @@ public: ~WindowedGLContext() { makeInactive(); - [renderContext setView: nil]; + [renderContext clearDrawable]; delete viewHolder; } @@ -266034,7 +266077,7 @@ public: } } - void fillPath (const Path& path, const AffineTransform& transform, EdgeTable::OversamplingLevel quality) + void fillPath (const Path& path, const AffineTransform& transform) { CGContextSaveGState (context); @@ -266058,7 +266101,7 @@ public: } void fillPathWithImage (const Path& path, const AffineTransform& transform, - const Image& image, int imageX, int imageY, EdgeTable::OversamplingLevel quality) + const Image& image, int imageX, int imageY) { CGContextSaveGState (context); createPath (path, transform); @@ -268731,7 +268774,7 @@ public: ~WindowedGLContext() { makeInactive(); - [renderContext setView: nil]; + [renderContext clearDrawable]; delete viewHolder; } diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 943d177232..e70c9bd351 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -12934,7 +12934,13 @@ public: Call this on the public key object to encode some data, then use the matching private key object to decode it. - Returns false if the operation failed, e.g. if this object isn't a valid key. + Returns false if the operation couldn't be completed, e.g. if this key hasn't been + initialised correctly. + + NOTE: This method dumbly applies this key to this data. If you encode some data + and then try to decode it with a key that doesn't match, this method will still + happily do its job and return true, but the result won't be what you were expecting. + It's your responsibility to check that the result is what you wanted. */ bool applyToValue (BitArray& value) const throw(); @@ -16699,6 +16705,229 @@ private: #endif // __JUCE_POINT_JUCEHEADER__ /********* End of inlined file: juce_Point.h *********/ +/********* Start of inlined file: juce_Rectangle.h *********/ +#ifndef __JUCE_RECTANGLE_JUCEHEADER__ +#define __JUCE_RECTANGLE_JUCEHEADER__ + +/** + A rectangle, specified using integer co-ordinates. + + @see RectangleList, Path, Line, Point +*/ +class JUCE_API Rectangle +{ +public: + + /** Creates a rectangle of zero size. + + The default co-ordinates will be (0, 0, 0, 0). + */ + Rectangle() throw(); + + /** Creates a copy of another rectangle. */ + Rectangle (const Rectangle& other) throw(); + + /** Creates a rectangle with a given position and size. */ + Rectangle (const int x, const int y, + const int width, const int height) throw(); + + /** Creates a rectangle with a given size, and a position of (0, 0). */ + Rectangle (const int width, const int height) throw(); + + /** Destructor. */ + ~Rectangle() throw(); + + /** Returns the x co-ordinate of the rectangle's left-hand-side. */ + inline int getX() const throw() { return x; } + + /** Returns the y co-ordinate of the rectangle's top edge. */ + inline int getY() const throw() { return y; } + + /** Returns the width of the rectangle. */ + inline int getWidth() const throw() { return w; } + + /** Returns the height of the rectangle. */ + inline int getHeight() const throw() { return h; } + + /** Returns the x co-ordinate of the rectangle's right-hand-side. */ + inline int getRight() const throw() { return x + w; } + + /** Returns the y co-ordinate of the rectangle's bottom edge. */ + inline int getBottom() const throw() { return y + h; } + + /** Returns the x co-ordinate of the rectangle's centre. */ + inline int getCentreX() const throw() { return x + (w >> 1); } + + /** Returns the y co-ordinate of the rectangle's centre. */ + inline int getCentreY() const throw() { return y + (h >> 1); } + + /** Returns true if the rectangle's width and height are both zero or less */ + bool isEmpty() const throw(); + + /** Changes the position of the rectangle's top-left corner (leaving its size unchanged). */ + void setPosition (const int x, const int y) throw(); + + /** Changes the rectangle's size, leaving the position of its top-left corner unchanged. */ + void setSize (const int w, const int h) throw(); + + /** Changes all the rectangle's co-ordinates. */ + void setBounds (const int newX, const int newY, + const int newWidth, const int newHeight) throw(); + + /** Moves the x position, adjusting the width so that the right-hand edge remains in the same place. + If the x is moved to be on the right of the current right-hand edge, the width will be set to zero. + */ + void setLeft (const int newLeft) throw(); + + /** Moves the y position, adjusting the height so that the bottom edge remains in the same place. + If the y is moved to be below the current bottom edge, the height will be set to zero. + */ + void setTop (const int newTop) throw(); + + /** Adjusts the width so that the right-hand edge of the rectangle has this new value. + If the new right is below the current X value, the X will be pushed down to match it. + @see getRight + */ + void setRight (const int newRight) throw(); + + /** Adjusts the height so that the bottom edge of the rectangle has this new value. + If the new bottom is lower than the current Y value, the Y will be pushed down to match it. + @see getBottom + */ + void setBottom (const int newBottom) throw(); + + /** Moves the rectangle's position by adding amount to its x and y co-ordinates. */ + void translate (const int deltaX, + const int deltaY) throw(); + + /** Returns a rectangle which is the same as this one moved by a given amount. */ + const Rectangle translated (const int deltaX, + const int deltaY) const throw(); + + /** Expands the rectangle by a given amount. + + Effectively, its new size is (x - deltaX, y - deltaY, w + deltaX * 2, h + deltaY * 2). + @see expanded, reduce, reduced + */ + void expand (const int deltaX, + const int deltaY) throw(); + + /** Returns a rectangle that is larger than this one by a given amount. + + Effectively, the rectangle returned is (x - deltaX, y - deltaY, w + deltaX * 2, h + deltaY * 2). + @see expand, reduce, reduced + */ + const Rectangle expanded (const int deltaX, + const int deltaY) const throw(); + + /** Shrinks the rectangle by a given amount. + + Effectively, its new size is (x + deltaX, y + deltaY, w - deltaX * 2, h - deltaY * 2). + @see reduced, expand, expanded + */ + void reduce (const int deltaX, + const int deltaY) throw(); + + /** Returns a rectangle that is smaller than this one by a given amount. + + Effectively, the rectangle returned is (x + deltaX, y + deltaY, w - deltaX * 2, h - deltaY * 2). + @see reduce, expand, expanded + */ + const Rectangle reduced (const int deltaX, + const int deltaY) const throw(); + + /** Returns true if the two rectangles are identical. */ + bool operator== (const Rectangle& other) const throw(); + + /** Returns true if the two rectangles are not identical. */ + bool operator!= (const Rectangle& other) const throw(); + + /** Returns true if this co-ordinate is inside the rectangle. */ + bool contains (const int x, const int y) const throw(); + + /** Returns true if this other rectangle is completely inside this one. */ + bool contains (const Rectangle& other) const throw(); + + /** Returns true if any part of another rectangle overlaps this one. */ + bool intersects (const Rectangle& other) const throw(); + + /** Returns the region that is the overlap between this and another rectangle. + + If the two rectangles don't overlap, the rectangle returned will be empty. + */ + const Rectangle getIntersection (const Rectangle& other) const throw(); + + /** Clips a rectangle so that it lies only within this one. + + This is a non-static version of intersectRectangles(). + + Returns false if the two regions didn't overlap. + */ + bool intersectRectangle (int& x, int& y, int& w, int& h) const throw(); + + /** Returns the smallest rectangle that contains both this one and the one + passed-in. + */ + const Rectangle getUnion (const Rectangle& other) const throw(); + + /** If this rectangle merged with another one results in a simple rectangle, this + will set this rectangle to the result, and return true. + + Returns false and does nothing to this rectangle if the two rectangles don't overlap, + or if they form a complex region. + */ + bool enlargeIfAdjacent (const Rectangle& other) throw(); + + /** If after removing another rectangle from this one the result is a simple rectangle, + this will set this object's bounds to be the result, and return true. + + Returns false and does nothing to this rectangle if the two rectangles don't overlap, + or if removing the other one would form a complex region. + */ + bool reduceIfPartlyContainedIn (const Rectangle& other) throw(); + + /** Static utility to intersect two sets of rectangular co-ordinates. + + Returns false if the two regions didn't overlap. + + @see intersectRectangle + */ + static bool intersectRectangles (int& x1, int& y1, int& w1, int& h1, + int x2, int y2, int w2, int h2) throw(); + + /** Creates a string describing this rectangle. + + The string will be of the form "x y width height", e.g. "100 100 400 200". + + Coupled with the fromString() method, this is very handy for things like + storing rectangles (particularly component positions) in XML attributes. + + @see fromString + */ + const String toString() const throw(); + + /** Parses a string containing a rectangle's details. + + The string should contain 4 integer tokens, in the form "x y width height". They + can be comma or whitespace separated. + + This method is intended to go with the toString() method, to form an easy way + of saving/loading rectangles as strings. + + @see toString + */ + static const Rectangle fromString (const String& stringVersion); + + juce_UseDebuggingNewOperator + +private: + friend class RectangleList; + int x, y, w, h; +}; + +#endif // __JUCE_RECTANGLE_JUCEHEADER__ +/********* End of inlined file: juce_Rectangle.h *********/ + /********* Start of inlined file: juce_Justification.h *********/ #ifndef __JUCE_JUSTIFICATION_JUCEHEADER__ #define __JUCE_JUSTIFICATION_JUCEHEADER__ @@ -16841,6 +17070,219 @@ private: #endif // __JUCE_JUSTIFICATION_JUCEHEADER__ /********* End of inlined file: juce_Justification.h *********/ +/********* Start of inlined file: juce_EdgeTable.h *********/ +#ifndef __JUCE_EDGETABLE_JUCEHEADER__ +#define __JUCE_EDGETABLE_JUCEHEADER__ + +class Path; +class Image; +class Rectangle; + +/** + A table of horizontal scan-line segments - used for rasterising Paths. + + @see Path, Graphics +*/ +class JUCE_API EdgeTable +{ +public: + + /** Creates an empty edge table ready to have paths added. + + A table is created with a fixed vertical size, and only sections of paths + which lie within their range will be added to the table. + + @param topY the lowest y co-ordinate that the table can contain + @param height the number of horizontal lines it can contain + */ + EdgeTable (const int topY, const int height) throw(); + + /** Creates a copy of another edge table. */ + EdgeTable (const EdgeTable& other) throw(); + + /** Copies from another edge table. */ + const EdgeTable& operator= (const EdgeTable& other) throw(); + + /** Destructor. */ + ~EdgeTable() throw(); + + /** Adds edges to the table for a path. + + This will add horizontal lines to the edge table for any parts of the path + which lie within the vertical bounds for which this table was created. + + @param path the path to add + @param transform an optional transform to apply to the path while it's + being added + */ + void addPath (const Path& path, + const AffineTransform& transform) throw(); + + /*void clipToRectangle (const Rectangle& r) throw(); + void intersectWith (const EdgeTable& other); + void generateFromImageAlpha (Image& image, int x, int y) 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) + @param clipLeft the left-hand edge of the rectangle which should be iterated + @param clipTop the top edge of the rectangle which should be iterated + @param clipRight the right-hand edge of the rectangle which should be iterated + @param clipBottom the bottom edge of the rectangle which should be iterated + @param subPixelXOffset a fraction of 1 pixel by which to shift the table rightwards, in the range 0 to 255 + */ + template + void iterate (EdgeTableIterationCallback& iterationCallback, + const int clipLeft, int clipTop, + const int clipRight, int clipBottom, + const int subPixelXOffset) const throw() + { + if (clipTop < top) + clipTop = top; + + if (clipBottom > top + height) + clipBottom = top + height; + + const int* lineStart = table + lineStrideElements * (clipTop - top); + + for (int y = clipTop; y < clipBottom; ++y) + { + const int* line = lineStart; + lineStart += lineStrideElements; + int numPoints = line[0]; + + if (--numPoints > 0) + { + int x = subPixelXOffset + *++line; + int level = *++line; + int levelAccumulator = 0; + + iterationCallback.setEdgeTableYPos (y); + + while (--numPoints >= 0) + { + int correctedLevel = abs (level); + if (correctedLevel >> 8) + { + if (nonZeroWinding) + { + correctedLevel = 0xff; + } + else + { + correctedLevel &= 511; + if (correctedLevel >> 8) + correctedLevel = 511 - correctedLevel; + } + } + + const int endX = subPixelXOffset + *++line; + jassert (endX >= x); + 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) * correctedLevel; + } + 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)) * correctedLevel; + + x >>= 8; + if (x >= clipRight) + { + levelAccumulator = 0; + break; + } + + if (x >= clipLeft) + { + levelAccumulator >>= 8; + if (levelAccumulator > 0) + iterationCallback.handleEdgeTablePixel (x, jmin (0xff, levelAccumulator)); + } + + if (++x >= clipRight) + { + levelAccumulator = 0; + break; + } + + // if there's a segment of solid pixels, do it all in one go.. + if (correctedLevel > 0 && endOfRun > x) + { + if (x < clipLeft) + x = clipLeft; + + if (endOfRun > clipRight) + endOfRun = clipRight; + + const int numPix = endOfRun - x; + + if (numPix > 0) + iterationCallback.handleEdgeTableLine (x, numPix, + jmin (correctedLevel, 0xff)); + } + + // save the bit at the end to be drawn next time round the loop. + levelAccumulator = (endX & 0xff) * correctedLevel; + } + + level += *++line; + x = endX; + } + + if (levelAccumulator > 0) + { + levelAccumulator >>= 8; + if (levelAccumulator >> 8) + levelAccumulator = 0xff; + + x >>= 8; + if (x >= clipLeft && x < clipRight) + iterationCallback.handleEdgeTablePixel (x, levelAccumulator); + } + } + } + } + + juce_UseDebuggingNewOperator + +private: + // table line format: number of points; point0 x, point0 levelDelta, point1 x, point1 levelDelta, etc + int* table; + int top, height, maxEdgesPerLine, lineStrideElements; + bool nonZeroWinding; + + void addEdgePoint (const int x, const int y, const int winding) throw(); + void remapTableForNumEdges (const int newNumEdgesPerLine) throw(); +}; + +#endif // __JUCE_EDGETABLE_JUCEHEADER__ +/********* End of inlined file: juce_EdgeTable.h *********/ + +class Image; + /** A path is a sequence of lines and curves that may either form a closed shape or be open-ended. @@ -17408,6 +17850,21 @@ public: */ void restoreFromString (const String& stringVersion); + /** Creates a single-channel bitmap containing a mask of this path. + + The smallest bitmap that contains the path will be created, and on return, the + imagePosition rectangle indicates the position of the newly created image, relative + to the path's origin. + + Only the intersection of the path's bounds with the specified clipRegion rectangle + will be rendered. + + If the path is empty or doesn't intersect the clip region, this may return 0. + */ + Image* createMaskBitmap (const AffineTransform& transform, + const Rectangle& clipRegion, + Rectangle& imagePosition) const throw(); + juce_UseDebuggingNewOperator private: @@ -17962,229 +18419,6 @@ private: #endif // __JUCE_FONT_JUCEHEADER__ /********* End of inlined file: juce_Font.h *********/ -/********* Start of inlined file: juce_Rectangle.h *********/ -#ifndef __JUCE_RECTANGLE_JUCEHEADER__ -#define __JUCE_RECTANGLE_JUCEHEADER__ - -/** - A rectangle, specified using integer co-ordinates. - - @see RectangleList, Path, Line, Point -*/ -class JUCE_API Rectangle -{ -public: - - /** Creates a rectangle of zero size. - - The default co-ordinates will be (0, 0, 0, 0). - */ - Rectangle() throw(); - - /** Creates a copy of another rectangle. */ - Rectangle (const Rectangle& other) throw(); - - /** Creates a rectangle with a given position and size. */ - Rectangle (const int x, const int y, - const int width, const int height) throw(); - - /** Creates a rectangle with a given size, and a position of (0, 0). */ - Rectangle (const int width, const int height) throw(); - - /** Destructor. */ - ~Rectangle() throw(); - - /** Returns the x co-ordinate of the rectangle's left-hand-side. */ - inline int getX() const throw() { return x; } - - /** Returns the y co-ordinate of the rectangle's top edge. */ - inline int getY() const throw() { return y; } - - /** Returns the width of the rectangle. */ - inline int getWidth() const throw() { return w; } - - /** Returns the height of the rectangle. */ - inline int getHeight() const throw() { return h; } - - /** Returns the x co-ordinate of the rectangle's right-hand-side. */ - inline int getRight() const throw() { return x + w; } - - /** Returns the y co-ordinate of the rectangle's bottom edge. */ - inline int getBottom() const throw() { return y + h; } - - /** Returns the x co-ordinate of the rectangle's centre. */ - inline int getCentreX() const throw() { return x + (w >> 1); } - - /** Returns the y co-ordinate of the rectangle's centre. */ - inline int getCentreY() const throw() { return y + (h >> 1); } - - /** Returns true if the rectangle's width and height are both zero or less */ - bool isEmpty() const throw(); - - /** Changes the position of the rectangle's top-left corner (leaving its size unchanged). */ - void setPosition (const int x, const int y) throw(); - - /** Changes the rectangle's size, leaving the position of its top-left corner unchanged. */ - void setSize (const int w, const int h) throw(); - - /** Changes all the rectangle's co-ordinates. */ - void setBounds (const int newX, const int newY, - const int newWidth, const int newHeight) throw(); - - /** Moves the x position, adjusting the width so that the right-hand edge remains in the same place. - If the x is moved to be on the right of the current right-hand edge, the width will be set to zero. - */ - void setLeft (const int newLeft) throw(); - - /** Moves the y position, adjusting the height so that the bottom edge remains in the same place. - If the y is moved to be below the current bottom edge, the height will be set to zero. - */ - void setTop (const int newTop) throw(); - - /** Adjusts the width so that the right-hand edge of the rectangle has this new value. - If the new right is below the current X value, the X will be pushed down to match it. - @see getRight - */ - void setRight (const int newRight) throw(); - - /** Adjusts the height so that the bottom edge of the rectangle has this new value. - If the new bottom is lower than the current Y value, the Y will be pushed down to match it. - @see getBottom - */ - void setBottom (const int newBottom) throw(); - - /** Moves the rectangle's position by adding amount to its x and y co-ordinates. */ - void translate (const int deltaX, - const int deltaY) throw(); - - /** Returns a rectangle which is the same as this one moved by a given amount. */ - const Rectangle translated (const int deltaX, - const int deltaY) const throw(); - - /** Expands the rectangle by a given amount. - - Effectively, its new size is (x - deltaX, y - deltaY, w + deltaX * 2, h + deltaY * 2). - @see expanded, reduce, reduced - */ - void expand (const int deltaX, - const int deltaY) throw(); - - /** Returns a rectangle that is larger than this one by a given amount. - - Effectively, the rectangle returned is (x - deltaX, y - deltaY, w + deltaX * 2, h + deltaY * 2). - @see expand, reduce, reduced - */ - const Rectangle expanded (const int deltaX, - const int deltaY) const throw(); - - /** Shrinks the rectangle by a given amount. - - Effectively, its new size is (x + deltaX, y + deltaY, w - deltaX * 2, h - deltaY * 2). - @see reduced, expand, expanded - */ - void reduce (const int deltaX, - const int deltaY) throw(); - - /** Returns a rectangle that is smaller than this one by a given amount. - - Effectively, the rectangle returned is (x + deltaX, y + deltaY, w - deltaX * 2, h - deltaY * 2). - @see reduce, expand, expanded - */ - const Rectangle reduced (const int deltaX, - const int deltaY) const throw(); - - /** Returns true if the two rectangles are identical. */ - bool operator== (const Rectangle& other) const throw(); - - /** Returns true if the two rectangles are not identical. */ - bool operator!= (const Rectangle& other) const throw(); - - /** Returns true if this co-ordinate is inside the rectangle. */ - bool contains (const int x, const int y) const throw(); - - /** Returns true if this other rectangle is completely inside this one. */ - bool contains (const Rectangle& other) const throw(); - - /** Returns true if any part of another rectangle overlaps this one. */ - bool intersects (const Rectangle& other) const throw(); - - /** Returns the region that is the overlap between this and another rectangle. - - If the two rectangles don't overlap, the rectangle returned will be empty. - */ - const Rectangle getIntersection (const Rectangle& other) const throw(); - - /** Clips a rectangle so that it lies only within this one. - - This is a non-static version of intersectRectangles(). - - Returns false if the two regions didn't overlap. - */ - bool intersectRectangle (int& x, int& y, int& w, int& h) const throw(); - - /** Returns the smallest rectangle that contains both this one and the one - passed-in. - */ - const Rectangle getUnion (const Rectangle& other) const throw(); - - /** If this rectangle merged with another one results in a simple rectangle, this - will set this rectangle to the result, and return true. - - Returns false and does nothing to this rectangle if the two rectangles don't overlap, - or if they form a complex region. - */ - bool enlargeIfAdjacent (const Rectangle& other) throw(); - - /** If after removing another rectangle from this one the result is a simple rectangle, - this will set this object's bounds to be the result, and return true. - - Returns false and does nothing to this rectangle if the two rectangles don't overlap, - or if removing the other one would form a complex region. - */ - bool reduceIfPartlyContainedIn (const Rectangle& other) throw(); - - /** Static utility to intersect two sets of rectangular co-ordinates. - - Returns false if the two regions didn't overlap. - - @see intersectRectangle - */ - static bool intersectRectangles (int& x1, int& y1, int& w1, int& h1, - int x2, int y2, int w2, int h2) throw(); - - /** Creates a string describing this rectangle. - - The string will be of the form "x y width height", e.g. "100 100 400 200". - - Coupled with the fromString() method, this is very handy for things like - storing rectangles (particularly component positions) in XML attributes. - - @see fromString - */ - const String toString() const throw(); - - /** Parses a string containing a rectangle's details. - - The string should contain 4 integer tokens, in the form "x y width height". They - can be comma or whitespace separated. - - This method is intended to go with the toString() method, to form an easy way - of saving/loading rectangles as strings. - - @see toString - */ - static const Rectangle fromString (const String& stringVersion); - - juce_UseDebuggingNewOperator - -private: - friend class RectangleList; - int x, y, w, h; -}; - -#endif // __JUCE_RECTANGLE_JUCEHEADER__ -/********* End of inlined file: juce_Rectangle.h *********/ - /********* Start of inlined file: juce_PathStrokeType.h *********/ #ifndef __JUCE_PATHSTROKETYPE_JUCEHEADER__ #define __JUCE_PATHSTROKETYPE_JUCEHEADER__ @@ -20366,6 +20600,32 @@ public: /** @internal */ LowLevelGraphicsContext* getInternalContext() const throw() { return context; } + /*class FillType + { + public: + FillType (const Colour& colour) throw(); + FillType (const ColourGradient& gradient) throw(); + FillType (Image* image, int x, int y) throw(); + FillType (const FillType& other) throw(); + const FillType& operator= (const FillType& other) throw(); + ~FillType() throw(); + + bool isColour() const throw() { return gradient == 0 && image == 0; } + bool isGradient() const throw() { return gradient != 0; } + bool isTiledImage() const throw() { return image != 0; } + + void setColour (const Colour& newColour) throw(); + void setGradient (const ColourGradient& newGradient) throw(); + void setTiledImage (Image* image, const int imageX, const int imageY) throw(); + + Colour colour; + ColourGradient* gradient; + Image* image; + int imageX, imageY; + + juce_UseDebuggingNewOperator + };*/ + private: LowLevelGraphicsContext* const context; @@ -39573,279 +39833,6 @@ private: #endif #ifndef __JUCE_EDGETABLE_JUCEHEADER__ -/********* Start of inlined file: juce_EdgeTable.h *********/ -#ifndef __JUCE_EDGETABLE_JUCEHEADER__ -#define __JUCE_EDGETABLE_JUCEHEADER__ - -class Path; - -static const int juce_edgeTableDefaultEdgesPerLine = 10; - -/** - A table of horizontal scan-line segments - used for rasterising Paths. - - @see Path, Graphics -*/ -class JUCE_API EdgeTable -{ -public: - - /** Indicates the quality at which the edge table should be generated. - - Higher values will have better quality anti-aliasing, but will take - longer to generate the edge table and to render it. - */ - enum OversamplingLevel - { - Oversampling_none = 0, /**< No vertical anti-aliasing at all. */ - Oversampling_4times = 2, /**< Anti-aliased with 4 levels of grey - good enough for normal use. */ - Oversampling_16times = 4, /**< Anti-aliased with 16 levels of grey - very good quality. */ - Oversampling_32times = 5, /**< Anti-aliased with 32 levels of grey - very good quality but slower. */ - Oversampling_256times = 8 /**< Anti-aliased with 256 levels of grey - best quality, but too slow for - normal user-interface use. */ - }; - - /** Creates an empty edge table ready to have paths added. - - A table is created with a fixed vertical size, and only sections of paths - which lie within their range will be added to the table. - - @param topY the lowest y co-ordinate that the table can contain - @param height the number of horizontal lines it can contain - @param verticalOversampling the amount of oversampling used for anti-aliasing - @param expectedEdgesPerLine used to optimise the table's internal data usage - it's not - worth changing this except for very special purposes - */ - EdgeTable (const int topY, - const int height, - const OversamplingLevel verticalOversampling = Oversampling_4times, - const int expectedEdgesPerLine = juce_edgeTableDefaultEdgesPerLine) throw(); - - /** Creates a copy of another edge table. */ - EdgeTable (const EdgeTable& other) throw(); - - /** Copies from another edge table. */ - const EdgeTable& operator= (const EdgeTable& other) throw(); - - /** Destructor. */ - ~EdgeTable() throw(); - - /** Adds edges to the table for a path. - - This will add horizontal lines to the edge table for any parts of the path - which lie within the vertical bounds for which this table was created. - - @param path the path to add - @param transform an optional transform to apply to the path while it's - being added - */ - void addPath (const Path& path, - const AffineTransform& transform) 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) - @param clipLeft the left-hand edge of the rectangle which should be iterated - @param clipTop the top edge of the rectangle which should be iterated - @param clipRight the right-hand edge of the rectangle which should be iterated - @param clipBottom the bottom edge of the rectangle which should be iterated - @param subPixelXOffset a fraction of 1 pixel by which to shift the table rightwards, in the range 0 to 255 - */ - template - void iterate (EdgeTableIterationCallback& iterationCallback, - const int clipLeft, - int clipTop, - const int clipRight, - int clipBottom, - const int subPixelXOffset) const - { - if (clipTop < top) - clipTop = top; - - if (clipBottom > top + height) - clipBottom = top + height; - - const int* singleLine = table + lineStrideElements - * ((clipTop - top) << (int) oversampling); - - int mergedLineAllocation = 128; - MemoryBlock temp (mergedLineAllocation * (2 * sizeof (int))); - int* mergedLine = (int*) temp.getData(); - - const int timesOverSampling = 1 << (int) oversampling; - - for (int y = clipTop; y < clipBottom; ++y) - { - int numMergedPoints = 0; - - // sort all the oversampled lines into a single merged line ready to draw.. - for (int over = timesOverSampling; --over >= 0;) - { - const int* l = singleLine; - singleLine += lineStrideElements; - - int num = *l; - jassert (num >= 0); - - if (num > 0) - { - if (numMergedPoints + num >= mergedLineAllocation) - { - mergedLineAllocation = (numMergedPoints + num + 0x100) & ~0xff; - temp.setSize (mergedLineAllocation * (2 * sizeof (int)), false); - mergedLine = (int*) temp.getData(); - } - - while (--num >= 0) - { - const int x = *++l; - const int winding = *++l; - - int n = numMergedPoints << 1; - - while (n > 0) - { - const int cx = mergedLine [n - 2]; - - if (cx <= x) - break; - - mergedLine [n] = cx; - --n; - mergedLine [n + 2] = mergedLine [n]; - --n; - } - - mergedLine [n] = x; - mergedLine [n + 1] = winding; - - ++numMergedPoints; - } - } - } - - if (--numMergedPoints > 0) - { - const int* line = mergedLine; - int x = subPixelXOffset + *line; - int level = *++line; - int levelAccumulator = 0; - - iterationCallback.setEdgeTableYPos (y); - - while (--numMergedPoints >= 0) - { - const int endX = subPixelXOffset + *++line; - jassert (endX >= x); - - const int absLevel = abs (level); - 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) * absLevel; - } - 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)) * absLevel; - - levelAccumulator >>= 8; - if (levelAccumulator > 0xff) - levelAccumulator = 0xff; - - x >>= 8; - - if (x >= clipRight) - { - levelAccumulator = 0; - break; - } - - if (x >= clipLeft && x < clipRight && levelAccumulator > 0) - iterationCallback.handleEdgeTablePixel (x, levelAccumulator); - - if (++x >= clipRight) - { - levelAccumulator = 0; - break; - } - - // if there's a segment of solid pixels, do it all in one go.. - if (absLevel > 0 && endOfRun > x) - { - if (x < clipLeft) - x = clipLeft; - - if (endOfRun > clipRight) - endOfRun = clipRight; - - const int numPix = endOfRun - x; - - if (numPix > 0) - iterationCallback.handleEdgeTableLine (x, numPix, - jmin (absLevel, 0xff)); - } - - // save the bit at the end to be drawn next time round the loop. - levelAccumulator = (endX & 0xff) * absLevel; - } - - level += *++line; - x = endX; - } - - if (levelAccumulator > 0) - { - levelAccumulator >>= 8; - if (levelAccumulator > 0xff) - levelAccumulator = 0xff; - - x >>= 8; - if (x >= clipLeft && x < clipRight) - iterationCallback.handleEdgeTablePixel (x, levelAccumulator); - } - } - } - } - - juce_UseDebuggingNewOperator - -private: - // table line format: number of points; point0 x, point0 levelDelta, point1 x, point1 levelDelta, etc - int* table; - int top, height, maxEdgesPerLine, lineStrideElements; - OversamplingLevel oversampling; - - // this will assume that the y co-ord is within bounds, and will avoid checking - // this for speed. - void addEdgePoint (const int x, const int y, const int winding) throw(); - - void remapTableForNumEdges (const int newNumEdgesPerLine) throw(); -}; - -#endif // __JUCE_EDGETABLE_JUCEHEADER__ -/********* End of inlined file: juce_EdgeTable.h *********/ - #endif #ifndef __JUCE_JUSTIFICATION_JUCEHEADER__ @@ -39894,6 +39881,9 @@ public: /** Cliping co-ords are relative to the origin. */ virtual bool reduceClipRegion (const RectangleList& clipRegion) = 0; + //virtual bool clipToPath (const Path& path) = 0; + //virtual bool clipToImageAlpha (Image& image, int imageX, int imageY) = 0; + /** Cliping co-ords are relative to the origin. */ virtual void excludeClipRegion (int x, int y, int w, int h) = 0; @@ -39910,10 +39900,10 @@ public: virtual void setInterpolationQuality (Graphics::ResamplingQuality quality) = 0; virtual void fillRect (int x, int y, int w, int h, const bool replaceExistingContents) = 0; - virtual void fillPath (const Path& path, const AffineTransform& transform, EdgeTable::OversamplingLevel quality) = 0; + virtual void fillPath (const Path& path, const AffineTransform& transform) = 0; virtual void fillPathWithImage (const Path& path, const AffineTransform& transform, - const Image& image, int imageX, int imageY, EdgeTable::OversamplingLevel quality) = 0; + const Image& image, int imageX, int imageY) = 0; virtual void fillAlphaChannel (const Image& alphaImage, int alphaImageX, int alphaImageY) = 0; virtual void fillAlphaChannelWithImage (const Image& alphaImage, int alphaImageX, int alphaImageY, @@ -39980,10 +39970,10 @@ public: void setInterpolationQuality (Graphics::ResamplingQuality quality); void fillRect (int x, int y, int w, int h, const bool replaceExistingContents); - void fillPath (const Path& path, const AffineTransform& transform, EdgeTable::OversamplingLevel quality); + void fillPath (const Path& path, const AffineTransform& transform); void fillPathWithImage (const Path& path, const AffineTransform& transform, - const Image& image, int imageX, int imageY, EdgeTable::OversamplingLevel quality); + const Image& image, int imageX, int imageY); void fillAlphaChannel (const Image& alphaImage, int imageX, int imageY); void fillAlphaChannelWithImage (const Image& alphaImage, int alphaImageX, int alphaImageY, @@ -40048,9 +40038,9 @@ protected: void clippedFillRectWithColour (const Rectangle& clipRect, int x, int y, int w, int h, const Colour& colour, const bool replaceExistingContents); - void clippedFillPath (int clipX, int clipY, int clipW, int clipH, const Path& path, const AffineTransform& transform, EdgeTable::OversamplingLevel quality); + void clippedFillPath (int clipX, int clipY, int clipW, int clipH, const Path& path, const AffineTransform& transform); void clippedFillPathWithImage (int clipX, int clipY, int clipW, int clipH, const Path& path, const AffineTransform& transform, - const Image& image, int imageX, int imageY, float alpha, EdgeTable::OversamplingLevel quality); + const Image& image, int imageX, int imageY, float alpha); void clippedFillAlphaChannel (int clipX, int clipY, int clipW, int clipH, const Image& alphaImage, int alphaImageX, int alphaImageY); void clippedFillAlphaChannelWithImage (int clipX, int clipY, int clipW, int clipH, const Image& alphaImage, int alphaImageX, int alphaImageY, @@ -40124,10 +40114,10 @@ public: void setInterpolationQuality (Graphics::ResamplingQuality quality); void fillRect (int x, int y, int w, int h, const bool replaceExistingContents); - void fillPath (const Path& path, const AffineTransform& transform, EdgeTable::OversamplingLevel quality); + void fillPath (const Path& path, const AffineTransform& transform); void fillPathWithImage (const Path& path, const AffineTransform& transform, - const Image& image, int imageX, int imageY, EdgeTable::OversamplingLevel quality); + const Image& image, int imageX, int imageY); void fillAlphaChannel (const Image& alphaImage, int imageX, int imageY); void fillAlphaChannelWithImage (const Image& alphaImage, int alphaImageX, int alphaImageY, diff --git a/src/cryptography/juce_RSAKey.h b/src/cryptography/juce_RSAKey.h index 87e48e18d9..98f9f9d907 100644 --- a/src/cryptography/juce_RSAKey.h +++ b/src/cryptography/juce_RSAKey.h @@ -68,7 +68,13 @@ public: Call this on the public key object to encode some data, then use the matching private key object to decode it. - Returns false if the operation failed, e.g. if this object isn't a valid key. + Returns false if the operation couldn't be completed, e.g. if this key hasn't been + initialised correctly. + + NOTE: This method dumbly applies this key to this data. If you encode some data + and then try to decode it with a key that doesn't match, this method will still + happily do its job and return true, but the result won't be what you were expecting. + It's your responsibility to check that the result is what you wanted. */ bool applyToValue (BitArray& value) const throw(); diff --git a/src/gui/graphics/brushes/juce_GradientBrush.cpp b/src/gui/graphics/brushes/juce_GradientBrush.cpp index e9ccc0cfa3..90645cf7ae 100644 --- a/src/gui/graphics/brushes/juce_GradientBrush.cpp +++ b/src/gui/graphics/brushes/juce_GradientBrush.cpp @@ -80,7 +80,7 @@ void GradientBrush::paintPath (LowLevelGraphicsContext& context, const Path& path, const AffineTransform& transform) throw() { context.setGradient (gradient); - context.fillPath (path, transform, EdgeTable::Oversampling_4times); + context.fillPath (path, transform); } void GradientBrush::paintRectangle (LowLevelGraphicsContext& context, diff --git a/src/gui/graphics/brushes/juce_ImageBrush.cpp b/src/gui/graphics/brushes/juce_ImageBrush.cpp index be87d05b83..706a875e74 100644 --- a/src/gui/graphics/brushes/juce_ImageBrush.cpp +++ b/src/gui/graphics/brushes/juce_ImageBrush.cpp @@ -171,7 +171,7 @@ void ImageBrush::paintPath (LowLevelGraphicsContext& context, while (x < right) { - context.fillPathWithImage (path, transform, *image, x, y, EdgeTable::Oversampling_4times); + context.fillPathWithImage (path, transform, *image, x, y); x += iw; } diff --git a/src/gui/graphics/brushes/juce_SolidColourBrush.cpp b/src/gui/graphics/brushes/juce_SolidColourBrush.cpp index b68c6394e1..41fb234aa7 100644 --- a/src/gui/graphics/brushes/juce_SolidColourBrush.cpp +++ b/src/gui/graphics/brushes/juce_SolidColourBrush.cpp @@ -70,7 +70,7 @@ void SolidColourBrush::paintPath (LowLevelGraphicsContext& context, const Path& path, const AffineTransform& transform) throw() { context.setColour (colour); - context.fillPath (path, transform, EdgeTable::Oversampling_4times); + context.fillPath (path, transform); } void SolidColourBrush::paintRectangle (LowLevelGraphicsContext& context, diff --git a/src/gui/graphics/contexts/juce_EdgeTable.cpp b/src/gui/graphics/contexts/juce_EdgeTable.cpp index 0d2324d660..021fe16aac 100644 --- a/src/gui/graphics/contexts/juce_EdgeTable.cpp +++ b/src/gui/graphics/contexts/juce_EdgeTable.cpp @@ -27,24 +27,20 @@ BEGIN_JUCE_NAMESPACE - #include "juce_EdgeTable.h" #include "../geometry/juce_PathIterator.h" +const int juce_edgeTableDefaultEdgesPerLine = 32; //============================================================================== -EdgeTable::EdgeTable (const int top_, - const int height_, - const OversamplingLevel oversampling_, - const int expectedEdgesPerLine) throw() +EdgeTable::EdgeTable (const int top_, const int height_) throw() : top (top_), height (height_), - maxEdgesPerLine (expectedEdgesPerLine), - lineStrideElements ((expectedEdgesPerLine << 1) + 1), - oversampling (oversampling_) + maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), + lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), + nonZeroWinding (true) { - table = (int*) juce_calloc ((height << (int)oversampling_) - * lineStrideElements * sizeof (int)); + table = (int*) juce_calloc (height * lineStrideElements * sizeof (int)); } EdgeTable::EdgeTable (const EdgeTable& other) throw() @@ -61,11 +57,9 @@ const EdgeTable& EdgeTable::operator= (const EdgeTable& other) throw() height = other.height; maxEdgesPerLine = other.maxEdgesPerLine; lineStrideElements = other.lineStrideElements; - oversampling = other.oversampling; - - const int tableSize = (height << (int)oversampling) - * lineStrideElements * sizeof (int); + nonZeroWinding = other.nonZeroWinding; + const int tableSize = height * lineStrideElements * sizeof (int); table = (int*) juce_malloc (tableSize); memcpy (table, other.table, tableSize); @@ -85,10 +79,9 @@ void EdgeTable::remapTableForNumEdges (const int newNumEdgesPerLine) throw() maxEdgesPerLine = newNumEdgesPerLine; const int newLineStrideElements = maxEdgesPerLine * 2 + 1; - int* const newTable = (int*) juce_malloc ((height << (int) oversampling) - * newLineStrideElements * sizeof (int)); + int* const newTable = (int*) juce_malloc (height * newLineStrideElements * sizeof (int)); - for (int i = 0; i < (height << (int) oversampling); ++i) + for (int i = 0; i < height; ++i) { const int* srcLine = table + lineStrideElements * i; int* dstLine = newTable + newLineStrideElements * i; @@ -121,7 +114,7 @@ void EdgeTable::optimiseTable() throw() //============================================================================== void EdgeTable::addEdgePoint (const int x, const int y, const int winding) throw() { - jassert (y >= 0 && y < (height << oversampling)) + jassert (y >= 0 && y < height) int* lineStart = table + lineStrideElements * y; int n = lineStart[0]; @@ -159,39 +152,28 @@ void EdgeTable::addEdgePoint (const int x, const int y, const int winding) throw void EdgeTable::addPath (const Path& path, const AffineTransform& transform) throw() { - const int windingAmount = 256 / (1 << (int) oversampling); - const float timesOversampling = (float) (1 << (int) oversampling); - - const int bottomLimit = (height << (int) oversampling); + nonZeroWinding = path.isUsingNonZeroWinding(); + const int bottomLimit = height << 8; PathFlatteningIterator iter (path, transform); while (iter.next()) { - int y1 = roundFloatToInt (iter.y1 * timesOversampling) - (top << (int) oversampling); - int y2 = roundFloatToInt (iter.y2 * timesOversampling) - (top << (int) oversampling); + int y1 = roundFloatToInt (iter.y1 * 256.0f) - (top << 8); + int y2 = roundFloatToInt (iter.y2 * 256.0f) - (top << 8); if (y1 != y2) { const double x1 = 256.0 * iter.x1; const double x2 = 256.0 * iter.x2; - const double multiplier = (x2 - x1) / (y2 - y1); - - const int oldY1 = y1; - int winding; + int winding = -1; if (y1 > y2) { swapVariables (y1, y2); - winding = windingAmount; + winding = 1; } - else - { - winding = -windingAmount; - } - - jassert (y1 < y2); if (y1 < 0) y1 = 0; @@ -199,45 +181,32 @@ void EdgeTable::addPath (const Path& path, if (y2 > bottomLimit) y2 = bottomLimit; + const int oldY1 = y1; + const int stepSize = jlimit (1, 256, 256 / (1 + abs ((int) multiplier))); + while (y1 < y2) { + const int step = jmin (stepSize, y2 - y1, 256 - (y1 & 255)); + addEdgePoint (roundDoubleToInt (x1 + multiplier * (y1 - oldY1)), - y1, - winding); + y1 >> 8, winding * step); - ++y1; - } - } - } - - if (! path.isUsingNonZeroWinding()) - { - // if it's an alternate-winding path, we need to go through and - // make sure all the windings are alternating. - - int* lineStart = table; - - for (int i = height << (int) oversampling; --i >= 0;) - { - int* line = lineStart; - lineStart += lineStrideElements; - - int num = *line; - - while (--num >= 0) - { - line += 2; - *line = abs (*line); - - if (--num >= 0) - { - line += 2; - *line = -abs (*line); - } + y1 += step; } } } } +/*void EdgeTable::clipToRectangle (const Rectangle& r) throw() +{ +} + +void EdgeTable::intersectWith (const EdgeTable& other) +{ +} + +void EdgeTable::generateFromImageAlpha (Image& image, int x, int y) throw() +{ +}*/ END_JUCE_NAMESPACE diff --git a/src/gui/graphics/contexts/juce_EdgeTable.h b/src/gui/graphics/contexts/juce_EdgeTable.h index 3725e39e55..e643d6d025 100644 --- a/src/gui/graphics/contexts/juce_EdgeTable.h +++ b/src/gui/graphics/contexts/juce_EdgeTable.h @@ -29,9 +29,8 @@ #include "../geometry/juce_AffineTransform.h" #include "../../../containers/juce_MemoryBlock.h" class Path; - -static const int juce_edgeTableDefaultEdgesPerLine = 10; - +class Image; +class Rectangle; //============================================================================== /** @@ -43,21 +42,6 @@ class JUCE_API EdgeTable { public: //============================================================================== - /** Indicates the quality at which the edge table should be generated. - - Higher values will have better quality anti-aliasing, but will take - longer to generate the edge table and to render it. - */ - enum OversamplingLevel - { - Oversampling_none = 0, /**< No vertical anti-aliasing at all. */ - Oversampling_4times = 2, /**< Anti-aliased with 4 levels of grey - good enough for normal use. */ - Oversampling_16times = 4, /**< Anti-aliased with 16 levels of grey - very good quality. */ - Oversampling_32times = 5, /**< Anti-aliased with 32 levels of grey - very good quality but slower. */ - Oversampling_256times = 8 /**< Anti-aliased with 256 levels of grey - best quality, but too slow for - normal user-interface use. */ - }; - /** Creates an empty edge table ready to have paths added. A table is created with a fixed vertical size, and only sections of paths @@ -65,14 +49,8 @@ public: @param topY the lowest y co-ordinate that the table can contain @param height the number of horizontal lines it can contain - @param verticalOversampling the amount of oversampling used for anti-aliasing - @param expectedEdgesPerLine used to optimise the table's internal data usage - it's not - worth changing this except for very special purposes */ - EdgeTable (const int topY, - const int height, - const OversamplingLevel verticalOversampling = Oversampling_4times, - const int expectedEdgesPerLine = juce_edgeTableDefaultEdgesPerLine) throw(); + EdgeTable (const int topY, const int height) throw(); /** Creates a copy of another edge table. */ EdgeTable (const EdgeTable& other) throw(); @@ -96,6 +74,10 @@ public: void addPath (const Path& path, const AffineTransform& transform) throw(); + /*void clipToRectangle (const Rectangle& r) throw(); + void intersectWith (const EdgeTable& other); + void generateFromImageAlpha (Image& image, int x, int y) 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 @@ -125,11 +107,9 @@ public: */ template void iterate (EdgeTableIterationCallback& iterationCallback, - const int clipLeft, - int clipTop, - const int clipRight, - int clipBottom, - const int subPixelXOffset) const + const int clipLeft, int clipTop, + const int clipRight, int clipBottom, + const int subPixelXOffset) const throw() { if (clipTop < top) clipTop = top; @@ -137,108 +117,68 @@ public: if (clipBottom > top + height) clipBottom = top + height; - const int* singleLine = table + lineStrideElements - * ((clipTop - top) << (int) oversampling); - - int mergedLineAllocation = 128; - MemoryBlock temp (mergedLineAllocation * (2 * sizeof (int))); - int* mergedLine = (int*) temp.getData(); - - const int timesOverSampling = 1 << (int) oversampling; + const int* lineStart = table + lineStrideElements * (clipTop - top); for (int y = clipTop; y < clipBottom; ++y) { - int numMergedPoints = 0; + const int* line = lineStart; + lineStart += lineStrideElements; + int numPoints = line[0]; - // sort all the oversampled lines into a single merged line ready to draw.. - for (int over = timesOverSampling; --over >= 0;) + if (--numPoints > 0) { - const int* l = singleLine; - singleLine += lineStrideElements; - - int num = *l; - jassert (num >= 0); - - if (num > 0) - { - if (numMergedPoints + num >= mergedLineAllocation) - { - mergedLineAllocation = (numMergedPoints + num + 0x100) & ~0xff; - temp.setSize (mergedLineAllocation * (2 * sizeof (int)), false); - mergedLine = (int*) temp.getData(); - } - - while (--num >= 0) - { - const int x = *++l; - const int winding = *++l; - - int n = numMergedPoints << 1; - - while (n > 0) - { - const int cx = mergedLine [n - 2]; - - if (cx <= x) - break; - - mergedLine [n] = cx; - --n; - mergedLine [n + 2] = mergedLine [n]; - --n; - } - - mergedLine [n] = x; - mergedLine [n + 1] = winding; - - ++numMergedPoints; - } - } - } - - if (--numMergedPoints > 0) - { - const int* line = mergedLine; - int x = subPixelXOffset + *line; + int x = subPixelXOffset + *++line; int level = *++line; int levelAccumulator = 0; iterationCallback.setEdgeTableYPos (y); - while (--numMergedPoints >= 0) + while (--numPoints >= 0) { + int correctedLevel = abs (level); + if (correctedLevel >> 8) + { + if (nonZeroWinding) + { + correctedLevel = 0xff; + } + else + { + correctedLevel &= 511; + if (correctedLevel >> 8) + correctedLevel = 511 - correctedLevel; + } + } + const int endX = subPixelXOffset + *++line; jassert (endX >= x); - - const int absLevel = abs (level); 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) * absLevel; + levelAccumulator += (endX - x) * correctedLevel; } 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)) * absLevel; - - levelAccumulator >>= 8; - if (levelAccumulator > 0xff) - levelAccumulator = 0xff; + levelAccumulator += (0xff - (x & 0xff)) * correctedLevel; x >>= 8; - if (x >= clipRight) { levelAccumulator = 0; break; } - if (x >= clipLeft && x < clipRight && levelAccumulator > 0) - iterationCallback.handleEdgeTablePixel (x, levelAccumulator); + if (x >= clipLeft) + { + levelAccumulator >>= 8; + if (levelAccumulator > 0) + iterationCallback.handleEdgeTablePixel (x, jmin (0xff, levelAccumulator)); + } if (++x >= clipRight) { @@ -247,7 +187,7 @@ public: } // if there's a segment of solid pixels, do it all in one go.. - if (absLevel > 0 && endOfRun > x) + if (correctedLevel > 0 && endOfRun > x) { if (x < clipLeft) x = clipLeft; @@ -259,11 +199,11 @@ public: if (numPix > 0) iterationCallback.handleEdgeTableLine (x, numPix, - jmin (absLevel, 0xff)); + jmin (correctedLevel, 0xff)); } // save the bit at the end to be drawn next time round the loop. - levelAccumulator = (endX & 0xff) * absLevel; + levelAccumulator = (endX & 0xff) * correctedLevel; } level += *++line; @@ -273,7 +213,7 @@ public: if (levelAccumulator > 0) { levelAccumulator >>= 8; - if (levelAccumulator > 0xff) + if (levelAccumulator >> 8) levelAccumulator = 0xff; x >>= 8; @@ -284,7 +224,6 @@ public: } } - //============================================================================== juce_UseDebuggingNewOperator @@ -292,12 +231,9 @@ private: // table line format: number of points; point0 x, point0 levelDelta, point1 x, point1 levelDelta, etc int* table; int top, height, maxEdgesPerLine, lineStrideElements; - OversamplingLevel oversampling; + bool nonZeroWinding; - // this will assume that the y co-ord is within bounds, and will avoid checking - // this for speed. void addEdgePoint (const int x, const int y, const int winding) throw(); - void remapTableForNumEdges (const int newNumEdgesPerLine) throw(); }; diff --git a/src/gui/graphics/contexts/juce_Graphics.cpp b/src/gui/graphics/contexts/juce_Graphics.cpp index 890a9dede4..a09caaeb07 100644 --- a/src/gui/graphics/contexts/juce_Graphics.cpp +++ b/src/gui/graphics/contexts/juce_Graphics.cpp @@ -450,7 +450,7 @@ void Graphics::fillPath (const Path& path, if ((! context->isClipEmpty()) && ! path.isEmpty()) { if (state->brush == 0) - context->fillPath (path, transform, EdgeTable::Oversampling_4times); + context->fillPath (path, transform); else state->brush->paintPath (*context, path, transform); } diff --git a/src/gui/graphics/contexts/juce_Graphics.h b/src/gui/graphics/contexts/juce_Graphics.h index 4fccbeba12..5cd75ee459 100644 --- a/src/gui/graphics/contexts/juce_Graphics.h +++ b/src/gui/graphics/contexts/juce_Graphics.h @@ -697,6 +697,33 @@ public: /** @internal */ LowLevelGraphicsContext* getInternalContext() const throw() { return context; } + //============================================================================== + /*class FillType + { + public: + FillType (const Colour& colour) throw(); + FillType (const ColourGradient& gradient) throw(); + FillType (Image* image, int x, int y) throw(); + FillType (const FillType& other) throw(); + const FillType& operator= (const FillType& other) throw(); + ~FillType() throw(); + + bool isColour() const throw() { return gradient == 0 && image == 0; } + bool isGradient() const throw() { return gradient != 0; } + bool isTiledImage() const throw() { return image != 0; } + + void setColour (const Colour& newColour) throw(); + void setGradient (const ColourGradient& newGradient) throw(); + void setTiledImage (Image* image, const int imageX, const int imageY) throw(); + + Colour colour; + ColourGradient* gradient; + Image* image; + int imageX, imageY; + + juce_UseDebuggingNewOperator + };*/ + private: //============================================================================== LowLevelGraphicsContext* const context; diff --git a/src/gui/graphics/contexts/juce_LowLevelGraphicsContext.h b/src/gui/graphics/contexts/juce_LowLevelGraphicsContext.h index 2ceb67db18..6e83f6d7e2 100644 --- a/src/gui/graphics/contexts/juce_LowLevelGraphicsContext.h +++ b/src/gui/graphics/contexts/juce_LowLevelGraphicsContext.h @@ -73,6 +73,9 @@ public: /** Cliping co-ords are relative to the origin. */ virtual bool reduceClipRegion (const RectangleList& clipRegion) = 0; + //virtual bool clipToPath (const Path& path) = 0; + //virtual bool clipToImageAlpha (Image& image, int imageX, int imageY) = 0; + /** Cliping co-ords are relative to the origin. */ virtual void excludeClipRegion (int x, int y, int w, int h) = 0; @@ -91,10 +94,10 @@ public: //============================================================================== virtual void fillRect (int x, int y, int w, int h, const bool replaceExistingContents) = 0; - virtual void fillPath (const Path& path, const AffineTransform& transform, EdgeTable::OversamplingLevel quality) = 0; + virtual void fillPath (const Path& path, const AffineTransform& transform) = 0; virtual void fillPathWithImage (const Path& path, const AffineTransform& transform, - const Image& image, int imageX, int imageY, EdgeTable::OversamplingLevel quality) = 0; + const Image& image, int imageX, int imageY) = 0; virtual void fillAlphaChannel (const Image& alphaImage, int alphaImageX, int alphaImageY) = 0; virtual void fillAlphaChannelWithImage (const Image& alphaImage, int alphaImageX, int alphaImageY, diff --git a/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp b/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp index 91af3a48e4..c8dc9dfaa8 100644 --- a/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp +++ b/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp @@ -374,14 +374,13 @@ void LowLevelGraphicsPostScriptRenderer::fillRect (int x, int y, int w, int h, c { Path p; p.addRectangle ((float) x, (float) y, (float) w, (float) h); - fillPath (p, AffineTransform::identity, EdgeTable::Oversampling_256times); + fillPath (p, AffineTransform::identity); } } //============================================================================== -void LowLevelGraphicsPostScriptRenderer::fillPath (const Path& path, const AffineTransform& t, - EdgeTable::OversamplingLevel /*quality*/) +void LowLevelGraphicsPostScriptRenderer::fillPath (const Path& path, const AffineTransform& t) { if (gradient == 0) { @@ -424,8 +423,7 @@ void LowLevelGraphicsPostScriptRenderer::fillPath (const Path& path, const Affin void LowLevelGraphicsPostScriptRenderer::fillPathWithImage (const Path& path, const AffineTransform& transform, const Image& sourceImage, - int imageX, int imageY, - EdgeTable::OversamplingLevel /*quality*/) + int imageX, int imageY) { writeClip(); @@ -593,7 +591,7 @@ void LowLevelGraphicsPostScriptRenderer::drawLine (double x1, double y1, double { Path p; p.addLineSegment ((float) x1, (float) y1, (float) x2, (float) y2, 1.0f); - fillPath (p, AffineTransform::identity, EdgeTable::Oversampling_256times); + fillPath (p, AffineTransform::identity); } void LowLevelGraphicsPostScriptRenderer::drawVerticalLine (const int x, double top, double bottom) diff --git a/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h b/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h index c62c94942f..007a1746b7 100644 --- a/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h +++ b/src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h @@ -69,10 +69,10 @@ public: //============================================================================== void fillRect (int x, int y, int w, int h, const bool replaceExistingContents); - void fillPath (const Path& path, const AffineTransform& transform, EdgeTable::OversamplingLevel quality); + void fillPath (const Path& path, const AffineTransform& transform); void fillPathWithImage (const Path& path, const AffineTransform& transform, - const Image& image, int imageX, int imageY, EdgeTable::OversamplingLevel quality); + const Image& image, int imageX, int imageY); void fillAlphaChannel (const Image& alphaImage, int imageX, int imageY); void fillAlphaChannelWithImage (const Image& alphaImage, int alphaImageX, int alphaImageY, diff --git a/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp b/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp index 25ca9063e2..1928d77f73 100644 --- a/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp +++ b/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp @@ -1058,6 +1058,80 @@ static void renderAlphaMap (DestPixelType* destPixels, } } +//============================================================================== +/*class ClippingPath +{ +public: + ClippingPath (const Rectangle& r) throw() + : rectangles (r) + { + } + + ClippingPath (const ClippingPath& other) throw() + : rectangles (other.rectangles), mask (other.mask) + { + } + + ~ClippingPath() throw() + { + delete mask; + } + + bool reduce (int x, int y, int w, int h) throw() + { + return clip.clipTo (Rectangle (x, y, w, h)); + } + + bool exclude (int x, int y, int w, int h) throw() + { + return clip.subtract (Rectangle (x, y, w, h)); + } + + bool reduce (const Path& p, const AffineTransform& transform) + { + float px, py, pw, ph; + p.getBoundsTransformed (transform, px, py, pw, ph); + + Rectangle pathBounds ((int) px - 1, (int) py - 1, (int) pw + 3, (int) ph + 3); + + if (clip.clipTo (pathBounds)) + { + } + } + + bool reduce (Image& image, int x, int y) + { + } + + bool reduce (Image& image, const AffineTransform& transform) + { + } + + class MaskImage : public ReferenceCountedObject + { + public: + MaskImage (int x_, int y_, int w, int h) throw() + : x (x_), y (y_) + { + image = new Image (Image::SingleChannel, w, h, true); + } + + ~MaskImage() throw() + { + delete image; + } + + Image* image; + int x, y; + }; + + RectangleList clip; + ReferenceCountedObjectPtr mask; + +private: +}; +*/ + //============================================================================== LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (Image& image_) : image (image_), @@ -1207,7 +1281,7 @@ void LowLevelGraphicsSoftwareRenderer::fillRect (int x, int y, int w, int h, con Path p; p.addRectangle ((float) x, (float) y, (float) w, (float) h); - fillPath (p, AffineTransform::identity, EdgeTable::Oversampling_none); + fillPath (p, AffineTransform::identity); } else { @@ -1269,26 +1343,26 @@ bool LowLevelGraphicsSoftwareRenderer::getPathBounds (int clipX, int clipY, int return Rectangle::intersectRectangles (x, y, w, h, clipX, clipY, clipW, clipH); } -void LowLevelGraphicsSoftwareRenderer::fillPath (const Path& path, const AffineTransform& transform, EdgeTable::OversamplingLevel quality) +void LowLevelGraphicsSoftwareRenderer::fillPath (const Path& path, const AffineTransform& transform) { for (RectangleList::Iterator i (*clip); i.next();) { const Rectangle& r = *i.getRectangle(); clippedFillPath (r.getX(), r.getY(), r.getWidth(), r.getHeight(), - path, transform, quality); + path, transform); } } void LowLevelGraphicsSoftwareRenderer::clippedFillPath (int clipX, int clipY, int clipW, int clipH, const Path& path, - const AffineTransform& t, EdgeTable::OversamplingLevel quality) + const AffineTransform& t) { const AffineTransform transform (t.translated ((float) xOffset, (float) yOffset)); int cx, cy, cw, ch; if (getPathBounds (clipX, clipY, clipW, clipH, path, transform, cx, cy, cw, ch)) { - EdgeTable edgeTable (0, ch, quality); + EdgeTable edgeTable (0, ch); edgeTable.addPath (path, transform.translated ((float) -cx, (float) -cy)); int stride, pixelStride; @@ -1396,7 +1470,7 @@ void LowLevelGraphicsSoftwareRenderer::clippedFillPath (int clipX, int clipY, in } void LowLevelGraphicsSoftwareRenderer::fillPathWithImage (const Path& path, const AffineTransform& transform, - const Image& sourceImage, int imageX, int imageY, EdgeTable::OversamplingLevel quality) + const Image& sourceImage, int imageX, int imageY) { imageX += xOffset; imageY += yOffset; @@ -1407,16 +1481,16 @@ void LowLevelGraphicsSoftwareRenderer::fillPathWithImage (const Path& path, cons clippedFillPathWithImage (r.getX(), r.getY(), r.getWidth(), r.getHeight(), path, transform, sourceImage, imageX, imageY, - colour.getFloatAlpha(), quality); + colour.getFloatAlpha()); } } void LowLevelGraphicsSoftwareRenderer::clippedFillPathWithImage (int x, int y, int w, int h, const Path& path, const AffineTransform& transform, - const Image& sourceImage, int imageX, int imageY, float opacity, EdgeTable::OversamplingLevel quality) + const Image& sourceImage, int imageX, int imageY, float opacity) { if (Rectangle::intersectRectangles (x, y, w, h, imageX, imageY, sourceImage.getWidth(), sourceImage.getHeight())) { - EdgeTable edgeTable (0, h, quality); + EdgeTable edgeTable (0, h); edgeTable.addPath (path, transform.translated ((float) (xOffset - x), (float) (yOffset - y))); int stride, pixelStride; diff --git a/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h b/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h index 25a2e42da2..f2c9a34b02 100644 --- a/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h +++ b/src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h @@ -68,10 +68,10 @@ public: //============================================================================== void fillRect (int x, int y, int w, int h, const bool replaceExistingContents); - void fillPath (const Path& path, const AffineTransform& transform, EdgeTable::OversamplingLevel quality); + void fillPath (const Path& path, const AffineTransform& transform); void fillPathWithImage (const Path& path, const AffineTransform& transform, - const Image& image, int imageX, int imageY, EdgeTable::OversamplingLevel quality); + const Image& image, int imageX, int imageY); void fillAlphaChannel (const Image& alphaImage, int imageX, int imageY); void fillAlphaChannelWithImage (const Image& alphaImage, int alphaImageX, int alphaImageY, @@ -141,9 +141,9 @@ protected: void clippedFillRectWithColour (const Rectangle& clipRect, int x, int y, int w, int h, const Colour& colour, const bool replaceExistingContents); - void clippedFillPath (int clipX, int clipY, int clipW, int clipH, const Path& path, const AffineTransform& transform, EdgeTable::OversamplingLevel quality); + void clippedFillPath (int clipX, int clipY, int clipW, int clipH, const Path& path, const AffineTransform& transform); void clippedFillPathWithImage (int clipX, int clipY, int clipW, int clipH, const Path& path, const AffineTransform& transform, - const Image& image, int imageX, int imageY, float alpha, EdgeTable::OversamplingLevel quality); + const Image& image, int imageX, int imageY, float alpha); void clippedFillAlphaChannel (int clipX, int clipY, int clipW, int clipH, const Image& alphaImage, int alphaImageX, int alphaImageY); void clippedFillAlphaChannelWithImage (int clipX, int clipY, int clipW, int clipH, const Image& alphaImage, int alphaImageX, int alphaImageY, diff --git a/src/gui/graphics/fonts/juce_Font.cpp b/src/gui/graphics/fonts/juce_Font.cpp index bbdb6e339f..853cd5c617 100644 --- a/src/gui/graphics/fonts/juce_Font.cpp +++ b/src/gui/graphics/fonts/juce_Font.cpp @@ -435,27 +435,27 @@ class FontGlyphAlphaMap public: //============================================================================== FontGlyphAlphaMap() throw() - : glyph (0), lastAccessCount (0), - bitmap1 (0), bitmap2 (0) + : glyph (0), lastAccessCount (0) { + bitmap[0] = bitmap[1] = 0; } ~FontGlyphAlphaMap() throw() { - delete bitmap1; - delete bitmap2; + delete bitmap[0]; + delete bitmap[1]; } void draw (LowLevelGraphicsContext& g, float x, const float y) const throw() { - if (bitmap1 != 0) + if (bitmap[0] != 0) { - x += xOrigin; const float xFloor = floorf (x); - const int intX = (int) xFloor; + const int bitmapToUse = ((x - xFloor) >= 0.5f && bitmap[1] != 0) ? 1 : 0; - g.fillAlphaChannel (((x - xFloor) >= 0.5f && bitmap2 != 0) ? *bitmap2 : *bitmap1, - intX, (int) floorf (y + yOrigin)); + g.fillAlphaChannel (*bitmap [bitmapToUse], + xOrigin [bitmapToUse] + (int) xFloor, + yOrigin [bitmapToUse] + (int) floorf (y)); } } @@ -464,8 +464,8 @@ public: font = font_; glyph = glyph_; - deleteAndZero (bitmap1); - deleteAndZero (bitmap2); + deleteAndZero (bitmap[0]); + deleteAndZero (bitmap[1]); Path glyphPath; font.getTypeface()->getOutlineForGlyph (glyph_, glyphPath); @@ -474,15 +474,19 @@ public: { const float fontHeight = font.getHeight(); const float fontHScale = fontHeight * font.getHorizontalScale(); + AffineTransform transform (AffineTransform::scale (fontHScale, fontHeight)); + Rectangle clip (-2048, -2048, 4096, 4096), pos; - bitmap1 = createAlphaMapFromPath (glyphPath, xOrigin, yOrigin, fontHScale, fontHeight, 0.0f); + bitmap[0] = glyphPath.createMaskBitmap (transform, clip, pos); + xOrigin[0] = pos.getX(); + yOrigin[0] = pos.getY(); - if (fontHScale < 24.0f) - bitmap2 = createAlphaMapFromPath (glyphPath, xOrigin, yOrigin, fontHScale, fontHeight, 0.5f); - } - else - { - xOrigin = yOrigin = 0; + if (fontHScale < 30.0f) + { + bitmap[1] = glyphPath.createMaskBitmap (transform.translated (0.5f, 0.0f), clip, pos); + xOrigin[1] = pos.getX(); + yOrigin[1] = pos.getY(); + } } } @@ -493,78 +497,8 @@ public: juce_UseDebuggingNewOperator private: - Image* bitmap1; - Image* bitmap2; - float xOrigin, yOrigin; - - class AlphaBitmapRenderer - { - public: - AlphaBitmapRenderer (uint8* const data_, const int stride_) throw() - : data (data_), stride (stride_) - { - } - - forcedinline void setEdgeTableYPos (const int y) throw() - { - lineStart = data + (stride * y); - } - - forcedinline void handleEdgeTablePixel (const int x, const int alphaLevel) const throw() - { - lineStart [x] = (uint8) alphaLevel; - } - - forcedinline void handleEdgeTableLine (const int x, int width, const int alphaLevel) const throw() - { - uint8* d = lineStart + x; - - while (--width >= 0) - *d++ = (uint8) alphaLevel; - } - - private: - uint8* const data; - const int stride; - uint8* lineStart; - - AlphaBitmapRenderer (const AlphaBitmapRenderer&); - const AlphaBitmapRenderer& operator= (const AlphaBitmapRenderer&); - }; - - Image* createAlphaMapFromPath (const Path& path, - float& topLeftX, float& topLeftY, - float xScale, float yScale, - const float subPixelOffsetX) throw() - { - Image* im = 0; - - float px, py, pw, ph; - path.getBounds (px, py, pw, ph); - - topLeftX = floorf (px * xScale); - topLeftY = floorf (py * yScale); - - const int bitmapWidth = roundFloatToInt (pw * xScale) + 2; - const int bitmapHeight = roundFloatToInt (ph * yScale) + 2; - - im = new Image (Image::SingleChannel, bitmapWidth, bitmapHeight, true); - - EdgeTable edgeTable (0, bitmapHeight, EdgeTable::Oversampling_16times); - - edgeTable.addPath (path, AffineTransform::scale (xScale, yScale) - .translated (subPixelOffsetX - topLeftX, -topLeftY)); - - int stride, pixelStride; - uint8* const pixels = (uint8*) im->lockPixelDataReadWrite (0, 0, bitmapWidth, bitmapHeight, stride, pixelStride); - - jassert (pixelStride == 1); - AlphaBitmapRenderer renderer (pixels, stride); - edgeTable.iterate (renderer, 0, 0, bitmapWidth, bitmapHeight, 0); - - im->releasePixelDataReadWrite (pixels); - return im; - } + Image* bitmap[2]; + int xOrigin[2], yOrigin[2]; FontGlyphAlphaMap (const FontGlyphAlphaMap&); const FontGlyphAlphaMap& operator= (const FontGlyphAlphaMap&); @@ -677,8 +611,7 @@ void Font::renderGlyphIndirectly (LowLevelGraphicsContext& g, int glyphNumber, c getTypeface()->getOutlineForGlyph (glyphNumber, p); g.fillPath (p, AffineTransform::scale (font->height * font->horizontalScale, font->height) - .followedBy (transform), - EdgeTable::Oversampling_16times); + .followedBy (transform)); } diff --git a/src/gui/graphics/geometry/juce_Path.cpp b/src/gui/graphics/geometry/juce_Path.cpp index da3f418c4d..1cc0ddc95a 100644 --- a/src/gui/graphics/geometry/juce_Path.cpp +++ b/src/gui/graphics/geometry/juce_Path.cpp @@ -31,6 +31,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_PathIterator.h" #include "juce_Line.h" #include "../../../io/streams/juce_MemoryInputStream.h" +#include "../imaging/juce_Image.h" // tests that some co-ords aren't NaNs #define CHECK_COORDS_ARE_VALID(x, y) \ @@ -1548,5 +1549,73 @@ bool Path::Iterator::next() return false; } +//============================================================================== +class MaskBitmapRenderer +{ +public: + MaskBitmapRenderer (uint8* const data_, const int stride_) throw() + : data (data_), stride (stride_) + { + } + + forcedinline void setEdgeTableYPos (const int y) throw() + { + lineStart = data + (stride * y); + } + + forcedinline void handleEdgeTablePixel (const int x, const int alphaLevel) const throw() + { + lineStart [x] = (uint8) alphaLevel; + } + + forcedinline void handleEdgeTableLine (const int x, int width, const int alphaLevel) const throw() + { + uint8* d = lineStart + x; + + while (--width >= 0) + *d++ = (uint8) alphaLevel; + } + +private: + uint8* const data; + const int stride; + uint8* lineStart; + + MaskBitmapRenderer (const MaskBitmapRenderer&); + const MaskBitmapRenderer& operator= (const MaskBitmapRenderer&); +}; + +Image* Path::createMaskBitmap (const AffineTransform& transform, + const Rectangle& clipRegion, + Rectangle& imagePosition) const throw() +{ + if (isEmpty()) + return 0; + + float px, py, pw, ph; + getBoundsTransformed (transform, px, py, pw, ph); + + imagePosition = clipRegion.getIntersection (Rectangle ((int) floorf (px), (int) floorf (py), + roundFloatToInt (pw) + 2, roundFloatToInt (ph) + 2)); + + if (imagePosition.isEmpty()) + return 0; + + Image* im = new Image (Image::SingleChannel, imagePosition.getWidth(), imagePosition.getHeight(), true); + + EdgeTable edgeTable (0, imagePosition.getHeight()); + edgeTable.addPath (*this, transform.translated (-imagePosition.getX(), -imagePosition.getY())); + + int stride, pixelStride; + uint8* const pixels = (uint8*) im->lockPixelDataReadWrite (0, 0, imagePosition.getWidth(), imagePosition.getHeight(), stride, pixelStride); + + jassert (pixelStride == 1); + MaskBitmapRenderer renderer (pixels, stride); + edgeTable.iterate (renderer, 0, 0, imagePosition.getWidth(), imagePosition.getHeight(), 0); + + im->releasePixelDataReadWrite (pixels); + return im; +} + END_JUCE_NAMESPACE diff --git a/src/gui/graphics/geometry/juce_Path.h b/src/gui/graphics/geometry/juce_Path.h index 8fa2ff0bdb..fe4d7d9a27 100644 --- a/src/gui/graphics/geometry/juce_Path.h +++ b/src/gui/graphics/geometry/juce_Path.h @@ -28,11 +28,13 @@ #include "juce_AffineTransform.h" #include "juce_Point.h" +#include "juce_Rectangle.h" #include "../contexts/juce_Justification.h" +#include "../contexts/juce_EdgeTable.h" #include "../../../containers/juce_Array.h" #include "../../../io/streams/juce_InputStream.h" #include "../../../io/streams/juce_OutputStream.h" - +class Image; //============================================================================== /** @@ -614,6 +616,22 @@ public: */ void restoreFromString (const String& stringVersion); + //============================================================================== + /** Creates a single-channel bitmap containing a mask of this path. + + The smallest bitmap that contains the path will be created, and on return, the + imagePosition rectangle indicates the position of the newly created image, relative + to the path's origin. + + Only the intersection of the path's bounds with the specified clipRegion rectangle + will be rendered. + + If the path is empty or doesn't intersect the clip region, this may return 0. + */ + Image* createMaskBitmap (const AffineTransform& transform, + const Rectangle& clipRegion, + Rectangle& imagePosition) const throw(); + //============================================================================== juce_UseDebuggingNewOperator diff --git a/src/native/mac/juce_mac_CoreGraphicsContext.mm b/src/native/mac/juce_mac_CoreGraphicsContext.mm index d5cd5924cb..411d5650db 100644 --- a/src/native/mac/juce_mac_CoreGraphicsContext.mm +++ b/src/native/mac/juce_mac_CoreGraphicsContext.mm @@ -187,7 +187,7 @@ public: } } - void fillPath (const Path& path, const AffineTransform& transform, EdgeTable::OversamplingLevel quality) + void fillPath (const Path& path, const AffineTransform& transform) { CGContextSaveGState (context); @@ -211,7 +211,7 @@ public: } void fillPathWithImage (const Path& path, const AffineTransform& transform, - const Image& image, int imageX, int imageY, EdgeTable::OversamplingLevel quality) + const Image& image, int imageX, int imageY) { CGContextSaveGState (context); createPath (path, transform); diff --git a/src/native/mac/juce_mac_OpenGLComponent.mm b/src/native/mac/juce_mac_OpenGLComponent.mm index 8e22c62105..641b660037 100644 --- a/src/native/mac/juce_mac_OpenGLComponent.mm +++ b/src/native/mac/juce_mac_OpenGLComponent.mm @@ -177,7 +177,7 @@ public: ~WindowedGLContext() { makeInactive(); - [renderContext setView: nil]; + [renderContext clearDrawable]; delete viewHolder; }