mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-30 02:50:05 +00:00
Rewrote EdgeTable so that it now always renders in perfect quality - this makes the old oversampling quality options defunct and I've removed them.
This commit is contained in:
parent
405d934e68
commit
4d000ff593
20 changed files with 1050 additions and 984 deletions
|
|
@ -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<MaskImage> 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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue