fix macOS build (following Projucer changes made in Windows, which removed /Applications/JUCE/modules from its headers). move JUCE headers under source control, so that Windows and macOS can both build against same version of JUCE. remove AUv3 target (I think it's an iOS thing, so it will never work with this macOS fluidsynth dylib).
This commit is contained in:
@ -0,0 +1,540 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2017 - ROLI Ltd.
|
||||
|
||||
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 5 End-User License
|
||||
Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
|
||||
27th April 2017).
|
||||
|
||||
End User License Agreement: www.juce.com/juce-5-licence
|
||||
Privacy Policy: www.juce.com/juce-5-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 / totalWidth_), (750.0f / totalHeight));
|
||||
|
||||
out << "%!PS-Adobe-3.0 EPSF-3.0"
|
||||
"\n%%BoundingBox: 0 0 600 824"
|
||||
"\n%%Pages: 0"
|
||||
"\n%%Creator: ROLI Ltd. 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);
|
||||
|
||||
Rectangle<float> 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";
|
||||
}
|
||||
|
||||
const Rectangle<int> 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.getTypeface()->getOutlineForGlyph (glyphNumber, p);
|
||||
fillPath (p, AffineTransform::scale (font.getHeight() * font.getHorizontalScale(), font.getHeight()).followedBy (transform));
|
||||
}
|
||||
|
||||
} // namespace juce
|
Reference in New Issue
Block a user