| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2015 - ROLI Ltd.
 - 
 -    Permission is granted to use this software under the terms of either:
 -    a) the GPL v2 (or any later version)
 -    b) the Affero GPL v3
 - 
 -    Details of these licenses can be found at: www.gnu.org/licenses
 - 
 -    JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
 -    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 -    A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 - 
 -    ------------------------------------------------------------------------------
 - 
 -    To release a closed-source product which uses JUCE, commercial licenses are
 -    available: visit www.juce.com for more information.
 - 
 -   ==============================================================================
 - */
 - 
 - // 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 (const Rectangle<int>* i = stateStack.getLast()->clip.begin(), * const e = stateStack.getLast()->clip.end(); i != e; ++i)
 -         {
 -             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 (const Rectangle<int>* i = imageClip.begin(), * const e = imageClip.end(); i != e; ++i)
 -     {
 -         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));
 - }
 
 
  |