 25bd5d8adb
			
		
	
	25bd5d8adb
	
	
	
		
			
			subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
		
			
				
	
	
		
			227 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			227 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|   ==============================================================================
 | |
| 
 | |
|    This file is part of the JUCE library.
 | |
|    Copyright (c) 2020 - Raw Material Software Limited
 | |
| 
 | |
|    JUCE is an open source library subject to commercial or open-source
 | |
|    licensing.
 | |
| 
 | |
|    By using JUCE, you agree to the terms of both the JUCE 6 End-User License
 | |
|    Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
 | |
| 
 | |
|    End User License Agreement: www.juce.com/juce-6-licence
 | |
|    Privacy Policy: www.juce.com/juce-privacy-policy
 | |
| 
 | |
|    Or: You may also use this code under the terms of the GPL v3 (see
 | |
|    www.gnu.org/licenses).
 | |
| 
 | |
|    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 | |
|    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 | |
|    DISCLAIMED.
 | |
| 
 | |
|   ==============================================================================
 | |
| */
 | |
| 
 | |
| namespace juce
 | |
| {
 | |
| 
 | |
| //==============================================================================
 | |
| /**
 | |
|     A table of horizontal scan-line segments - used for rasterising Paths.
 | |
| 
 | |
|     @see Path, Graphics
 | |
| 
 | |
|     @tags{Graphics}
 | |
| */
 | |
| class JUCE_API  EdgeTable
 | |
| {
 | |
| public:
 | |
|     //==============================================================================
 | |
|     /** Creates an edge table containing a path.
 | |
| 
 | |
|         A table is created with a fixed vertical range, and only sections of the path
 | |
|         which lie within this range will be added to the table.
 | |
| 
 | |
|         @param clipLimits               only the region of the path that lies within this area will be added
 | |
|         @param pathToAdd                the path to add to the table
 | |
|         @param transform                a transform to apply to the path being added
 | |
|     */
 | |
|     EdgeTable (Rectangle<int> clipLimits,
 | |
|                const Path& pathToAdd,
 | |
|                const AffineTransform& transform);
 | |
| 
 | |
|     /** Creates an edge table containing a rectangle. */
 | |
|     explicit EdgeTable (Rectangle<int> rectangleToAdd);
 | |
| 
 | |
|     /** Creates an edge table containing a rectangle. */
 | |
|     explicit EdgeTable (Rectangle<float> rectangleToAdd);
 | |
| 
 | |
|     /** Creates an edge table containing a rectangle list. */
 | |
|     explicit EdgeTable (const RectangleList<int>& rectanglesToAdd);
 | |
| 
 | |
|     /** Creates an edge table containing a rectangle list. */
 | |
|     explicit EdgeTable (const RectangleList<float>& rectanglesToAdd);
 | |
| 
 | |
|     /** Creates a copy of another edge table. */
 | |
|     EdgeTable (const EdgeTable&);
 | |
| 
 | |
|     /** Copies from another edge table. */
 | |
|     EdgeTable& operator= (const EdgeTable&);
 | |
| 
 | |
|     /** Destructor. */
 | |
|     ~EdgeTable();
 | |
| 
 | |
|     //==============================================================================
 | |
|     void clipToRectangle (Rectangle<int> r);
 | |
|     void excludeRectangle (Rectangle<int> r);
 | |
|     void clipToEdgeTable (const EdgeTable&);
 | |
|     void clipLineToMask (int x, int y, const uint8* mask, int maskStride, int numPixels);
 | |
|     bool isEmpty() noexcept;
 | |
|     const Rectangle<int>& getMaximumBounds() const noexcept      { return bounds; }
 | |
|     void translate (float dx, int dy) noexcept;
 | |
| 
 | |
|     /** Scales all the alpha-levels in the table by the given multiplier. */
 | |
|     void multiplyLevels (float factor);
 | |
| 
 | |
|     /** 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();
 | |
| 
 | |
| 
 | |
|     //==============================================================================
 | |
|     /** 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 handleEdgeTablePixelFull (int x) const;
 | |
|                                         inline void handleEdgeTableLine (int x, int width, int alphaLevel) const;
 | |
|                                         inline void handleEdgeTableLineFull (int x, int width) const;
 | |
|                                         @endcode
 | |
|                                         (these don't necessarily have to be 'const', but it might help it go faster)
 | |
|     */
 | |
|     template <class EdgeTableIterationCallback>
 | |
|     void iterate (EdgeTableIterationCallback& iterationCallback) const noexcept
 | |
|     {
 | |
|         const int* lineStart = table;
 | |
| 
 | |
|         for (int y = 0; y < bounds.getHeight(); ++y)
 | |
|         {
 | |
|             const int* line = lineStart;
 | |
|             lineStart += lineStrideElements;
 | |
|             int numPoints = line[0];
 | |
| 
 | |
|             if (--numPoints > 0)
 | |
|             {
 | |
|                 int x = *++line;
 | |
|                 jassert ((x / scale) >= bounds.getX() && (x / scale) < bounds.getRight());
 | |
|                 int levelAccumulator = 0;
 | |
| 
 | |
|                 iterationCallback.setEdgeTableYPos (bounds.getY() + y);
 | |
| 
 | |
|                 while (--numPoints >= 0)
 | |
|                 {
 | |
|                     const int level = *++line;
 | |
|                     jassert (isPositiveAndBelow (level, scale));
 | |
|                     const int endX = *++line;
 | |
|                     jassert (endX >= x);
 | |
|                     const int endOfRun = (endX / scale);
 | |
| 
 | |
|                     if (endOfRun == (x / scale))
 | |
|                     {
 | |
|                         // small segment within the same pixel, so just save it for the next
 | |
|                         // time round..
 | |
|                         levelAccumulator += (endX - x) * level;
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         // plot the fist pixel of this segment, including any accumulated
 | |
|                         // levels from smaller segments that haven't been drawn yet
 | |
|                         levelAccumulator += (0x100 - (x & 0xff)) * level;
 | |
|                         levelAccumulator /= scale;
 | |
|                         x /= scale;
 | |
| 
 | |
|                         if (levelAccumulator > 0)
 | |
|                         {
 | |
|                             if (levelAccumulator >= 255)
 | |
|                                 iterationCallback.handleEdgeTablePixelFull (x);
 | |
|                             else
 | |
|                                 iterationCallback.handleEdgeTablePixel (x, levelAccumulator);
 | |
|                         }
 | |
| 
 | |
|                         // if there's a run of similar pixels, do it all in one go..
 | |
|                         if (level > 0)
 | |
|                         {
 | |
|                             jassert (endOfRun <= bounds.getRight());
 | |
|                             const int numPix = endOfRun - ++x;
 | |
| 
 | |
|                             if (numPix > 0)
 | |
|                                 iterationCallback.handleEdgeTableLine (x, numPix, level);
 | |
|                         }
 | |
| 
 | |
|                         // save the bit at the end to be drawn next time round the loop.
 | |
|                         levelAccumulator = (endX & 0xff) * level;
 | |
|                     }
 | |
| 
 | |
|                     x = endX;
 | |
|                 }
 | |
| 
 | |
|                 levelAccumulator /= scale;
 | |
| 
 | |
|                 if (levelAccumulator > 0)
 | |
|                 {
 | |
|                     x /= scale;
 | |
|                     jassert (x >= bounds.getX() && x < bounds.getRight());
 | |
| 
 | |
|                     if (levelAccumulator >= 255)
 | |
|                         iterationCallback.handleEdgeTablePixelFull (x);
 | |
|                     else
 | |
|                         iterationCallback.handleEdgeTablePixel (x, levelAccumulator);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     //==============================================================================
 | |
|     static constexpr auto defaultEdgesPerLine = 32;
 | |
|     static constexpr auto scale = 256;
 | |
| 
 | |
|     //==============================================================================
 | |
|     // table line format: number of points; point0 x, point0 levelDelta, point1 x, point1 levelDelta, etc
 | |
|     struct LineItem
 | |
|     {
 | |
|         int x, level;
 | |
| 
 | |
|         bool operator< (const LineItem& other) const noexcept   { return x < other.x; }
 | |
|     };
 | |
| 
 | |
|     HeapBlock<int> table;
 | |
|     Rectangle<int> bounds;
 | |
|     int maxEdgesPerLine, lineStrideElements;
 | |
|     bool needToCheckEmptiness = true;
 | |
| 
 | |
|     void allocate();
 | |
|     void clearLineSizes() noexcept;
 | |
|     void addEdgePoint (int x, int y, int winding);
 | |
|     void addEdgePointPair (int x1, int x2, int y, int winding);
 | |
|     void remapTableForNumEdges (int newNumEdgesPerLine);
 | |
|     void remapWithExtraSpace (int numPointsNeeded);
 | |
|     void intersectWithEdgeTableLine (int y, const int* otherLine);
 | |
|     void clipEdgeTableLineToRange (int* line, int x1, int x2) noexcept;
 | |
|     void sanitiseLevels (bool useNonZeroWinding) noexcept;
 | |
|     static void copyEdgeTableData (int* dest, int destLineStride, const int* src, int srcLineStride, int numLines) noexcept;
 | |
| 
 | |
|     JUCE_LEAK_DETECTOR (EdgeTable)
 | |
| };
 | |
| 
 | |
| } // namespace juce
 |