git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce
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"
This commit is contained in:
705
deps/juce/modules/juce_graphics/contexts/juce_GraphicsContext.cpp
vendored
Normal file
705
deps/juce/modules/juce_graphics/contexts/juce_GraphicsContext.cpp
vendored
Normal file
@ -0,0 +1,705 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename Type>
|
||||
Rectangle<Type> coordsToRectangle (Type x, Type y, Type w, Type h) noexcept
|
||||
{
|
||||
#if JUCE_DEBUG
|
||||
const int maxVal = 0x3fffffff;
|
||||
|
||||
jassert ((int) x >= -maxVal && (int) x <= maxVal
|
||||
&& (int) y >= -maxVal && (int) y <= maxVal
|
||||
&& (int) w >= 0 && (int) w <= maxVal
|
||||
&& (int) h >= 0 && (int) h <= maxVal);
|
||||
#endif
|
||||
|
||||
return { x, y, w, h };
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
LowLevelGraphicsContext::LowLevelGraphicsContext() {}
|
||||
LowLevelGraphicsContext::~LowLevelGraphicsContext() {}
|
||||
|
||||
//==============================================================================
|
||||
Graphics::Graphics (const Image& imageToDrawOnto)
|
||||
: contextHolder (imageToDrawOnto.createLowLevelContext()),
|
||||
context (*contextHolder)
|
||||
{
|
||||
jassert (imageToDrawOnto.isValid()); // Can't draw into a null image!
|
||||
}
|
||||
|
||||
Graphics::Graphics (LowLevelGraphicsContext& internalContext) noexcept
|
||||
: context (internalContext)
|
||||
{
|
||||
}
|
||||
|
||||
Graphics::~Graphics()
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Graphics::resetToDefaultState()
|
||||
{
|
||||
saveStateIfPending();
|
||||
context.setFill (FillType());
|
||||
context.setFont (Font());
|
||||
context.setInterpolationQuality (Graphics::mediumResamplingQuality);
|
||||
}
|
||||
|
||||
bool Graphics::isVectorDevice() const
|
||||
{
|
||||
return context.isVectorDevice();
|
||||
}
|
||||
|
||||
bool Graphics::reduceClipRegion (Rectangle<int> area)
|
||||
{
|
||||
saveStateIfPending();
|
||||
return context.clipToRectangle (area);
|
||||
}
|
||||
|
||||
bool Graphics::reduceClipRegion (int x, int y, int w, int h)
|
||||
{
|
||||
return reduceClipRegion (coordsToRectangle (x, y, w, h));
|
||||
}
|
||||
|
||||
bool Graphics::reduceClipRegion (const RectangleList<int>& clipRegion)
|
||||
{
|
||||
saveStateIfPending();
|
||||
return context.clipToRectangleList (clipRegion);
|
||||
}
|
||||
|
||||
bool Graphics::reduceClipRegion (const Path& path, const AffineTransform& transform)
|
||||
{
|
||||
saveStateIfPending();
|
||||
context.clipToPath (path, transform);
|
||||
return ! context.isClipEmpty();
|
||||
}
|
||||
|
||||
bool Graphics::reduceClipRegion (const Image& image, const AffineTransform& transform)
|
||||
{
|
||||
saveStateIfPending();
|
||||
context.clipToImageAlpha (image, transform);
|
||||
return ! context.isClipEmpty();
|
||||
}
|
||||
|
||||
void Graphics::excludeClipRegion (Rectangle<int> rectangleToExclude)
|
||||
{
|
||||
saveStateIfPending();
|
||||
context.excludeClipRectangle (rectangleToExclude);
|
||||
}
|
||||
|
||||
bool Graphics::isClipEmpty() const
|
||||
{
|
||||
return context.isClipEmpty();
|
||||
}
|
||||
|
||||
Rectangle<int> Graphics::getClipBounds() const
|
||||
{
|
||||
return context.getClipBounds();
|
||||
}
|
||||
|
||||
void Graphics::saveState()
|
||||
{
|
||||
saveStateIfPending();
|
||||
saveStatePending = true;
|
||||
}
|
||||
|
||||
void Graphics::restoreState()
|
||||
{
|
||||
if (saveStatePending)
|
||||
saveStatePending = false;
|
||||
else
|
||||
context.restoreState();
|
||||
}
|
||||
|
||||
void Graphics::saveStateIfPending()
|
||||
{
|
||||
if (saveStatePending)
|
||||
{
|
||||
saveStatePending = false;
|
||||
context.saveState();
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::setOrigin (Point<int> newOrigin)
|
||||
{
|
||||
saveStateIfPending();
|
||||
context.setOrigin (newOrigin);
|
||||
}
|
||||
|
||||
void Graphics::setOrigin (int x, int y)
|
||||
{
|
||||
setOrigin ({ x, y });
|
||||
}
|
||||
|
||||
void Graphics::addTransform (const AffineTransform& transform)
|
||||
{
|
||||
saveStateIfPending();
|
||||
context.addTransform (transform);
|
||||
}
|
||||
|
||||
bool Graphics::clipRegionIntersects (Rectangle<int> area) const
|
||||
{
|
||||
return context.clipRegionIntersects (area);
|
||||
}
|
||||
|
||||
void Graphics::beginTransparencyLayer (float layerOpacity)
|
||||
{
|
||||
saveStateIfPending();
|
||||
context.beginTransparencyLayer (layerOpacity);
|
||||
}
|
||||
|
||||
void Graphics::endTransparencyLayer()
|
||||
{
|
||||
context.endTransparencyLayer();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Graphics::setColour (Colour newColour)
|
||||
{
|
||||
saveStateIfPending();
|
||||
context.setFill (newColour);
|
||||
}
|
||||
|
||||
void Graphics::setOpacity (float newOpacity)
|
||||
{
|
||||
saveStateIfPending();
|
||||
context.setOpacity (newOpacity);
|
||||
}
|
||||
|
||||
void Graphics::setGradientFill (const ColourGradient& gradient)
|
||||
{
|
||||
setFillType (gradient);
|
||||
}
|
||||
|
||||
void Graphics::setGradientFill (ColourGradient&& gradient)
|
||||
{
|
||||
setFillType (std::move (gradient));
|
||||
}
|
||||
|
||||
void Graphics::setTiledImageFill (const Image& imageToUse, const int anchorX, const int anchorY, const float opacity)
|
||||
{
|
||||
saveStateIfPending();
|
||||
context.setFill (FillType (imageToUse, AffineTransform::translation ((float) anchorX, (float) anchorY)));
|
||||
context.setOpacity (opacity);
|
||||
}
|
||||
|
||||
void Graphics::setFillType (const FillType& newFill)
|
||||
{
|
||||
saveStateIfPending();
|
||||
context.setFill (newFill);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Graphics::setFont (const Font& newFont)
|
||||
{
|
||||
saveStateIfPending();
|
||||
context.setFont (newFont);
|
||||
}
|
||||
|
||||
void Graphics::setFont (const float newFontHeight)
|
||||
{
|
||||
setFont (context.getFont().withHeight (newFontHeight));
|
||||
}
|
||||
|
||||
Font Graphics::getCurrentFont() const
|
||||
{
|
||||
return context.getFont();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Graphics::drawSingleLineText (const String& text, const int startX, const int baselineY,
|
||||
Justification justification) const
|
||||
{
|
||||
if (text.isNotEmpty())
|
||||
{
|
||||
// Don't pass any vertical placement flags to this method - they'll be ignored.
|
||||
jassert (justification.getOnlyVerticalFlags() == 0);
|
||||
|
||||
auto flags = justification.getOnlyHorizontalFlags();
|
||||
|
||||
if (flags == Justification::right && startX < context.getClipBounds().getX())
|
||||
return;
|
||||
|
||||
if (flags == Justification::left && startX > context.getClipBounds().getRight())
|
||||
return;
|
||||
|
||||
GlyphArrangement arr;
|
||||
arr.addLineOfText (context.getFont(), text, (float) startX, (float) baselineY);
|
||||
|
||||
if (flags != Justification::left)
|
||||
{
|
||||
auto w = arr.getBoundingBox (0, -1, true).getWidth();
|
||||
|
||||
if ((flags & (Justification::horizontallyCentred | Justification::horizontallyJustified)) != 0)
|
||||
w /= 2.0f;
|
||||
|
||||
arr.draw (*this, AffineTransform::translation (-w, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
arr.draw (*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::drawMultiLineText (const String& text, const int startX,
|
||||
const int baselineY, const int maximumLineWidth,
|
||||
Justification justification, const float leading) const
|
||||
{
|
||||
if (text.isNotEmpty()
|
||||
&& startX < context.getClipBounds().getRight())
|
||||
{
|
||||
GlyphArrangement arr;
|
||||
arr.addJustifiedText (context.getFont(), text,
|
||||
(float) startX, (float) baselineY, (float) maximumLineWidth,
|
||||
justification, leading);
|
||||
arr.draw (*this);
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::drawText (const String& text, Rectangle<float> area,
|
||||
Justification justificationType, bool useEllipsesIfTooBig) const
|
||||
{
|
||||
if (text.isNotEmpty() && context.clipRegionIntersects (area.getSmallestIntegerContainer()))
|
||||
{
|
||||
GlyphArrangement arr;
|
||||
arr.addCurtailedLineOfText (context.getFont(), text, 0.0f, 0.0f,
|
||||
area.getWidth(), useEllipsesIfTooBig);
|
||||
|
||||
arr.justifyGlyphs (0, arr.getNumGlyphs(),
|
||||
area.getX(), area.getY(), area.getWidth(), area.getHeight(),
|
||||
justificationType);
|
||||
arr.draw (*this);
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::drawText (const String& text, Rectangle<int> area,
|
||||
Justification justificationType, bool useEllipsesIfTooBig) const
|
||||
{
|
||||
drawText (text, area.toFloat(), justificationType, useEllipsesIfTooBig);
|
||||
}
|
||||
|
||||
void Graphics::drawText (const String& text, int x, int y, int width, int height,
|
||||
Justification justificationType, const bool useEllipsesIfTooBig) const
|
||||
{
|
||||
drawText (text, coordsToRectangle (x, y, width, height), justificationType, useEllipsesIfTooBig);
|
||||
}
|
||||
|
||||
void Graphics::drawFittedText (const String& text, Rectangle<int> area,
|
||||
Justification justification,
|
||||
const int maximumNumberOfLines,
|
||||
const float minimumHorizontalScale) const
|
||||
{
|
||||
if (text.isNotEmpty() && (! area.isEmpty()) && context.clipRegionIntersects (area))
|
||||
{
|
||||
GlyphArrangement arr;
|
||||
arr.addFittedText (context.getFont(), text,
|
||||
(float) area.getX(), (float) area.getY(),
|
||||
(float) area.getWidth(), (float) area.getHeight(),
|
||||
justification,
|
||||
maximumNumberOfLines,
|
||||
minimumHorizontalScale);
|
||||
|
||||
arr.draw (*this);
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::drawFittedText (const String& text, int x, int y, int width, int height,
|
||||
Justification justification,
|
||||
const int maximumNumberOfLines,
|
||||
const float minimumHorizontalScale) const
|
||||
{
|
||||
drawFittedText (text, coordsToRectangle (x, y, width, height),
|
||||
justification, maximumNumberOfLines, minimumHorizontalScale);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Graphics::fillRect (Rectangle<int> r) const
|
||||
{
|
||||
context.fillRect (r, false);
|
||||
}
|
||||
|
||||
void Graphics::fillRect (Rectangle<float> r) const
|
||||
{
|
||||
context.fillRect (r);
|
||||
}
|
||||
|
||||
void Graphics::fillRect (int x, int y, int width, int height) const
|
||||
{
|
||||
context.fillRect (coordsToRectangle (x, y, width, height), false);
|
||||
}
|
||||
|
||||
void Graphics::fillRect (float x, float y, float width, float height) const
|
||||
{
|
||||
fillRect (coordsToRectangle (x, y, width, height));
|
||||
}
|
||||
|
||||
void Graphics::fillRectList (const RectangleList<float>& rectangles) const
|
||||
{
|
||||
context.fillRectList (rectangles);
|
||||
}
|
||||
|
||||
void Graphics::fillRectList (const RectangleList<int>& rects) const
|
||||
{
|
||||
for (auto& r : rects)
|
||||
context.fillRect (r, false);
|
||||
}
|
||||
|
||||
void Graphics::fillAll() const
|
||||
{
|
||||
fillRect (context.getClipBounds());
|
||||
}
|
||||
|
||||
void Graphics::fillAll (Colour colourToUse) const
|
||||
{
|
||||
if (! colourToUse.isTransparent())
|
||||
{
|
||||
auto clip = context.getClipBounds();
|
||||
|
||||
context.saveState();
|
||||
context.setFill (colourToUse);
|
||||
context.fillRect (clip, false);
|
||||
context.restoreState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
void Graphics::fillPath (const Path& path) const
|
||||
{
|
||||
if (! (context.isClipEmpty() || path.isEmpty()))
|
||||
context.fillPath (path, AffineTransform());
|
||||
}
|
||||
|
||||
void Graphics::fillPath (const Path& path, const AffineTransform& transform) const
|
||||
{
|
||||
if (! (context.isClipEmpty() || path.isEmpty()))
|
||||
context.fillPath (path, transform);
|
||||
}
|
||||
|
||||
void Graphics::strokePath (const Path& path,
|
||||
const PathStrokeType& strokeType,
|
||||
const AffineTransform& transform) const
|
||||
{
|
||||
Path stroke;
|
||||
strokeType.createStrokedPath (stroke, path, transform, context.getPhysicalPixelScaleFactor());
|
||||
fillPath (stroke);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Graphics::drawRect (float x, float y, float width, float height, float lineThickness) const
|
||||
{
|
||||
drawRect (coordsToRectangle (x, y, width, height), lineThickness);
|
||||
}
|
||||
|
||||
void Graphics::drawRect (int x, int y, int width, int height, int lineThickness) const
|
||||
{
|
||||
drawRect (coordsToRectangle (x, y, width, height), lineThickness);
|
||||
}
|
||||
|
||||
void Graphics::drawRect (Rectangle<int> r, int lineThickness) const
|
||||
{
|
||||
drawRect (r.toFloat(), (float) lineThickness);
|
||||
}
|
||||
|
||||
void Graphics::drawRect (Rectangle<float> r, const float lineThickness) const
|
||||
{
|
||||
jassert (r.getWidth() >= 0.0f && r.getHeight() >= 0.0f);
|
||||
|
||||
RectangleList<float> rects;
|
||||
rects.addWithoutMerging (r.removeFromTop (lineThickness));
|
||||
rects.addWithoutMerging (r.removeFromBottom (lineThickness));
|
||||
rects.addWithoutMerging (r.removeFromLeft (lineThickness));
|
||||
rects.addWithoutMerging (r.removeFromRight (lineThickness));
|
||||
context.fillRectList (rects);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Graphics::fillEllipse (Rectangle<float> area) const
|
||||
{
|
||||
Path p;
|
||||
p.addEllipse (area);
|
||||
fillPath (p);
|
||||
}
|
||||
|
||||
void Graphics::fillEllipse (float x, float y, float w, float h) const
|
||||
{
|
||||
fillEllipse (coordsToRectangle (x, y, w, h));
|
||||
}
|
||||
|
||||
void Graphics::drawEllipse (float x, float y, float width, float height, float lineThickness) const
|
||||
{
|
||||
drawEllipse (coordsToRectangle (x, y, width, height), lineThickness);
|
||||
}
|
||||
|
||||
void Graphics::drawEllipse (Rectangle<float> area, float lineThickness) const
|
||||
{
|
||||
Path p;
|
||||
|
||||
if (area.getWidth() == area.getHeight())
|
||||
{
|
||||
// For a circle, we can avoid having to generate a stroke
|
||||
p.addEllipse (area.expanded (lineThickness * 0.5f));
|
||||
p.addEllipse (area.reduced (lineThickness * 0.5f));
|
||||
p.setUsingNonZeroWinding (false);
|
||||
fillPath (p);
|
||||
}
|
||||
else
|
||||
{
|
||||
p.addEllipse (area);
|
||||
strokePath (p, PathStrokeType (lineThickness));
|
||||
}
|
||||
}
|
||||
|
||||
void Graphics::fillRoundedRectangle (float x, float y, float width, float height, float cornerSize) const
|
||||
{
|
||||
fillRoundedRectangle (coordsToRectangle (x, y, width, height), cornerSize);
|
||||
}
|
||||
|
||||
void Graphics::fillRoundedRectangle (Rectangle<float> r, const float cornerSize) const
|
||||
{
|
||||
Path p;
|
||||
p.addRoundedRectangle (r, cornerSize);
|
||||
fillPath (p);
|
||||
}
|
||||
|
||||
void Graphics::drawRoundedRectangle (float x, float y, float width, float height,
|
||||
float cornerSize, float lineThickness) const
|
||||
{
|
||||
drawRoundedRectangle (coordsToRectangle (x, y, width, height), cornerSize, lineThickness);
|
||||
}
|
||||
|
||||
void Graphics::drawRoundedRectangle (Rectangle<float> r, float cornerSize, float lineThickness) const
|
||||
{
|
||||
Path p;
|
||||
p.addRoundedRectangle (r, cornerSize);
|
||||
strokePath (p, PathStrokeType (lineThickness));
|
||||
}
|
||||
|
||||
void Graphics::drawArrow (Line<float> line, float lineThickness, float arrowheadWidth, float arrowheadLength) const
|
||||
{
|
||||
Path p;
|
||||
p.addArrow (line, lineThickness, arrowheadWidth, arrowheadLength);
|
||||
fillPath (p);
|
||||
}
|
||||
|
||||
void Graphics::fillCheckerBoard (Rectangle<float> area, float checkWidth, float checkHeight,
|
||||
Colour colour1, Colour colour2) const
|
||||
{
|
||||
jassert (checkWidth > 0 && checkHeight > 0); // can't be zero or less!
|
||||
|
||||
if (checkWidth > 0 && checkHeight > 0)
|
||||
{
|
||||
context.saveState();
|
||||
|
||||
if (colour1 == colour2)
|
||||
{
|
||||
context.setFill (colour1);
|
||||
context.fillRect (area);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto clipped = context.getClipBounds().getIntersection (area.getSmallestIntegerContainer());
|
||||
|
||||
if (! clipped.isEmpty())
|
||||
{
|
||||
const int checkNumX = (int) (((float) clipped.getX() - area.getX()) / checkWidth);
|
||||
const int checkNumY = (int) (((float) clipped.getY() - area.getY()) / checkHeight);
|
||||
const float startX = area.getX() + (float) checkNumX * checkWidth;
|
||||
const float startY = area.getY() + (float) checkNumY * checkHeight;
|
||||
const float right = (float) clipped.getRight();
|
||||
const float bottom = (float) clipped.getBottom();
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
int cy = i;
|
||||
RectangleList<float> checks;
|
||||
|
||||
for (float y = startY; y < bottom; y += checkHeight)
|
||||
for (float x = startX + (cy++ & 1) * checkWidth; x < right; x += checkWidth * 2.0f)
|
||||
checks.addWithoutMerging ({ x, y, checkWidth, checkHeight });
|
||||
|
||||
checks.clipTo (area);
|
||||
context.setFill (i == ((checkNumX ^ checkNumY) & 1) ? colour1 : colour2);
|
||||
context.fillRectList (checks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.restoreState();
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Graphics::drawVerticalLine (const int x, float top, float bottom) const
|
||||
{
|
||||
if (top < bottom)
|
||||
context.fillRect (Rectangle<float> ((float) x, top, 1.0f, bottom - top));
|
||||
}
|
||||
|
||||
void Graphics::drawHorizontalLine (const int y, float left, float right) const
|
||||
{
|
||||
if (left < right)
|
||||
context.fillRect (Rectangle<float> (left, (float) y, right - left, 1.0f));
|
||||
}
|
||||
|
||||
void Graphics::drawLine (Line<float> line) const
|
||||
{
|
||||
context.drawLine (line);
|
||||
}
|
||||
|
||||
void Graphics::drawLine (float x1, float y1, float x2, float y2) const
|
||||
{
|
||||
context.drawLine (Line<float> (x1, y1, x2, y2));
|
||||
}
|
||||
|
||||
void Graphics::drawLine (float x1, float y1, float x2, float y2, float lineThickness) const
|
||||
{
|
||||
drawLine (Line<float> (x1, y1, x2, y2), lineThickness);
|
||||
}
|
||||
|
||||
void Graphics::drawLine (Line<float> line, const float lineThickness) const
|
||||
{
|
||||
Path p;
|
||||
p.addLineSegment (line, lineThickness);
|
||||
fillPath (p);
|
||||
}
|
||||
|
||||
void Graphics::drawDashedLine (Line<float> line, const float* dashLengths,
|
||||
int numDashLengths, float lineThickness, int n) const
|
||||
{
|
||||
jassert (n >= 0 && n < numDashLengths); // your start index must be valid!
|
||||
|
||||
const Point<double> delta ((line.getEnd() - line.getStart()).toDouble());
|
||||
const double totalLen = delta.getDistanceFromOrigin();
|
||||
|
||||
if (totalLen >= 0.1)
|
||||
{
|
||||
const double onePixAlpha = 1.0 / totalLen;
|
||||
|
||||
for (double alpha = 0.0; alpha < 1.0;)
|
||||
{
|
||||
jassert (dashLengths[n] > 0); // can't have zero-length dashes!
|
||||
|
||||
const double lastAlpha = alpha;
|
||||
alpha += dashLengths [n] * onePixAlpha;
|
||||
n = (n + 1) % numDashLengths;
|
||||
|
||||
if ((n & 1) != 0)
|
||||
{
|
||||
const Line<float> segment (line.getStart() + (delta * lastAlpha).toFloat(),
|
||||
line.getStart() + (delta * jmin (1.0, alpha)).toFloat());
|
||||
|
||||
if (lineThickness != 1.0f)
|
||||
drawLine (segment, lineThickness);
|
||||
else
|
||||
context.drawLine (segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Graphics::setImageResamplingQuality (const Graphics::ResamplingQuality newQuality)
|
||||
{
|
||||
saveStateIfPending();
|
||||
context.setInterpolationQuality (newQuality);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Graphics::drawImageAt (const Image& imageToDraw, int x, int y, bool fillAlphaChannel) const
|
||||
{
|
||||
drawImageTransformed (imageToDraw,
|
||||
AffineTransform::translation ((float) x, (float) y),
|
||||
fillAlphaChannel);
|
||||
}
|
||||
|
||||
void Graphics::drawImage (const Image& imageToDraw, Rectangle<float> targetArea,
|
||||
RectanglePlacement placementWithinTarget, bool fillAlphaChannelWithCurrentBrush) const
|
||||
{
|
||||
if (imageToDraw.isValid())
|
||||
drawImageTransformed (imageToDraw,
|
||||
placementWithinTarget.getTransformToFit (imageToDraw.getBounds().toFloat(), targetArea),
|
||||
fillAlphaChannelWithCurrentBrush);
|
||||
}
|
||||
|
||||
void Graphics::drawImageWithin (const Image& imageToDraw, int dx, int dy, int dw, int dh,
|
||||
RectanglePlacement placementWithinTarget, bool fillAlphaChannelWithCurrentBrush) const
|
||||
{
|
||||
drawImage (imageToDraw, coordsToRectangle (dx, dy, dw, dh).toFloat(),
|
||||
placementWithinTarget, fillAlphaChannelWithCurrentBrush);
|
||||
}
|
||||
|
||||
void Graphics::drawImage (const Image& imageToDraw,
|
||||
int dx, int dy, int dw, int dh,
|
||||
int sx, int sy, int sw, int sh,
|
||||
const bool fillAlphaChannelWithCurrentBrush) const
|
||||
{
|
||||
if (imageToDraw.isValid() && context.clipRegionIntersects (coordsToRectangle (dx, dy, dw, dh)))
|
||||
drawImageTransformed (imageToDraw.getClippedImage (coordsToRectangle (sx, sy, sw, sh)),
|
||||
AffineTransform::scale ((float) dw / (float) sw, (float) dh / (float) sh)
|
||||
.translated ((float) dx, (float) dy),
|
||||
fillAlphaChannelWithCurrentBrush);
|
||||
}
|
||||
|
||||
void Graphics::drawImageTransformed (const Image& imageToDraw,
|
||||
const AffineTransform& transform,
|
||||
const bool fillAlphaChannelWithCurrentBrush) const
|
||||
{
|
||||
if (imageToDraw.isValid() && ! context.isClipEmpty())
|
||||
{
|
||||
if (fillAlphaChannelWithCurrentBrush)
|
||||
{
|
||||
context.saveState();
|
||||
context.clipToImageAlpha (imageToDraw, transform);
|
||||
fillAll();
|
||||
context.restoreState();
|
||||
}
|
||||
else
|
||||
{
|
||||
context.drawImage (imageToDraw, transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
Graphics::ScopedSaveState::ScopedSaveState (Graphics& g) : context (g)
|
||||
{
|
||||
context.saveState();
|
||||
}
|
||||
|
||||
Graphics::ScopedSaveState::~ScopedSaveState()
|
||||
{
|
||||
context.restoreState();
|
||||
}
|
||||
|
||||
} // namespace juce
|
752
deps/juce/modules/juce_graphics/contexts/juce_GraphicsContext.h
vendored
Normal file
752
deps/juce/modules/juce_graphics/contexts/juce_GraphicsContext.h
vendored
Normal file
@ -0,0 +1,752 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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 graphics context, used for drawing a component or image.
|
||||
|
||||
When a Component needs painting, a Graphics context is passed to its
|
||||
Component::paint() method, and this you then call methods within this
|
||||
object to actually draw the component's content.
|
||||
|
||||
A Graphics can also be created from an image, to allow drawing directly onto
|
||||
that image.
|
||||
|
||||
@see Component::paint
|
||||
|
||||
@tags{Graphics}
|
||||
*/
|
||||
class JUCE_API Graphics final
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a Graphics object to draw directly onto the given image.
|
||||
|
||||
The graphics object that is created will be set up to draw onto the image,
|
||||
with the context's clipping area being the entire size of the image, and its
|
||||
origin being the image's origin. To draw into a subsection of an image, use the
|
||||
reduceClipRegion() and setOrigin() methods.
|
||||
|
||||
Obviously you shouldn't delete the image before this context is deleted.
|
||||
*/
|
||||
explicit Graphics (const Image& imageToDrawOnto);
|
||||
|
||||
/** Destructor. */
|
||||
~Graphics();
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the current drawing colour.
|
||||
|
||||
This sets the colour that will now be used for drawing operations - it also
|
||||
sets the opacity to that of the colour passed-in.
|
||||
|
||||
If a brush is being used when this method is called, the brush will be deselected,
|
||||
and any subsequent drawing will be done with a solid colour brush instead.
|
||||
|
||||
@see setOpacity
|
||||
*/
|
||||
void setColour (Colour newColour);
|
||||
|
||||
/** Changes the opacity to use with the current colour.
|
||||
|
||||
If a solid colour is being used for drawing, this changes its opacity
|
||||
to this new value (i.e. it doesn't multiply the colour's opacity by this amount).
|
||||
|
||||
If a gradient is being used, this will have no effect on it.
|
||||
|
||||
A value of 0.0 is completely transparent, 1.0 is completely opaque.
|
||||
*/
|
||||
void setOpacity (float newOpacity);
|
||||
|
||||
/** Sets the context to use a gradient for its fill pattern. */
|
||||
void setGradientFill (const ColourGradient& gradient);
|
||||
|
||||
/** Sets the context to use a gradient for its fill pattern. */
|
||||
void setGradientFill (ColourGradient&& gradient);
|
||||
|
||||
/** Sets the context to use a tiled image pattern for filling.
|
||||
Make sure that you don't delete this image while it's still being used by
|
||||
this context!
|
||||
*/
|
||||
void setTiledImageFill (const Image& imageToUse,
|
||||
int anchorX, int anchorY,
|
||||
float opacity);
|
||||
|
||||
/** Changes the current fill settings.
|
||||
@see setColour, setGradientFill, setTiledImageFill
|
||||
*/
|
||||
void setFillType (const FillType& newFill);
|
||||
|
||||
//==============================================================================
|
||||
/** Changes the font to use for subsequent text-drawing functions.
|
||||
@see drawSingleLineText, drawMultiLineText, drawText, drawFittedText
|
||||
*/
|
||||
void setFont (const Font& newFont);
|
||||
|
||||
/** Changes the size of the currently-selected font.
|
||||
This is a convenient shortcut that changes the context's current font to a
|
||||
different size. The typeface won't be changed.
|
||||
@see Font
|
||||
*/
|
||||
void setFont (float newFontHeight);
|
||||
|
||||
/** Returns the currently selected font. */
|
||||
Font getCurrentFont() const;
|
||||
|
||||
/** Draws a one-line text string.
|
||||
|
||||
This will use the current colour (or brush) to fill the text. The font is the last
|
||||
one specified by setFont().
|
||||
|
||||
@param text the string to draw
|
||||
@param startX the position to draw the left-hand edge of the text
|
||||
@param baselineY the position of the text's baseline
|
||||
@param justification the horizontal flags indicate which end of the text string is
|
||||
anchored at the specified point.
|
||||
@see drawMultiLineText, drawText, drawFittedText, GlyphArrangement::addLineOfText
|
||||
*/
|
||||
void drawSingleLineText (const String& text,
|
||||
int startX, int baselineY,
|
||||
Justification justification = Justification::left) const;
|
||||
|
||||
/** Draws text across multiple lines.
|
||||
|
||||
This will break the text onto a new line where there's a new-line or
|
||||
carriage-return character, or at a word-boundary when the text becomes wider
|
||||
than the size specified by the maximumLineWidth parameter. New-lines
|
||||
will be vertically separated by the specified leading.
|
||||
|
||||
@see setFont, drawSingleLineText, drawFittedText, GlyphArrangement::addJustifiedText
|
||||
*/
|
||||
void drawMultiLineText (const String& text,
|
||||
int startX, int baselineY,
|
||||
int maximumLineWidth,
|
||||
Justification justification = Justification::left,
|
||||
float leading = 0.0f) const;
|
||||
|
||||
/** Draws a line of text within a specified rectangle.
|
||||
|
||||
The text will be positioned within the rectangle based on the justification
|
||||
flags passed-in. If the string is too long to fit inside the rectangle, it will
|
||||
either be truncated or will have ellipsis added to its end (if the useEllipsesIfTooBig
|
||||
flag is true).
|
||||
|
||||
@see drawSingleLineText, drawFittedText, drawMultiLineText, GlyphArrangement::addJustifiedText
|
||||
*/
|
||||
void drawText (const String& text,
|
||||
int x, int y, int width, int height,
|
||||
Justification justificationType,
|
||||
bool useEllipsesIfTooBig = true) const;
|
||||
|
||||
/** Draws a line of text within a specified rectangle.
|
||||
|
||||
The text will be positioned within the rectangle based on the justification
|
||||
flags passed-in. If the string is too long to fit inside the rectangle, it will
|
||||
either be truncated or will have ellipsis added to its end (if the useEllipsesIfTooBig
|
||||
flag is true).
|
||||
|
||||
@see drawSingleLineText, drawFittedText, drawMultiLineText, GlyphArrangement::addJustifiedText
|
||||
*/
|
||||
void drawText (const String& text,
|
||||
Rectangle<int> area,
|
||||
Justification justificationType,
|
||||
bool useEllipsesIfTooBig = true) const;
|
||||
|
||||
/** Draws a line of text within a specified rectangle.
|
||||
|
||||
The text will be positioned within the rectangle based on the justification
|
||||
flags passed-in. If the string is too long to fit inside the rectangle, it will
|
||||
either be truncated or will have ellipsis added to its end (if the useEllipsesIfTooBig
|
||||
flag is true).
|
||||
|
||||
@see drawSingleLineText, drawFittedText, drawMultiLineText, GlyphArrangement::addJustifiedText
|
||||
*/
|
||||
void drawText (const String& text,
|
||||
Rectangle<float> area,
|
||||
Justification justificationType,
|
||||
bool useEllipsesIfTooBig = true) const;
|
||||
|
||||
/** Tries to draw a text string inside a given space.
|
||||
|
||||
This does its best to make the given text readable within the specified rectangle,
|
||||
so it's useful for labelling things.
|
||||
|
||||
If the text is too big, it'll be squashed horizontally or broken over multiple lines
|
||||
if the maximumLinesToUse value allows this. If the text just won't fit into the space,
|
||||
it'll cram as much as possible in there, and put some ellipsis at the end to show that
|
||||
it's been truncated.
|
||||
|
||||
A Justification parameter lets you specify how the text is laid out within the rectangle,
|
||||
both horizontally and vertically.
|
||||
|
||||
The minimumHorizontalScale parameter specifies how much the text can be squashed horizontally
|
||||
to try to squeeze it into the space. If you don't want any horizontal scaling to occur, you
|
||||
can set this value to 1.0f. Pass 0 if you want it to use a default value.
|
||||
|
||||
@see GlyphArrangement::addFittedText
|
||||
*/
|
||||
void drawFittedText (const String& text,
|
||||
int x, int y, int width, int height,
|
||||
Justification justificationFlags,
|
||||
int maximumNumberOfLines,
|
||||
float minimumHorizontalScale = 0.0f) const;
|
||||
|
||||
/** Tries to draw a text string inside a given space.
|
||||
|
||||
This does its best to make the given text readable within the specified rectangle,
|
||||
so it's useful for labelling things.
|
||||
|
||||
If the text is too big, it'll be squashed horizontally or broken over multiple lines
|
||||
if the maximumLinesToUse value allows this. If the text just won't fit into the space,
|
||||
it'll cram as much as possible in there, and put some ellipsis at the end to show that
|
||||
it's been truncated.
|
||||
|
||||
A Justification parameter lets you specify how the text is laid out within the rectangle,
|
||||
both horizontally and vertically.
|
||||
|
||||
The minimumHorizontalScale parameter specifies how much the text can be squashed horizontally
|
||||
to try to squeeze it into the space. If you don't want any horizontal scaling to occur, you
|
||||
can set this value to 1.0f. Pass 0 if you want it to use a default value.
|
||||
|
||||
@see GlyphArrangement::addFittedText
|
||||
*/
|
||||
void drawFittedText (const String& text,
|
||||
Rectangle<int> area,
|
||||
Justification justificationFlags,
|
||||
int maximumNumberOfLines,
|
||||
float minimumHorizontalScale = 0.0f) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Fills the context's entire clip region with the current colour or brush.
|
||||
|
||||
(See also the fillAll (Colour) method which is a quick way of filling
|
||||
it with a given colour).
|
||||
*/
|
||||
void fillAll() const;
|
||||
|
||||
/** Fills the context's entire clip region with a given colour.
|
||||
|
||||
This leaves the context's current colour and brush unchanged, it just
|
||||
uses the specified colour temporarily.
|
||||
*/
|
||||
void fillAll (Colour colourToUse) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Fills a rectangle with the current colour or brush.
|
||||
@see drawRect, fillRoundedRectangle
|
||||
*/
|
||||
void fillRect (Rectangle<int> rectangle) const;
|
||||
|
||||
/** Fills a rectangle with the current colour or brush.
|
||||
@see drawRect, fillRoundedRectangle
|
||||
*/
|
||||
void fillRect (Rectangle<float> rectangle) const;
|
||||
|
||||
/** Fills a rectangle with the current colour or brush.
|
||||
@see drawRect, fillRoundedRectangle
|
||||
*/
|
||||
void fillRect (int x, int y, int width, int height) const;
|
||||
|
||||
/** Fills a rectangle with the current colour or brush.
|
||||
@see drawRect, fillRoundedRectangle
|
||||
*/
|
||||
void fillRect (float x, float y, float width, float height) const;
|
||||
|
||||
/** Fills a set of rectangles using the current colour or brush.
|
||||
If you have a lot of rectangles to draw, it may be more efficient
|
||||
to create a RectangleList and use this method than to call fillRect()
|
||||
multiple times.
|
||||
*/
|
||||
void fillRectList (const RectangleList<float>& rectangles) const;
|
||||
|
||||
/** Fills a set of rectangles using the current colour or brush.
|
||||
If you have a lot of rectangles to draw, it may be more efficient
|
||||
to create a RectangleList and use this method than to call fillRect()
|
||||
multiple times.
|
||||
*/
|
||||
void fillRectList (const RectangleList<int>& rectangles) const;
|
||||
|
||||
/** Uses the current colour or brush to fill a rectangle with rounded corners.
|
||||
@see drawRoundedRectangle, Path::addRoundedRectangle
|
||||
*/
|
||||
void fillRoundedRectangle (float x, float y, float width, float height,
|
||||
float cornerSize) const;
|
||||
|
||||
/** Uses the current colour or brush to fill a rectangle with rounded corners.
|
||||
@see drawRoundedRectangle, Path::addRoundedRectangle
|
||||
*/
|
||||
void fillRoundedRectangle (Rectangle<float> rectangle,
|
||||
float cornerSize) const;
|
||||
|
||||
/** Fills a rectangle with a checkerboard pattern, alternating between two colours. */
|
||||
void fillCheckerBoard (Rectangle<float> area,
|
||||
float checkWidth, float checkHeight,
|
||||
Colour colour1, Colour colour2) const;
|
||||
|
||||
/** Draws a rectangular outline, using the current colour or brush.
|
||||
The lines are drawn inside the given rectangle, and greater line thicknesses extend inwards.
|
||||
@see fillRect
|
||||
*/
|
||||
void drawRect (int x, int y, int width, int height, int lineThickness = 1) const;
|
||||
|
||||
/** Draws a rectangular outline, using the current colour or brush.
|
||||
The lines are drawn inside the given rectangle, and greater line thicknesses extend inwards.
|
||||
@see fillRect
|
||||
*/
|
||||
void drawRect (float x, float y, float width, float height, float lineThickness = 1.0f) const;
|
||||
|
||||
/** Draws a rectangular outline, using the current colour or brush.
|
||||
The lines are drawn inside the given rectangle, and greater line thicknesses extend inwards.
|
||||
@see fillRect
|
||||
*/
|
||||
void drawRect (Rectangle<int> rectangle, int lineThickness = 1) const;
|
||||
|
||||
/** Draws a rectangular outline, using the current colour or brush.
|
||||
The lines are drawn inside the given rectangle, and greater line thicknesses extend inwards.
|
||||
@see fillRect
|
||||
*/
|
||||
void drawRect (Rectangle<float> rectangle, float lineThickness = 1.0f) const;
|
||||
|
||||
/** Uses the current colour or brush to draw the outline of a rectangle with rounded corners.
|
||||
@see fillRoundedRectangle, Path::addRoundedRectangle
|
||||
*/
|
||||
void drawRoundedRectangle (float x, float y, float width, float height,
|
||||
float cornerSize, float lineThickness) const;
|
||||
|
||||
/** Uses the current colour or brush to draw the outline of a rectangle with rounded corners.
|
||||
@see fillRoundedRectangle, Path::addRoundedRectangle
|
||||
*/
|
||||
void drawRoundedRectangle (Rectangle<float> rectangle,
|
||||
float cornerSize, float lineThickness) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Fills an ellipse with the current colour or brush.
|
||||
The ellipse is drawn to fit inside the given rectangle.
|
||||
@see drawEllipse, Path::addEllipse
|
||||
*/
|
||||
void fillEllipse (float x, float y, float width, float height) const;
|
||||
|
||||
/** Fills an ellipse with the current colour or brush.
|
||||
The ellipse is drawn to fit inside the given rectangle.
|
||||
@see drawEllipse, Path::addEllipse
|
||||
*/
|
||||
void fillEllipse (Rectangle<float> area) const;
|
||||
|
||||
/** Draws an elliptical stroke using the current colour or brush.
|
||||
@see fillEllipse, Path::addEllipse
|
||||
*/
|
||||
void drawEllipse (float x, float y, float width, float height,
|
||||
float lineThickness) const;
|
||||
|
||||
/** Draws an elliptical stroke using the current colour or brush.
|
||||
@see fillEllipse, Path::addEllipse
|
||||
*/
|
||||
void drawEllipse (Rectangle<float> area, float lineThickness) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Draws a line between two points.
|
||||
The line is 1 pixel wide and drawn with the current colour or brush.
|
||||
TIP: If you're trying to draw horizontal or vertical lines, don't use this -
|
||||
it's better to use fillRect() instead unless you really need an angled line.
|
||||
*/
|
||||
void drawLine (float startX, float startY, float endX, float endY) const;
|
||||
|
||||
/** Draws a line between two points with a given thickness.
|
||||
TIP: If you're trying to draw horizontal or vertical lines, don't use this -
|
||||
it's better to use fillRect() instead unless you really need an angled line.
|
||||
@see Path::addLineSegment
|
||||
*/
|
||||
void drawLine (float startX, float startY, float endX, float endY, float lineThickness) const;
|
||||
|
||||
/** Draws a line between two points.
|
||||
The line is 1 pixel wide and drawn with the current colour or brush.
|
||||
TIP: If you're trying to draw horizontal or vertical lines, don't use this -
|
||||
it's better to use fillRect() instead unless you really need an angled line.
|
||||
*/
|
||||
void drawLine (Line<float> line) const;
|
||||
|
||||
/** Draws a line between two points with a given thickness.
|
||||
@see Path::addLineSegment
|
||||
TIP: If you're trying to draw horizontal or vertical lines, don't use this -
|
||||
it's better to use fillRect() instead unless you really need an angled line.
|
||||
*/
|
||||
void drawLine (Line<float> line, float lineThickness) const;
|
||||
|
||||
/** Draws a dashed line using a custom set of dash-lengths.
|
||||
|
||||
@param line the line to draw
|
||||
@param dashLengths a series of lengths to specify the on/off lengths - e.g.
|
||||
{ 4, 5, 6, 7 } will draw a line of 4 pixels, skip 5 pixels,
|
||||
draw 6 pixels, skip 7 pixels, and then repeat.
|
||||
@param numDashLengths the number of elements in the array (this must be an even number).
|
||||
@param lineThickness the thickness of the line to draw
|
||||
@param dashIndexToStartFrom the index in the dash-length array to use for the first segment
|
||||
@see PathStrokeType::createDashedStroke
|
||||
*/
|
||||
void drawDashedLine (Line<float> line,
|
||||
const float* dashLengths, int numDashLengths,
|
||||
float lineThickness = 1.0f,
|
||||
int dashIndexToStartFrom = 0) const;
|
||||
|
||||
/** Draws a vertical line of pixels at a given x position.
|
||||
|
||||
The x position is an integer, but the top and bottom of the line can be sub-pixel
|
||||
positions, and these will be anti-aliased if necessary.
|
||||
|
||||
The bottom parameter must be greater than or equal to the top parameter.
|
||||
*/
|
||||
void drawVerticalLine (int x, float top, float bottom) const;
|
||||
|
||||
/** Draws a horizontal line of pixels at a given y position.
|
||||
|
||||
The y position is an integer, but the left and right ends of the line can be sub-pixel
|
||||
positions, and these will be anti-aliased if necessary.
|
||||
|
||||
The right parameter must be greater than or equal to the left parameter.
|
||||
*/
|
||||
void drawHorizontalLine (int y, float left, float right) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Fills a path using the currently selected colour or brush. */
|
||||
void fillPath (const Path& path) const;
|
||||
|
||||
/** Fills a path using the currently selected colour or brush, and adds a transform. */
|
||||
void fillPath (const Path& path, const AffineTransform& transform) const;
|
||||
|
||||
/** Draws a path's outline using the currently selected colour or brush. */
|
||||
void strokePath (const Path& path,
|
||||
const PathStrokeType& strokeType,
|
||||
const AffineTransform& transform = {}) const;
|
||||
|
||||
/** Draws a line with an arrowhead at its end.
|
||||
|
||||
@param line the line to draw
|
||||
@param lineThickness the thickness of the line
|
||||
@param arrowheadWidth the width of the arrow head (perpendicular to the line)
|
||||
@param arrowheadLength the length of the arrow head (along the length of the line)
|
||||
*/
|
||||
void drawArrow (Line<float> line,
|
||||
float lineThickness,
|
||||
float arrowheadWidth,
|
||||
float arrowheadLength) const;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Types of rendering quality that can be specified when drawing images.
|
||||
|
||||
@see Graphics::setImageResamplingQuality
|
||||
*/
|
||||
enum ResamplingQuality
|
||||
{
|
||||
lowResamplingQuality = 0, /**< Just uses a nearest-neighbour algorithm for resampling. */
|
||||
mediumResamplingQuality = 1, /**< Uses bilinear interpolation for upsampling and area-averaging for downsampling. */
|
||||
highResamplingQuality = 2, /**< Uses bicubic interpolation for upsampling and area-averaging for downsampling. */
|
||||
};
|
||||
|
||||
/** Changes the quality that will be used when resampling images.
|
||||
By default a Graphics object will be set to mediumRenderingQuality.
|
||||
@see Graphics::drawImage, Graphics::drawImageTransformed, Graphics::drawImageWithin
|
||||
*/
|
||||
void setImageResamplingQuality (const ResamplingQuality newQuality);
|
||||
|
||||
/** Draws an image.
|
||||
|
||||
This will draw the whole of an image, positioning its top-left corner at the
|
||||
given coordinates, and keeping its size the same. This is the simplest image
|
||||
drawing method - the others give more control over the scaling and clipping
|
||||
of the images.
|
||||
|
||||
Images are composited using the context's current opacity, so if you
|
||||
don't want it to be drawn semi-transparently, be sure to call setOpacity (1.0f)
|
||||
(or setColour() with an opaque colour) before drawing images.
|
||||
*/
|
||||
void drawImageAt (const Image& imageToDraw, int topLeftX, int topLeftY,
|
||||
bool fillAlphaChannelWithCurrentBrush = false) const;
|
||||
|
||||
/** Draws part of an image, rescaling it to fit in a given target region.
|
||||
|
||||
The specified area of the source image is rescaled and drawn to fill the
|
||||
specified destination rectangle.
|
||||
|
||||
Images are composited using the context's current opacity, so if you
|
||||
don't want it to be drawn semi-transparently, be sure to call setOpacity (1.0f)
|
||||
(or setColour() with an opaque colour) before drawing images.
|
||||
|
||||
@param imageToDraw the image to overlay
|
||||
@param destX the left of the destination rectangle
|
||||
@param destY the top of the destination rectangle
|
||||
@param destWidth the width of the destination rectangle
|
||||
@param destHeight the height of the destination rectangle
|
||||
@param sourceX the left of the rectangle to copy from the source image
|
||||
@param sourceY the top of the rectangle to copy from the source image
|
||||
@param sourceWidth the width of the rectangle to copy from the source image
|
||||
@param sourceHeight the height of the rectangle to copy from the source image
|
||||
@param fillAlphaChannelWithCurrentBrush if true, then instead of drawing the source image's pixels,
|
||||
the source image's alpha channel is used as a mask with
|
||||
which to fill the destination using the current colour
|
||||
or brush. (If the source is has no alpha channel, then
|
||||
it will just fill the target with a solid rectangle)
|
||||
@see setImageResamplingQuality, drawImageAt, drawImageWithin, fillAlphaMap
|
||||
*/
|
||||
void drawImage (const Image& imageToDraw,
|
||||
int destX, int destY, int destWidth, int destHeight,
|
||||
int sourceX, int sourceY, int sourceWidth, int sourceHeight,
|
||||
bool fillAlphaChannelWithCurrentBrush = false) const;
|
||||
|
||||
/** Draws an image, having applied an affine transform to it.
|
||||
|
||||
This lets you throw the image around in some wacky ways, rotate it, shear,
|
||||
scale it, etc.
|
||||
|
||||
Images are composited using the context's current opacity, so if you
|
||||
don't want it to be drawn semi-transparently, be sure to call setOpacity (1.0f)
|
||||
(or setColour() with an opaque colour) before drawing images.
|
||||
|
||||
If fillAlphaChannelWithCurrentBrush is set to true, then the image's RGB channels
|
||||
are ignored and it is filled with the current brush, masked by its alpha channel.
|
||||
|
||||
If you want to render only a subsection of an image, use Image::getClippedImage() to
|
||||
create the section that you need.
|
||||
|
||||
@see setImageResamplingQuality, drawImage
|
||||
*/
|
||||
void drawImageTransformed (const Image& imageToDraw,
|
||||
const AffineTransform& transform,
|
||||
bool fillAlphaChannelWithCurrentBrush = false) const;
|
||||
|
||||
/** Draws an image to fit within a designated rectangle.
|
||||
|
||||
@param imageToDraw the source image to draw
|
||||
@param targetArea the target rectangle to fit it into
|
||||
@param placementWithinTarget this specifies how the image should be positioned
|
||||
within the target rectangle - see the RectanglePlacement
|
||||
class for more details about this.
|
||||
@param fillAlphaChannelWithCurrentBrush if true, then instead of drawing the image, just its
|
||||
alpha channel will be used as a mask with which to
|
||||
draw with the current brush or colour. This is
|
||||
similar to fillAlphaMap(), and see also drawImage()
|
||||
@see drawImage, drawImageTransformed, drawImageAt, RectanglePlacement
|
||||
*/
|
||||
void drawImage (const Image& imageToDraw, Rectangle<float> targetArea,
|
||||
RectanglePlacement placementWithinTarget = RectanglePlacement::stretchToFit,
|
||||
bool fillAlphaChannelWithCurrentBrush = false) const;
|
||||
|
||||
/** Draws an image to fit within a designated rectangle.
|
||||
|
||||
If the image is too big or too small for the space, it will be rescaled
|
||||
to fit as nicely as it can do without affecting its aspect ratio. It will
|
||||
then be placed within the target rectangle according to the justification flags
|
||||
specified.
|
||||
|
||||
@param imageToDraw the source image to draw
|
||||
@param destX top-left of the target rectangle to fit it into
|
||||
@param destY top-left of the target rectangle to fit it into
|
||||
@param destWidth size of the target rectangle to fit the image into
|
||||
@param destHeight size of the target rectangle to fit the image into
|
||||
@param placementWithinTarget this specifies how the image should be positioned
|
||||
within the target rectangle - see the RectanglePlacement
|
||||
class for more details about this.
|
||||
@param fillAlphaChannelWithCurrentBrush if true, then instead of drawing the image, just its
|
||||
alpha channel will be used as a mask with which to
|
||||
draw with the current brush or colour. This is
|
||||
similar to fillAlphaMap(), and see also drawImage()
|
||||
@see setImageResamplingQuality, drawImage, drawImageTransformed, drawImageAt, RectanglePlacement
|
||||
*/
|
||||
void drawImageWithin (const Image& imageToDraw,
|
||||
int destX, int destY, int destWidth, int destHeight,
|
||||
RectanglePlacement placementWithinTarget,
|
||||
bool fillAlphaChannelWithCurrentBrush = false) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the position of the bounding box for the current clipping region.
|
||||
@see clipRegionIntersects
|
||||
*/
|
||||
Rectangle<int> getClipBounds() const;
|
||||
|
||||
/** Checks whether a rectangle overlaps the context's clipping region.
|
||||
|
||||
If this returns false, no part of the given area can be drawn onto, so this
|
||||
method can be used to optimise a component's paint() method, by letting it
|
||||
avoid drawing complex objects that aren't within the region being repainted.
|
||||
*/
|
||||
bool clipRegionIntersects (Rectangle<int> area) const;
|
||||
|
||||
/** Intersects the current clipping region with another region.
|
||||
|
||||
@returns true if the resulting clipping region is non-zero in size
|
||||
@see setOrigin, clipRegionIntersects
|
||||
*/
|
||||
bool reduceClipRegion (int x, int y, int width, int height);
|
||||
|
||||
/** Intersects the current clipping region with another region.
|
||||
|
||||
@returns true if the resulting clipping region is non-zero in size
|
||||
@see setOrigin, clipRegionIntersects
|
||||
*/
|
||||
bool reduceClipRegion (Rectangle<int> area);
|
||||
|
||||
/** Intersects the current clipping region with a rectangle list region.
|
||||
|
||||
@returns true if the resulting clipping region is non-zero in size
|
||||
@see setOrigin, clipRegionIntersects
|
||||
*/
|
||||
bool reduceClipRegion (const RectangleList<int>& clipRegion);
|
||||
|
||||
/** Intersects the current clipping region with a path.
|
||||
|
||||
@returns true if the resulting clipping region is non-zero in size
|
||||
@see reduceClipRegion
|
||||
*/
|
||||
bool reduceClipRegion (const Path& path, const AffineTransform& transform = AffineTransform());
|
||||
|
||||
/** Intersects the current clipping region with an image's alpha-channel.
|
||||
|
||||
The current clipping path is intersected with the area covered by this image's
|
||||
alpha-channel, after the image has been transformed by the specified matrix.
|
||||
|
||||
@param image the image whose alpha-channel should be used. If the image doesn't
|
||||
have an alpha-channel, it is treated as entirely opaque.
|
||||
@param transform a matrix to apply to the image
|
||||
@returns true if the resulting clipping region is non-zero in size
|
||||
@see reduceClipRegion
|
||||
*/
|
||||
bool reduceClipRegion (const Image& image, const AffineTransform& transform);
|
||||
|
||||
/** Excludes a rectangle to stop it being drawn into. */
|
||||
void excludeClipRegion (Rectangle<int> rectangleToExclude);
|
||||
|
||||
/** Returns true if no drawing can be done because the clip region is zero. */
|
||||
bool isClipEmpty() const;
|
||||
|
||||
//==============================================================================
|
||||
/** Saves the current graphics state on an internal stack.
|
||||
To restore the state, use restoreState().
|
||||
@see ScopedSaveState
|
||||
*/
|
||||
void saveState();
|
||||
|
||||
/** Restores a graphics state that was previously saved with saveState().
|
||||
@see ScopedSaveState
|
||||
*/
|
||||
void restoreState();
|
||||
|
||||
/** Uses RAII to save and restore the state of a graphics context.
|
||||
On construction, this calls Graphics::saveState(), and on destruction it calls
|
||||
Graphics::restoreState() on the Graphics object that you supply.
|
||||
*/
|
||||
class ScopedSaveState
|
||||
{
|
||||
public:
|
||||
ScopedSaveState (Graphics&);
|
||||
~ScopedSaveState();
|
||||
|
||||
private:
|
||||
Graphics& context;
|
||||
JUCE_DECLARE_NON_COPYABLE (ScopedSaveState)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Begins rendering to an off-screen bitmap which will later be flattened onto the current
|
||||
context with the given opacity.
|
||||
|
||||
The context uses an internal stack of temporary image layers to do this. When you've
|
||||
finished drawing to the layer, call endTransparencyLayer() to complete the operation and
|
||||
composite the finished layer. Every call to beginTransparencyLayer() MUST be matched
|
||||
by a corresponding call to endTransparencyLayer()!
|
||||
|
||||
This call also saves the current state, and endTransparencyLayer() restores it.
|
||||
*/
|
||||
void beginTransparencyLayer (float layerOpacity);
|
||||
|
||||
/** Completes a drawing operation to a temporary semi-transparent buffer.
|
||||
See beginTransparencyLayer() for more details.
|
||||
*/
|
||||
void endTransparencyLayer();
|
||||
|
||||
/** Moves the position of the context's origin.
|
||||
|
||||
This changes the position that the context considers to be (0, 0) to
|
||||
the specified position.
|
||||
|
||||
So if you call setOrigin with (100, 100), then the position that was previously
|
||||
referred to as (100, 100) will subsequently be considered to be (0, 0).
|
||||
|
||||
@see reduceClipRegion, addTransform
|
||||
*/
|
||||
void setOrigin (Point<int> newOrigin);
|
||||
|
||||
/** Moves the position of the context's origin.
|
||||
|
||||
This changes the position that the context considers to be (0, 0) to
|
||||
the specified position.
|
||||
|
||||
So if you call setOrigin (100, 100), then the position that was previously
|
||||
referred to as (100, 100) will subsequently be considered to be (0, 0).
|
||||
|
||||
@see reduceClipRegion, addTransform
|
||||
*/
|
||||
void setOrigin (int newOriginX, int newOriginY);
|
||||
|
||||
/** Adds a transformation which will be performed on all the graphics operations that
|
||||
the context subsequently performs.
|
||||
|
||||
After calling this, all the coordinates that are passed into the context will be
|
||||
transformed by this matrix.
|
||||
|
||||
@see setOrigin
|
||||
*/
|
||||
void addTransform (const AffineTransform& transform);
|
||||
|
||||
/** Resets the current colour, brush, and font to default settings. */
|
||||
void resetToDefaultState();
|
||||
|
||||
/** Returns true if this context is drawing to a vector-based device, such as a printer. */
|
||||
bool isVectorDevice() const;
|
||||
|
||||
//==============================================================================
|
||||
/** Create a graphics that draws with a given low-level renderer.
|
||||
This method is intended for use only by people who know what they're doing.
|
||||
Note that the LowLevelGraphicsContext will NOT be deleted by this object.
|
||||
*/
|
||||
Graphics (LowLevelGraphicsContext&) noexcept;
|
||||
|
||||
/** @internal */
|
||||
LowLevelGraphicsContext& getInternalContext() const noexcept { return context; }
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
std::unique_ptr<LowLevelGraphicsContext> contextHolder;
|
||||
LowLevelGraphicsContext& context;
|
||||
|
||||
bool saveStatePending = false;
|
||||
void saveStateIfPending();
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Graphics)
|
||||
};
|
||||
|
||||
} // namespace juce
|
102
deps/juce/modules/juce_graphics/contexts/juce_LowLevelGraphicsContext.h
vendored
Normal file
102
deps/juce/modules/juce_graphics/contexts/juce_LowLevelGraphicsContext.h
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Interface class for graphics context objects, used internally by the Graphics class.
|
||||
|
||||
Users are not supposed to create instances of this class directly - do your drawing
|
||||
via the Graphics object instead.
|
||||
|
||||
It's a base class for different types of graphics context, that may perform software-based
|
||||
or OS-accelerated rendering.
|
||||
|
||||
E.g. the LowLevelGraphicsSoftwareRenderer renders onto an image in memory, but other
|
||||
subclasses could render directly to a windows HDC, a Quartz context, or an OpenGL
|
||||
context.
|
||||
|
||||
@tags{Graphics}
|
||||
*/
|
||||
class JUCE_API LowLevelGraphicsContext
|
||||
{
|
||||
protected:
|
||||
//==============================================================================
|
||||
LowLevelGraphicsContext();
|
||||
|
||||
public:
|
||||
virtual ~LowLevelGraphicsContext();
|
||||
|
||||
/** Returns true if this device is vector-based, e.g. a printer. */
|
||||
virtual bool isVectorDevice() const = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Moves the origin to a new position.
|
||||
|
||||
The coordinates are relative to the current origin, and indicate the new position
|
||||
of (0, 0).
|
||||
*/
|
||||
virtual void setOrigin (Point<int>) = 0;
|
||||
virtual void addTransform (const AffineTransform&) = 0;
|
||||
virtual float getPhysicalPixelScaleFactor() = 0;
|
||||
|
||||
virtual bool clipToRectangle (const Rectangle<int>&) = 0;
|
||||
virtual bool clipToRectangleList (const RectangleList<int>&) = 0;
|
||||
virtual void excludeClipRectangle (const Rectangle<int>&) = 0;
|
||||
virtual void clipToPath (const Path&, const AffineTransform&) = 0;
|
||||
virtual void clipToImageAlpha (const Image&, const AffineTransform&) = 0;
|
||||
|
||||
virtual bool clipRegionIntersects (const Rectangle<int>&) = 0;
|
||||
virtual Rectangle<int> getClipBounds() const = 0;
|
||||
virtual bool isClipEmpty() const = 0;
|
||||
|
||||
virtual void saveState() = 0;
|
||||
virtual void restoreState() = 0;
|
||||
|
||||
virtual void beginTransparencyLayer (float opacity) = 0;
|
||||
virtual void endTransparencyLayer() = 0;
|
||||
|
||||
//==============================================================================
|
||||
virtual void setFill (const FillType&) = 0;
|
||||
virtual void setOpacity (float) = 0;
|
||||
virtual void setInterpolationQuality (Graphics::ResamplingQuality) = 0;
|
||||
|
||||
//==============================================================================
|
||||
virtual void fillRect (const Rectangle<int>&, bool replaceExistingContents) = 0;
|
||||
virtual void fillRect (const Rectangle<float>&) = 0;
|
||||
virtual void fillRectList (const RectangleList<float>&) = 0;
|
||||
virtual void fillPath (const Path&, const AffineTransform&) = 0;
|
||||
virtual void drawImage (const Image&, const AffineTransform&) = 0;
|
||||
virtual void drawLine (const Line<float>&) = 0;
|
||||
|
||||
virtual void setFont (const Font&) = 0;
|
||||
virtual const Font& getFont() = 0;
|
||||
virtual void drawGlyph (int glyphNumber, const AffineTransform&) = 0;
|
||||
virtual bool drawTextLayout (const AttributedString&, const Rectangle<float>&) { return false; }
|
||||
};
|
||||
|
||||
} // namespace juce
|
539
deps/juce/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp
vendored
Normal file
539
deps/juce/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp
vendored
Normal file
@ -0,0 +1,539 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
// this will throw an assertion if you try to draw something that's not
|
||||
// possible in postscript
|
||||
#define WARN_ABOUT_NON_POSTSCRIPT_OPERATIONS 0
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_DEBUG && WARN_ABOUT_NON_POSTSCRIPT_OPERATIONS
|
||||
#define notPossibleInPostscriptAssert jassertfalse
|
||||
#else
|
||||
#define notPossibleInPostscriptAssert
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
LowLevelGraphicsPostScriptRenderer::LowLevelGraphicsPostScriptRenderer (OutputStream& resultingPostScript,
|
||||
const String& documentTitle,
|
||||
const int totalWidth_,
|
||||
const int totalHeight_)
|
||||
: out (resultingPostScript),
|
||||
totalWidth (totalWidth_),
|
||||
totalHeight (totalHeight_),
|
||||
needToClip (true)
|
||||
{
|
||||
stateStack.add (new SavedState());
|
||||
stateStack.getLast()->clip = Rectangle<int> (totalWidth_, totalHeight_);
|
||||
|
||||
const float scale = jmin ((520.0f / (float) totalWidth_), (750.0f / (float) totalHeight));
|
||||
|
||||
out << "%!PS-Adobe-3.0 EPSF-3.0"
|
||||
"\n%%BoundingBox: 0 0 600 824"
|
||||
"\n%%Pages: 0"
|
||||
"\n%%Creator: Raw Material Software Limited - JUCE"
|
||||
"\n%%Title: " << documentTitle <<
|
||||
"\n%%CreationDate: none"
|
||||
"\n%%LanguageLevel: 2"
|
||||
"\n%%EndComments"
|
||||
"\n%%BeginProlog"
|
||||
"\n%%BeginResource: JRes"
|
||||
"\n/bd {bind def} bind def"
|
||||
"\n/c {setrgbcolor} bd"
|
||||
"\n/m {moveto} bd"
|
||||
"\n/l {lineto} bd"
|
||||
"\n/rl {rlineto} bd"
|
||||
"\n/ct {curveto} bd"
|
||||
"\n/cp {closepath} bd"
|
||||
"\n/pr {3 index 3 index moveto 1 index 0 rlineto 0 1 index rlineto pop neg 0 rlineto pop pop closepath} bd"
|
||||
"\n/doclip {initclip newpath} bd"
|
||||
"\n/endclip {clip newpath} bd"
|
||||
"\n%%EndResource"
|
||||
"\n%%EndProlog"
|
||||
"\n%%BeginSetup"
|
||||
"\n%%EndSetup"
|
||||
"\n%%Page: 1 1"
|
||||
"\n%%BeginPageSetup"
|
||||
"\n%%EndPageSetup\n\n"
|
||||
<< "40 800 translate\n"
|
||||
<< scale << ' ' << scale << " scale\n\n";
|
||||
}
|
||||
|
||||
LowLevelGraphicsPostScriptRenderer::~LowLevelGraphicsPostScriptRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool LowLevelGraphicsPostScriptRenderer::isVectorDevice() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::setOrigin (Point<int> o)
|
||||
{
|
||||
if (! o.isOrigin())
|
||||
{
|
||||
stateStack.getLast()->xOffset += o.x;
|
||||
stateStack.getLast()->yOffset += o.y;
|
||||
needToClip = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::addTransform (const AffineTransform& /*transform*/)
|
||||
{
|
||||
//xxx
|
||||
jassertfalse;
|
||||
}
|
||||
|
||||
float LowLevelGraphicsPostScriptRenderer::getPhysicalPixelScaleFactor() { return 1.0f; }
|
||||
|
||||
bool LowLevelGraphicsPostScriptRenderer::clipToRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
needToClip = true;
|
||||
return stateStack.getLast()->clip.clipTo (r.translated (stateStack.getLast()->xOffset, stateStack.getLast()->yOffset));
|
||||
}
|
||||
|
||||
bool LowLevelGraphicsPostScriptRenderer::clipToRectangleList (const RectangleList<int>& clipRegion)
|
||||
{
|
||||
needToClip = true;
|
||||
return stateStack.getLast()->clip.clipTo (clipRegion);
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::excludeClipRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
needToClip = true;
|
||||
stateStack.getLast()->clip.subtract (r.translated (stateStack.getLast()->xOffset, stateStack.getLast()->yOffset));
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::clipToPath (const Path& path, const AffineTransform& transform)
|
||||
{
|
||||
writeClip();
|
||||
|
||||
Path p (path);
|
||||
p.applyTransform (transform.translated ((float) stateStack.getLast()->xOffset, (float) stateStack.getLast()->yOffset));
|
||||
writePath (p);
|
||||
out << "clip\n";
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::clipToImageAlpha (const Image& /*sourceImage*/, const AffineTransform& /*transform*/)
|
||||
{
|
||||
needToClip = true;
|
||||
jassertfalse; // xxx
|
||||
}
|
||||
|
||||
bool LowLevelGraphicsPostScriptRenderer::clipRegionIntersects (const Rectangle<int>& r)
|
||||
{
|
||||
return stateStack.getLast()->clip.intersectsRectangle (r.translated (stateStack.getLast()->xOffset, stateStack.getLast()->yOffset));
|
||||
}
|
||||
|
||||
Rectangle<int> LowLevelGraphicsPostScriptRenderer::getClipBounds() const
|
||||
{
|
||||
return stateStack.getLast()->clip.getBounds().translated (-stateStack.getLast()->xOffset,
|
||||
-stateStack.getLast()->yOffset);
|
||||
}
|
||||
|
||||
bool LowLevelGraphicsPostScriptRenderer::isClipEmpty() const
|
||||
{
|
||||
return stateStack.getLast()->clip.isEmpty();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
LowLevelGraphicsPostScriptRenderer::SavedState::SavedState()
|
||||
: xOffset (0),
|
||||
yOffset (0)
|
||||
{
|
||||
}
|
||||
|
||||
LowLevelGraphicsPostScriptRenderer::SavedState::~SavedState()
|
||||
{
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::saveState()
|
||||
{
|
||||
stateStack.add (new SavedState (*stateStack.getLast()));
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::restoreState()
|
||||
{
|
||||
jassert (stateStack.size() > 0);
|
||||
|
||||
if (stateStack.size() > 0)
|
||||
stateStack.removeLast();
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::beginTransparencyLayer (float)
|
||||
{
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::endTransparencyLayer()
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void LowLevelGraphicsPostScriptRenderer::writeClip()
|
||||
{
|
||||
if (needToClip)
|
||||
{
|
||||
needToClip = false;
|
||||
|
||||
out << "doclip ";
|
||||
|
||||
int itemsOnLine = 0;
|
||||
|
||||
for (auto& i : stateStack.getLast()->clip)
|
||||
{
|
||||
if (++itemsOnLine == 6)
|
||||
{
|
||||
itemsOnLine = 0;
|
||||
out << '\n';
|
||||
}
|
||||
|
||||
out << i.getX() << ' ' << -i.getY() << ' '
|
||||
<< i.getWidth() << ' ' << -i.getHeight() << " pr ";
|
||||
}
|
||||
|
||||
out << "endclip\n";
|
||||
}
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::writeColour (Colour colour)
|
||||
{
|
||||
Colour c (Colours::white.overlaidWith (colour));
|
||||
|
||||
if (lastColour != c)
|
||||
{
|
||||
lastColour = c;
|
||||
|
||||
out << String (c.getFloatRed(), 3) << ' '
|
||||
<< String (c.getFloatGreen(), 3) << ' '
|
||||
<< String (c.getFloatBlue(), 3) << " c\n";
|
||||
}
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::writeXY (const float x, const float y) const
|
||||
{
|
||||
out << String (x, 2) << ' '
|
||||
<< String (-y, 2) << ' ';
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::writePath (const Path& path) const
|
||||
{
|
||||
out << "newpath ";
|
||||
|
||||
float lastX = 0.0f;
|
||||
float lastY = 0.0f;
|
||||
int itemsOnLine = 0;
|
||||
|
||||
Path::Iterator i (path);
|
||||
|
||||
while (i.next())
|
||||
{
|
||||
if (++itemsOnLine == 4)
|
||||
{
|
||||
itemsOnLine = 0;
|
||||
out << '\n';
|
||||
}
|
||||
|
||||
switch (i.elementType)
|
||||
{
|
||||
case Path::Iterator::startNewSubPath:
|
||||
writeXY (i.x1, i.y1);
|
||||
lastX = i.x1;
|
||||
lastY = i.y1;
|
||||
out << "m ";
|
||||
break;
|
||||
|
||||
case Path::Iterator::lineTo:
|
||||
writeXY (i.x1, i.y1);
|
||||
lastX = i.x1;
|
||||
lastY = i.y1;
|
||||
out << "l ";
|
||||
break;
|
||||
|
||||
case Path::Iterator::quadraticTo:
|
||||
{
|
||||
const float cp1x = lastX + (i.x1 - lastX) * 2.0f / 3.0f;
|
||||
const float cp1y = lastY + (i.y1 - lastY) * 2.0f / 3.0f;
|
||||
const float cp2x = cp1x + (i.x2 - lastX) / 3.0f;
|
||||
const float cp2y = cp1y + (i.y2 - lastY) / 3.0f;
|
||||
|
||||
writeXY (cp1x, cp1y);
|
||||
writeXY (cp2x, cp2y);
|
||||
writeXY (i.x2, i.y2);
|
||||
out << "ct ";
|
||||
lastX = i.x2;
|
||||
lastY = i.y2;
|
||||
}
|
||||
break;
|
||||
|
||||
case Path::Iterator::cubicTo:
|
||||
writeXY (i.x1, i.y1);
|
||||
writeXY (i.x2, i.y2);
|
||||
writeXY (i.x3, i.y3);
|
||||
out << "ct ";
|
||||
lastX = i.x3;
|
||||
lastY = i.y3;
|
||||
break;
|
||||
|
||||
case Path::Iterator::closePath:
|
||||
out << "cp ";
|
||||
break;
|
||||
|
||||
default:
|
||||
jassertfalse;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out << '\n';
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::writeTransform (const AffineTransform& trans) const
|
||||
{
|
||||
out << "[ "
|
||||
<< trans.mat00 << ' '
|
||||
<< trans.mat10 << ' '
|
||||
<< trans.mat01 << ' '
|
||||
<< trans.mat11 << ' '
|
||||
<< trans.mat02 << ' '
|
||||
<< trans.mat12 << " ] concat ";
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void LowLevelGraphicsPostScriptRenderer::setFill (const FillType& fillType)
|
||||
{
|
||||
stateStack.getLast()->fillType = fillType;
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::setOpacity (float /*opacity*/)
|
||||
{
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::setInterpolationQuality (Graphics::ResamplingQuality /*quality*/)
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void LowLevelGraphicsPostScriptRenderer::fillRect (const Rectangle<int>& r, const bool /*replaceExistingContents*/)
|
||||
{
|
||||
fillRect (r.toFloat());
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::fillRect (const Rectangle<float>& r)
|
||||
{
|
||||
if (stateStack.getLast()->fillType.isColour())
|
||||
{
|
||||
writeClip();
|
||||
writeColour (stateStack.getLast()->fillType.colour);
|
||||
|
||||
auto r2 = r.translated ((float) stateStack.getLast()->xOffset,
|
||||
(float) stateStack.getLast()->yOffset);
|
||||
|
||||
out << r2.getX() << ' ' << -r2.getBottom() << ' ' << r2.getWidth() << ' ' << r2.getHeight() << " rectfill\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
Path p;
|
||||
p.addRectangle (r);
|
||||
fillPath (p, AffineTransform());
|
||||
}
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::fillRectList (const RectangleList<float>& list)
|
||||
{
|
||||
fillPath (list.toPath(), AffineTransform());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void LowLevelGraphicsPostScriptRenderer::fillPath (const Path& path, const AffineTransform& t)
|
||||
{
|
||||
if (stateStack.getLast()->fillType.isColour())
|
||||
{
|
||||
writeClip();
|
||||
|
||||
Path p (path);
|
||||
p.applyTransform (t.translated ((float) stateStack.getLast()->xOffset,
|
||||
(float) stateStack.getLast()->yOffset));
|
||||
writePath (p);
|
||||
|
||||
writeColour (stateStack.getLast()->fillType.colour);
|
||||
|
||||
out << "fill\n";
|
||||
}
|
||||
else if (stateStack.getLast()->fillType.isGradient())
|
||||
{
|
||||
// this doesn't work correctly yet - it could be improved to handle solid gradients, but
|
||||
// postscript can't do semi-transparent ones.
|
||||
notPossibleInPostscriptAssert; // you can disable this warning by setting the WARN_ABOUT_NON_POSTSCRIPT_OPERATIONS flag at the top of this file
|
||||
|
||||
writeClip();
|
||||
out << "gsave ";
|
||||
|
||||
{
|
||||
Path p (path);
|
||||
p.applyTransform (t.translated ((float) stateStack.getLast()->xOffset, (float) stateStack.getLast()->yOffset));
|
||||
writePath (p);
|
||||
out << "clip\n";
|
||||
}
|
||||
|
||||
auto bounds = stateStack.getLast()->clip.getBounds();
|
||||
|
||||
// ideally this would draw lots of lines or ellipses to approximate the gradient, but for the
|
||||
// time-being, this just fills it with the average colour..
|
||||
writeColour (stateStack.getLast()->fillType.gradient->getColourAtPosition (0.5f));
|
||||
out << bounds.getX() << ' ' << -bounds.getBottom() << ' ' << bounds.getWidth() << ' ' << bounds.getHeight() << " rectfill\n";
|
||||
|
||||
out << "grestore\n";
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void LowLevelGraphicsPostScriptRenderer::writeImage (const Image& im,
|
||||
const int sx, const int sy,
|
||||
const int maxW, const int maxH) const
|
||||
{
|
||||
out << "{<\n";
|
||||
|
||||
const int w = jmin (maxW, im.getWidth());
|
||||
const int h = jmin (maxH, im.getHeight());
|
||||
|
||||
int charsOnLine = 0;
|
||||
const Image::BitmapData srcData (im, 0, 0, w, h);
|
||||
Colour pixel;
|
||||
|
||||
for (int y = h; --y >= 0;)
|
||||
{
|
||||
for (int x = 0; x < w; ++x)
|
||||
{
|
||||
const uint8* pixelData = srcData.getPixelPointer (x, y);
|
||||
|
||||
if (x >= sx && y >= sy)
|
||||
{
|
||||
if (im.isARGB())
|
||||
{
|
||||
PixelARGB p (*(const PixelARGB*) pixelData);
|
||||
p.unpremultiply();
|
||||
pixel = Colours::white.overlaidWith (Colour (p));
|
||||
}
|
||||
else if (im.isRGB())
|
||||
{
|
||||
pixel = Colour (*((const PixelRGB*) pixelData));
|
||||
}
|
||||
else
|
||||
{
|
||||
pixel = Colour ((uint8) 0, (uint8) 0, (uint8) 0, *pixelData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pixel = Colours::transparentWhite;
|
||||
}
|
||||
|
||||
const uint8 pixelValues[3] = { pixel.getRed(), pixel.getGreen(), pixel.getBlue() };
|
||||
|
||||
out << String::toHexString (pixelValues, 3, 0);
|
||||
charsOnLine += 3;
|
||||
|
||||
if (charsOnLine > 100)
|
||||
{
|
||||
out << '\n';
|
||||
charsOnLine = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out << "\n>}\n";
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::drawImage (const Image& sourceImage, const AffineTransform& transform)
|
||||
{
|
||||
const int w = sourceImage.getWidth();
|
||||
const int h = sourceImage.getHeight();
|
||||
|
||||
writeClip();
|
||||
|
||||
out << "gsave ";
|
||||
writeTransform (transform.translated ((float) stateStack.getLast()->xOffset, (float) stateStack.getLast()->yOffset)
|
||||
.scaled (1.0f, -1.0f));
|
||||
|
||||
RectangleList<int> imageClip;
|
||||
sourceImage.createSolidAreaMask (imageClip, 0.5f);
|
||||
|
||||
out << "newpath ";
|
||||
int itemsOnLine = 0;
|
||||
|
||||
for (auto& i : imageClip)
|
||||
{
|
||||
if (++itemsOnLine == 6)
|
||||
{
|
||||
out << '\n';
|
||||
itemsOnLine = 0;
|
||||
}
|
||||
|
||||
out << i.getX() << ' ' << i.getY() << ' ' << i.getWidth() << ' ' << i.getHeight() << " pr ";
|
||||
}
|
||||
|
||||
out << " clip newpath\n";
|
||||
|
||||
out << w << ' ' << h << " scale\n";
|
||||
out << w << ' ' << h << " 8 [" << w << " 0 0 -" << h << ' ' << (int) 0 << ' ' << h << " ]\n";
|
||||
|
||||
writeImage (sourceImage, 0, 0, w, h);
|
||||
|
||||
out << "false 3 colorimage grestore\n";
|
||||
needToClip = true;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
void LowLevelGraphicsPostScriptRenderer::drawLine (const Line <float>& line)
|
||||
{
|
||||
Path p;
|
||||
p.addLineSegment (line, 1.0f);
|
||||
fillPath (p, AffineTransform());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void LowLevelGraphicsPostScriptRenderer::setFont (const Font& newFont)
|
||||
{
|
||||
stateStack.getLast()->font = newFont;
|
||||
}
|
||||
|
||||
const Font& LowLevelGraphicsPostScriptRenderer::getFont()
|
||||
{
|
||||
return stateStack.getLast()->font;
|
||||
}
|
||||
|
||||
void LowLevelGraphicsPostScriptRenderer::drawGlyph (int glyphNumber, const AffineTransform& transform)
|
||||
{
|
||||
Path p;
|
||||
Font& font = stateStack.getLast()->font;
|
||||
font.getTypefacePtr()->getOutlineForGlyph (glyphNumber, p);
|
||||
fillPath (p, AffineTransform::scale (font.getHeight() * font.getHorizontalScale(), font.getHeight()).followedBy (transform));
|
||||
}
|
||||
|
||||
} // namespace juce
|
119
deps/juce/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h
vendored
Normal file
119
deps/juce/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
An implementation of LowLevelGraphicsContext that turns the drawing operations
|
||||
into a PostScript document.
|
||||
|
||||
@tags{Graphics}
|
||||
*/
|
||||
class JUCE_API LowLevelGraphicsPostScriptRenderer : public LowLevelGraphicsContext
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
LowLevelGraphicsPostScriptRenderer (OutputStream& resultingPostScript,
|
||||
const String& documentTitle,
|
||||
int totalWidth,
|
||||
int totalHeight);
|
||||
|
||||
~LowLevelGraphicsPostScriptRenderer() override;
|
||||
|
||||
//==============================================================================
|
||||
bool isVectorDevice() const override;
|
||||
void setOrigin (Point<int>) override;
|
||||
void addTransform (const AffineTransform&) override;
|
||||
float getPhysicalPixelScaleFactor() override;
|
||||
|
||||
bool clipToRectangle (const Rectangle<int>&) override;
|
||||
bool clipToRectangleList (const RectangleList<int>&) override;
|
||||
void excludeClipRectangle (const Rectangle<int>&) override;
|
||||
void clipToPath (const Path&, const AffineTransform&) override;
|
||||
void clipToImageAlpha (const Image&, const AffineTransform&) override;
|
||||
|
||||
void saveState() override;
|
||||
void restoreState() override;
|
||||
|
||||
void beginTransparencyLayer (float) override;
|
||||
void endTransparencyLayer() override;
|
||||
|
||||
bool clipRegionIntersects (const Rectangle<int>&) override;
|
||||
Rectangle<int> getClipBounds() const override;
|
||||
bool isClipEmpty() const override;
|
||||
|
||||
//==============================================================================
|
||||
void setFill (const FillType&) override;
|
||||
void setOpacity (float) override;
|
||||
void setInterpolationQuality (Graphics::ResamplingQuality) override;
|
||||
|
||||
//==============================================================================
|
||||
void fillRect (const Rectangle<int>&, bool replaceExistingContents) override;
|
||||
void fillRect (const Rectangle<float>&) override;
|
||||
void fillRectList (const RectangleList<float>&) override;
|
||||
void fillPath (const Path&, const AffineTransform&) override;
|
||||
void drawImage (const Image&, const AffineTransform&) override;
|
||||
void drawLine (const Line <float>&) override;
|
||||
|
||||
//==============================================================================
|
||||
const Font& getFont() override;
|
||||
void setFont (const Font&) override;
|
||||
void drawGlyph (int glyphNumber, const AffineTransform&) override;
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
OutputStream& out;
|
||||
int totalWidth, totalHeight;
|
||||
bool needToClip;
|
||||
Colour lastColour;
|
||||
|
||||
/** Describes a saved state */
|
||||
struct SavedState
|
||||
{
|
||||
SavedState();
|
||||
SavedState& operator= (const SavedState&) = delete;
|
||||
~SavedState();
|
||||
|
||||
RectangleList<int> clip;
|
||||
int xOffset, yOffset;
|
||||
FillType fillType;
|
||||
Font font;
|
||||
};
|
||||
|
||||
OwnedArray<SavedState> stateStack;
|
||||
|
||||
void writeClip();
|
||||
void writeColour (Colour colour);
|
||||
void writePath (const Path&) const;
|
||||
void writeXY (float x, float y) const;
|
||||
void writeTransform (const AffineTransform&) const;
|
||||
void writeImage (const Image&, int sx, int sy, int maxW, int maxH) const;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LowLevelGraphicsPostScriptRenderer)
|
||||
};
|
||||
|
||||
} // namespace juce
|
44
deps/juce/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp
vendored
Normal file
44
deps/juce/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (const Image& image)
|
||||
: RenderingHelpers::StackBasedLowLevelGraphicsContext<RenderingHelpers::SoftwareRendererSavedState>
|
||||
(new RenderingHelpers::SoftwareRendererSavedState (image, image.getBounds()))
|
||||
{
|
||||
}
|
||||
|
||||
LowLevelGraphicsSoftwareRenderer::LowLevelGraphicsSoftwareRenderer (const Image& image, Point<int> origin,
|
||||
const RectangleList<int>& initialClip)
|
||||
: RenderingHelpers::StackBasedLowLevelGraphicsContext<RenderingHelpers::SoftwareRendererSavedState>
|
||||
(new RenderingHelpers::SoftwareRendererSavedState (image, initialClip, origin))
|
||||
{
|
||||
}
|
||||
|
||||
LowLevelGraphicsSoftwareRenderer::~LowLevelGraphicsSoftwareRenderer() {}
|
||||
|
||||
} // namespace juce
|
57
deps/juce/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h
vendored
Normal file
57
deps/juce/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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 lowest-common-denominator implementation of LowLevelGraphicsContext that does all
|
||||
its rendering in memory.
|
||||
|
||||
User code is not supposed to create instances of this class directly - do all your
|
||||
rendering via the Graphics class instead.
|
||||
|
||||
@tags{Graphics}
|
||||
*/
|
||||
class JUCE_API LowLevelGraphicsSoftwareRenderer : public RenderingHelpers::StackBasedLowLevelGraphicsContext<RenderingHelpers::SoftwareRendererSavedState>
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a context to render into an image. */
|
||||
LowLevelGraphicsSoftwareRenderer (const Image& imageToRenderOnto);
|
||||
|
||||
/** Creates a context to render into a clipped subsection of an image. */
|
||||
LowLevelGraphicsSoftwareRenderer (const Image& imageToRenderOnto, Point<int> origin,
|
||||
const RectangleList<int>& initialClip);
|
||||
|
||||
/** Destructor. */
|
||||
~LowLevelGraphicsSoftwareRenderer() override;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LowLevelGraphicsSoftwareRenderer)
|
||||
};
|
||||
|
||||
} // namespace juce
|
Reference in New Issue
Block a user