text:
/*
  ==============================================================================

   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
{

//==============================================================================
/**
    A Pre-formatted piece of text, which may contain multiple fonts and colours.

    A TextLayout is created from an AttributedString, and once created can be
    quickly drawn into a Graphics context.

    @see AttributedString
*/
class JUCE_API  TextLayout  final
{
public:
    /** Creates an empty layout.
        Having created a TextLayout, you can populate it using createLayout() or
        createLayoutWithBalancedLineLengths().
    */
    TextLayout();
    TextLayout (const TextLayout&);
    TextLayout& operator= (const TextLayout&);
    TextLayout (TextLayout&&) noexcept;
    TextLayout& operator= (TextLayout&&) noexcept;

    /** Destructor. */
    ~TextLayout();

    //==============================================================================
    /** Creates a layout from the given attributed string.
        This will replace any data that is currently stored in the layout.
    */
    void createLayout (const AttributedString&, float maxWidth);

    /** Creates a layout from the given attributed string, given some size constraints.
        This will replace any data that is currently stored in the layout.
    */
    void createLayout (const AttributedString&, float maxWidth, float maxHeight);

    /** Creates a layout, attempting to choose a width which results in lines
        of a similar length.

        This will be slower than the normal createLayout method, but produces a
        tidier result.
    */
    void createLayoutWithBalancedLineLengths (const AttributedString&, float maxWidth);

    /** Creates a layout, attempting to choose a width which results in lines
        of a similar length.

        This will be slower than the normal createLayout method, but produces a
        tidier result.
    */
    void createLayoutWithBalancedLineLengths (const AttributedString&, float maxWidth, float maxHeight);

    /** Draws the layout within the specified area.
        The position of the text within the rectangle is controlled by the justification
        flags set in the original AttributedString that was used to create this layout.
    */
    void draw (Graphics&, Rectangle<float> area) const;

    //==============================================================================
    /** A positioned glyph. */
    class JUCE_API  Glyph
    {
    public:
        Glyph (int glyphCode, Point<float> anchor, float width) noexcept;
        Glyph (const Glyph&) noexcept;
        Glyph& operator= (const Glyph&) noexcept;
        ~Glyph() noexcept;

        /** The code number of this glyph. */
        int glyphCode;

        /** The glyph's anchor point - this is relative to the line's origin.
            @see TextLayout::Line::lineOrigin
        */
        Point<float> anchor;

        float width;

    private:
        JUCE_LEAK_DETECTOR (Glyph)
    };

    //==============================================================================
    /** A sequence of glyphs with a common font and colour. */
    class JUCE_API  Run
    {
    public:
        Run() noexcept;
        Run (const Run&);
        Run (Range<int> stringRange, int numGlyphsToPreallocate);
        ~Run() noexcept;

        Font font;              /**< The run's font. */
        Colour colour;          /**< The run's colour. */
        Array<Glyph> glyphs;    /**< The glyphs in this run. */
        Range<int> stringRange; /**< The character range that this run represents in the
                                     original string that was used to create it. */
    private:
        Run& operator= (const Run&);
        JUCE_LEAK_DETECTOR (Run)
    };

    //==============================================================================
    /** A line containing a sequence of glyph-runs. */
    class JUCE_API  Line
    {
    public:
        Line() noexcept;
        Line (const Line&);
        Line (Range<int> stringRange, Point<float> lineOrigin,
              float ascent, float descent, float leading, int numRunsToPreallocate);
        ~Line() noexcept;

        /** Returns the X position range which contains all the glyphs in this line. */
        Range<float> getLineBoundsX() const noexcept;

        /** Returns the Y position range which contains all the glyphs in this line. */
        Range<float> getLineBoundsY() const noexcept;

        /** Returns the smallest rectangle which contains all the glyphs in this line. */
        Rectangle<float> getLineBounds() const noexcept;

        OwnedArray<Run> runs;           /**< The glyph-runs in this line. */
        Range<int> stringRange;         /**< The character range that this line represents in the
                                             original string that was used to create it. */
        Point<float> lineOrigin;        /**< The line's baseline origin. */
        float ascent, descent, leading;

    private:
        Line& operator= (const Line&);
        JUCE_LEAK_DETECTOR (Line)
    };

    //==============================================================================
    /** Returns the maximum width of the content. */
    float getWidth() const noexcept     { return width; }

    /** Returns the maximum height of the content. */
    float getHeight() const noexcept    { return height; }

    /** Returns the number of lines in the layout. */
    int getNumLines() const noexcept    { return lines.size(); }

    /** Returns one of the lines. */
    Line& getLine (int index) const;

    /** Adds a line to the layout. The layout will take ownership of this line object
        and will delete it when it is no longer needed. */
    void addLine (Line*);

    /** Pre-allocates space for the specified number of lines. */
    void ensureStorageAllocated (int numLinesNeeded);

private:
    OwnedArray<Line> lines;
    float width, height;
    Justification justification;

    void createStandardLayout (const AttributedString&);
    bool createNativeLayout (const AttributedString&);
    void recalculateSize();

    JUCE_LEAK_DETECTOR (TextLayout)
};

} // namespace juce


text:
/*
  ==============================================================================

   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
{

//==============================================================================
/**
    Represents a type of justification to be used when positioning graphical items.

    e.g. it indicates whether something should be placed top-left, top-right,
    centred, etc.

    It is used in various places wherever this kind of information is needed.
*/
class Justification
{
public:
    //==============================================================================
    /** Creates a Justification object using a combination of flags from the Flags enum. */
    Justification (int justificationFlags) noexcept   : flags (justificationFlags) {}

    /** Creates a copy of another Justification object. */
    Justification (const Justification& other) noexcept   : flags (other.flags) {}

    /** Copies another Justification object. */
    Justification& operator= (const Justification& other) noexcept
    {
        flags = other.flags;
        return *this;
    }

    bool operator== (const Justification& other) const noexcept     { return flags == other.flags; }
    bool operator!= (const Justification& other) const noexcept     { return flags != other.flags; }

    //==============================================================================
    /** Returns the raw flags that are set for this Justification object. */
    inline int getFlags() const noexcept                        { return flags; }

    /** Tests a set of flags for this object.
        @returns true if any of the flags passed in are set on this object.
    */
    inline bool testFlags (int flagsToTest) const noexcept      { return (flags & flagsToTest) != 0; }

    /** Returns just the flags from this object that deal with vertical layout. */
    int getOnlyVerticalFlags() const noexcept                   { return flags & (top | bottom | verticallyCentred); }

    /** Returns just the flags from this object that deal with horizontal layout. */
    int getOnlyHorizontalFlags() const noexcept                 { return flags & (left | right | horizontallyCentred | horizontallyJustified); }

    //==============================================================================
    /** Adjusts the position of a rectangle to fit it into a space.

        The (x, y) position of the rectangle will be updated to position it inside the
        given space according to the justification flags.
    */
    template <typename ValueType>
    void applyToRectangle (ValueType& x, ValueType& y, ValueType w, ValueType h,
                           ValueType spaceX, ValueType spaceY, ValueType spaceW, ValueType spaceH) const noexcept
    {
        x = spaceX;
        if ((flags & horizontallyCentred) != 0)     x += (spaceW - w) / (ValueType) 2;
        else if ((flags & right) != 0)              x += spaceW - w;

        y = spaceY;
        if ((flags & verticallyCentred) != 0)       y += (spaceH - h) / (ValueType) 2;
        else if ((flags & bottom) != 0)             y += spaceH - h;
    }

    /** Returns the new position of a rectangle that has been justified to fit within a given space.
    */
    template <typename ValueType>
    const Rectangle<ValueType> appliedToRectangle (const Rectangle<ValueType>& areaToAdjust,
                                                   const Rectangle<ValueType>& targetSpace) const noexcept
    {
        ValueType x = areaToAdjust.getX(), y = areaToAdjust.getY();
        applyToRectangle (x, y, areaToAdjust.getWidth(), areaToAdjust.getHeight(),
                          targetSpace.getX(), targetSpace.getY(), targetSpace.getWidth(), targetSpace.getHeight());
        return areaToAdjust.withPosition (x, y);
    }

    //==============================================================================
    /** Flag values that can be combined and used in the constructor. */
    enum Flags
    {
        //==============================================================================
        /** Indicates that the item should be aligned against the left edge of the available space. */
        left                            = 1,

        /** Indicates that the item should be aligned against the right edge of the available space. */
        right                           = 2,

        /** Indicates that the item should be placed in the centre between the left and right
            sides of the available space. */
        horizontallyCentred             = 4,

        //==============================================================================
        /** Indicates that the item should be aligned against the top edge of the available space. */
        top                             = 8,

        /** Indicates that the item should be aligned against the bottom edge of the available space. */
        bottom                          = 16,

        /** Indicates that the item should be placed in the centre between the top and bottom
            sides of the available space. */
        verticallyCentred               = 32,

        //==============================================================================
        /** Indicates that lines of text should be spread out to fill the maximum width
            available, so that both margins are aligned vertically.
        */
        horizontallyJustified           = 64,

        //==============================================================================
        /** Indicates that the item should be centred vertically and horizontally.
            This is equivalent to (horizontallyCentred | verticallyCentred)
        */
        centred                         = 36,

        /** Indicates that the item should be centred vertically but placed on the left hand side.
            This is equivalent to (left | verticallyCentred)
        */
        centredLeft                     = 33,

        /** Indicates that the item should be centred vertically but placed on the right hand side.
            This is equivalent to (right | verticallyCentred)
        */
        centredRight                    = 34,

        /** Indicates that the item should be centred horizontally and placed at the top.
            This is equivalent to (horizontallyCentred | top)
        */
        centredTop                      = 12,

        /** Indicates that the item should be centred horizontally and placed at the bottom.
            This is equivalent to (horizontallyCentred | bottom)
        */
        centredBottom                   = 20,

        /** Indicates that the item should be placed in the top-left corner.
            This is equivalent to (left | top)
        */
        topLeft                         = 9,

        /** Indicates that the item should be placed in the top-right corner.
            This is equivalent to (right | top)
        */
        topRight                        = 10,

        /** Indicates that the item should be placed in the bottom-left corner.
            This is equivalent to (left | bottom)
        */
        bottomLeft                      = 17,

        /** Indicates that the item should be placed in the bottom-left corner.
            This is equivalent to (right | bottom)
        */
        bottomRight                     = 18
    };

private:
    //==============================================================================
    int flags;
};

} // namespace juce

repo_name: fedden/RenderMan

mime_type: text/x-c++


text:
/*
  ==============================================================================

   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
{

RectanglePlacement::RectanglePlacement (const RectanglePlacement& other) noexcept
    : flags (other.flags)
{
}

RectanglePlacement& RectanglePlacement::operator= (const RectanglePlacement& other) noexcept
{
    flags = other.flags;
    return *this;
}

bool RectanglePlacement::operator== (const RectanglePlacement& other) const noexcept
{
    return flags == other.flags;
}

bool RectanglePlacement::operator!= (const RectanglePlacement& other) const noexcept
{
    return flags != other.flags;
}

void RectanglePlacement::applyTo (double& x, double& y, double& w, double& h,
                                  const double dx, const double dy, const double dw, const double dh) const noexcept
{
    if (w == 0.0 || h == 0.0)
        return;

    if ((flags & stretchToFit) != 0)
    {
        x = dx;
        y = dy;
        w = dw;
        h = dh;
    }
    else
    {
        double scale = (flags & fillDestination) != 0 ? jmax (dw / w, dh / h)
                                                      : jmin (dw / w, dh / h);

        if ((flags & onlyReduceInSize) != 0)
            scale = jmin (scale, 1.0);

        if ((flags & onlyIncreaseInSize) != 0)
            scale = jmax (scale, 1.0);

        w *= scale;
        h *= scale;

        if ((flags & xLeft) != 0)
            x = dx;
        else if ((flags & xRight) != 0)
            x = dx + dw - w;
        else
            x = dx + (dw - w) * 0.5;

        if ((flags & yTop) != 0)
            y = dy;
        else if ((flags & yBottom) != 0)
            y = dy + dh - h;
        else
            y = dy + (dh - h) * 0.5;
    }
}

AffineTransform RectanglePlacement::getTransformToFit (const Rectangle<float>& source, const Rectangle<float>& destination) const noexcept
{
    if (source.isEmpty())
        return AffineTransform();

    float newX = destination.getX();
    float newY = destination.getY();

    float scaleX = destination.getWidth() / source.getWidth();
    float scaleY = destination.getHeight() / source.getHeight();

    if ((flags & stretchToFit) == 0)
    {
        scaleX = (flags & fillDestination) != 0 ? jmax (scaleX, scaleY)
                                                : jmin (scaleX, scaleY);

        if ((flags & onlyReduceInSize) != 0)
            scaleX = jmin (scaleX, 1.0f);

        if ((flags & onlyIncreaseInSize) != 0)
            scaleX = jmax (scaleX, 1.0f);

        scaleY = scaleX;

        if ((flags & xRight) != 0)
            newX += destination.getWidth() - source.getWidth() * scaleX;             // right
        else if ((flags & xLeft) == 0)
            newX += (destination.getWidth() - source.getWidth() * scaleX) / 2.0f;    // centre

        if ((flags & yBottom) != 0)
            newY += destination.getHeight() - source.getHeight() * scaleX;             // bottom
        else if ((flags & yTop) == 0)
            newY += (destination.getHeight() - source.getHeight() * scaleX) / 2.0f;    // centre
    }

    return AffineTransform::translation (-source.getX(), -source.getY())
                .scaled (scaleX, scaleY)
                .translated (newX, newY);
}

} // namespace juce


text:
/*
  ==============================================================================

   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
{

//==============================================================================
/**
    Defines the method used to position some kind of rectangular object within
    a rectangular viewport.

    Although similar to Justification, this is more specific, and has some extra
    options.
*/
class JUCE_API  RectanglePlacement
{
public:
    //==============================================================================
    /** Creates a RectanglePlacement object using a combination of flags from the Flags enum. */
    inline RectanglePlacement (int placementFlags) noexcept  : flags (placementFlags) {}

    /** Creates a default RectanglePlacement object, which is equivalent to using the 'centred' flag. */
    inline RectanglePlacement() noexcept                     : flags (centred) {}

    /** Creates a copy of another RectanglePlacement object. */
    RectanglePlacement (const RectanglePlacement&) noexcept;

    /** Copies another RectanglePlacement object. */
    RectanglePlacement& operator= (const RectanglePlacement&) noexcept;

    bool operator== (const RectanglePlacement&) const noexcept;
    bool operator!= (const RectanglePlacement&) const noexcept;

    //==============================================================================
    /** Flag values that can be combined and used in the constructor. */
    enum Flags
    {
        //==============================================================================
        /** Indicates that the source rectangle's left edge should be aligned with the left edge of the target rectangle. */
        xLeft                                   = 1,

        /** Indicates that the source rectangle's right edge should be aligned with the right edge of the target rectangle. */
        xRight                                  = 2,

        /** Indicates that the source should be placed in the centre between the left and right
            sides of the available space. */
        xMid                                    = 4,

        //==============================================================================
        /** Indicates that the source's top edge should be aligned with the top edge of the
            destination rectangle. */
        yTop                                    = 8,

        /** Indicates that the source's bottom edge should be aligned with the bottom edge of the
            destination rectangle. */
        yBottom                                 = 16,

        /** Indicates that the source should be placed in the centre between the top and bottom
            sides of the available space. */
        yMid                                    = 32,

        //==============================================================================
        /** If this flag is set, then the source rectangle will be resized to completely fill
            the destination rectangle, and all other flags are ignored.
        */
        stretchToFit                            = 64,

        //==============================================================================
        /** If this flag is set, then the source rectangle will be resized so that it is the
            minimum size to completely fill the destination rectangle, without changing its
            aspect ratio. This means that some of the source rectangle may fall outside
            the destination.

            If this flag is not set, the source will be given the maximum size at which none
            of it falls outside the destination rectangle.
        */
        fillDestination                         = 128,

        /** Indicates that the source rectangle can be reduced in size if required, but should
            never be made larger than its original size.
        */
        onlyReduceInSize                        = 256,

        /** Indicates that the source rectangle can be enlarged if required, but should
            never be made smaller than its original size.
        */
        onlyIncreaseInSize                      = 512,

        /** Indicates that the source rectangle's size should be left unchanged.
        */
        doNotResize                             = (onlyIncreaseInSize | onlyReduceInSize),

        //==============================================================================
        /** A shorthand value that is equivalent to (xMid | yMid). */
        centred                                 = 4 + 32
    };

    //==============================================================================
    /** Returns the raw flags that are set for this object. */
    inline int getFlags() const noexcept                            { return flags; }

    /** Tests a set of flags for this object.

        @returns true if any of the flags passed in are set on this object.
    */
    inline bool testFlags (int flagsToTest) const noexcept          { return (flags & flagsToTest) != 0; }

    //==============================================================================
    /** Adjusts the position and size of a rectangle to fit it into a space.

        The source rectangle coordinates will be adjusted so that they fit into
        the destination rectangle based on this object's flags.
    */
    void applyTo (double& sourceX,
                  double& sourceY,
                  double& sourceW,
                  double& sourceH,
                  double destinationX,
                  double destinationY,
                  double destinationW,
                  double destinationH) const noexcept;

    /** Returns the rectangle that should be used to fit the given source rectangle
        into the destination rectangle using the current flags.
    */
    template <typename ValueType>
    Rectangle<ValueType> appliedTo (const Rectangle<ValueType>& source,
                                    const Rectangle<ValueType>& destination) const noexcept
    {
        double x = source.getX(), y = source.getY(), w = source.getWidth(), h = source.getHeight();
        applyTo (x, y, w, h, static_cast<double> (destination.getX()), static_cast<double> (destination.getY()),
                 static_cast<double> (destination.getWidth()), static_cast<double> (destination.getHeight()));
        return Rectangle<ValueType> (static_cast<ValueType> (x), static_cast<ValueType> (y),
                                     static_cast<ValueType> (w), static_cast<ValueType> (h));
    }

    /** Returns the transform that should be applied to these source coordinates to fit them
        into the destination rectangle using the current flags.
    */
    AffineTransform getTransformToFit (const Rectangle<float>& source,
                                       const Rectangle<float>& destination) const noexcept;

private:
    //==============================================================================
    int flags;
};

} // namespace juce


text:
/*
  ==============================================================================

   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
{

FillType::FillType() noexcept
    : colour (0xff000000)
{
}

FillType::FillType (Colour c) noexcept
    : colour (c)
{
}

FillType::FillType (const ColourGradient& gradient_)
    : colour (0xff000000), gradient (new ColourGradient (gradient_))
{
}

FillType::FillType (const Image& image_, const AffineTransform& transform_) noexcept
    : colour (0xff000000), image (image_), transform (transform_)
{
}

FillType::FillType (const FillType& other)
    : colour (other.colour),
      gradient (other.gradient.createCopy()),
      image (other.image),
      transform (other.transform)
{
}

FillType& FillType::operator= (const FillType& other)
{
    if (this != &other)
    {
        colour = other.colour;
        gradient = other.gradient.createCopy();
        image = other.image;
        transform = other.transform;
    }

    return *this;
}

FillType::FillType (FillType&& other) noexcept
    : colour (other.colour),
      gradient (other.gradient.release()),
      image (static_cast<Image&&> (other.image)),
      transform (other.transform)
{
}

FillType& FillType::operator= (FillType&& other) noexcept
{
    jassert (this != &other); // hopefully the compiler should make this situation impossible!

    colour = other.colour;
    gradient = other.gradient.release();
    image = static_cast<Image&&> (other.image);
    transform = other.transform;
    return *this;
}

FillType::~FillType() noexcept
{
}

bool FillType::operator== (const FillType& other) const
{
    return colour == other.colour && image == other.image
            && transform == other.transform
            && (gradient == other.gradient
                 || (gradient != nullptr && other.gradient != nullptr && *gradient == *other.gradient));
}

bool FillType::operator!= (const FillType& other) const
{
    return ! operator== (other);
}

void FillType::setColour (Colour newColour) noexcept
{
    gradient = nullptr;
    image = Image();
    colour = newColour;
}

void FillType::setGradient (const ColourGradient& newGradient)
{
    if (gradient != nullptr)
    {
        *gradient = newGradient;
    }
    else
    {
        image = Image();
        gradient = new ColourGradient (newGradient);
        colour = Colours::black;
    }
}

void FillType::setTiledImage (const Image& image_, const AffineTransform& transform_) noexcept
{
    gradient = nullptr;
    image = image_;
    transform = transform_;
    colour = Colours::black;
}

void FillType::setOpacity (const float newOpacity) noexcept
{
    colour = colour.withAlpha (newOpacity);
}

bool FillType::isInvisible() const noexcept
{
    return colour.isTransparent() || (gradient != nullptr && gradient->isInvisible());
}

FillType FillType::transformed (const AffineTransform& t) const
{
    FillType f (*this);
    f.transform = f.transform.followedBy (t);
    return f;
}

} // namespace juce


text:
/*
  ==============================================================================

   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
{

//==============================================================================
/**
    Represents a colour or fill pattern to use for rendering paths.

    This is used by the Graphics and DrawablePath classes as a way to encapsulate
    a brush type. It can either be a solid colour, a gradient, or a tiled image.

    @see Graphics::setFillType, DrawablePath::setFill
*/
class JUCE_API  FillType  final
{
public:
    //==============================================================================
    /** Creates a default fill type, of solid black. */
    FillType() noexcept;

    /** Creates a fill type of a solid colour.
        @see setColour
    */
    FillType (Colour colour) noexcept;

    /** Creates a gradient fill type.
        @see setGradient
    */
    FillType (const ColourGradient& gradient);

    /** Creates a tiled image fill type. The transform allows you to set the scaling, offset
        and rotation of the pattern.
        @see setTiledImage
    */
    FillType (const Image& image, const AffineTransform& transform) noexcept;

    /** Creates a copy of another FillType. */
    FillType (const FillType&);

    /** Makes a copy of another FillType. */
    FillType& operator= (const FillType&);

    /** Move constructor */
    FillType (FillType&&) noexcept;

    /** Move assignment operator */
    FillType& operator= (FillType&&) noexcept;

    /** Destructor. */
    ~FillType() noexcept;

    //==============================================================================
    /** Returns true if this is a solid colour fill, and not a gradient or image. */
    bool isColour() const noexcept          { return gradient == nullptr && image.isNull(); }

    /** Returns true if this is a gradient fill. */
    bool isGradient() const noexcept        { return gradient != nullptr; }

    /** Returns true if this is a tiled image pattern fill. */
    bool isTiledImage() const noexcept      { return image.isValid(); }

    /** Turns this object into a solid colour fill.
        If the object was an image or gradient, those fields will no longer be valid. */
    void setColour (Colour newColour) noexcept;

    /** Turns this object into a gradient fill. */
    void setGradient (const ColourGradient& newGradient);

    /** Turns this object into a tiled image fill type. The transform allows you to set
        the scaling, offset and rotation of the pattern.
    */
    void setTiledImage (const Image& image, const AffineTransform& transform) noexcept;

    /** Changes the opacity that should be used.
        If the fill is a solid colour, this just changes the opacity of that colour. For
        gradients and image tiles, it changes the opacity that will be used for them.
    */
    void setOpacity (float newOpacity) noexcept;

    /** Returns the current opacity to be applied to the colour, gradient, or image.
        @see setOpacity
    */
    float getOpacity() const noexcept       { return colour.getFloatAlpha(); }

    /** Returns true if this fill type is completely transparent. */
    bool isInvisible() const noexcept;

    /** Returns a copy of this fill, adding the specified transform applied to the
        existing transform.
    */
    FillType transformed (const AffineTransform& transform) const;

    //==============================================================================
    /** The solid colour being used.

        If the fill type is not a solid colour, the alpha channel of this colour indicates
        the opacity that should be used for the fill, and the RGB channels are ignored.
    */
    Colour colour;

    /** Returns the gradient that should be used for filling.
        This will be zero if the object is some other type of fill.
        If a gradient is active, the overall opacity with which it should be applied
        is indicated by the alpha channel of the colour variable.
    */
    ScopedPointer<ColourGradient> gradient;

    /** The image that should be used for tiling.
        If an image fill is active, the overall opacity with which it should be applied
        is indicated by the alpha channel of the colour variable.
    */
    Image image;

    /** The transform that should be applied to the image or gradient that's being drawn. */
    AffineTransform transform;

    //==============================================================================
    bool operator== (const FillType&) const;
    bool operator!= (const FillType&) const;

private:
    JUCE_LEAK_DETECTOR (FillType)
};

} // namespace juce


text:
/*
  ==============================================================================

   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
{

ColourGradient::ColourGradient() noexcept
{
   #if JUCE_DEBUG
    point1.setX (987654.0f);
    #define JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED   jassert (point1.x != 987654.0f);
   #else
    #define JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED
   #endif
}

ColourGradient::ColourGradient (Colour colour1, float x1, float y1,
                                Colour colour2, float x2, float y2, bool radial)
    : ColourGradient (colour1, Point<float> (x1, y1),
                      colour2, Point<float> (x2, y2), radial)
{
}

ColourGradient::ColourGradient (Colour colour1, Point<float> p1,
                                Colour colour2, Point<float> p2, bool radial)
    : point1 (p1),
      point2 (p2),
      isRadial (radial)
{
    colours.add (ColourPoint (0.0, colour1));
    colours.add (ColourPoint (1.0, colour2));
}

ColourGradient::~ColourGradient()
{
}

bool ColourGradient::operator== (const ColourGradient& other) const noexcept
{
    return point1 == other.point1 && point2 == other.point2
            && isRadial == other.isRadial
            && colours == other.colours;
}

bool ColourGradient::operator!= (const ColourGradient& other) const noexcept
{
    return ! operator== (other);
}

//==============================================================================
void ColourGradient::clearColours()
{
    colours.clear();
}

int ColourGradient::addColour (const double proportionAlongGradient, Colour colour)
{
    // must be within the two end-points
    jassert (proportionAlongGradient >= 0 && proportionAlongGradient <= 1.0);

    if (proportionAlongGradient <= 0)
    {
        colours.set (0, ColourPoint (0.0, colour));
        return 0;
    }

    auto pos = jmin (1.0, proportionAlongGradient);

    int i;
    for (i = 0; i < colours.size(); ++i)
        if (colours.getReference(i).position > pos)
            break;

    colours.insert (i, ColourPoint (pos, colour));
    return i;
}

void ColourGradient::removeColour (int index)
{
    jassert (index > 0 && index < colours.size() - 1);
    colours.remove (index);
}

void ColourGradient::multiplyOpacity (const float multiplier) noexcept
{
    for (auto& c : colours)
        c.colour = c.colour.withMultipliedAlpha (multiplier);
}

//==============================================================================
int ColourGradient::getNumColours() const noexcept
{
    return colours.size();
}

double ColourGradient::getColourPosition (const int index) const noexcept
{
    if (isPositiveAndBelow (index, colours.size()))
        return colours.getReference (index).position;

    return 0;
 }

Colour ColourGradient::getColour (const int index) const noexcept
{
    if (isPositiveAndBelow (index, colours.size()))
        return colours.getReference (index).colour;

    return {};
}

void ColourGradient::setColour (int index, Colour newColour) noexcept
{
    if (isPositiveAndBelow (index, colours.size()))
        colours.getReference (index).colour = newColour;
}

Colour ColourGradient::getColourAtPosition (const double position) const noexcept
{
    jassert (colours.getReference(0).position == 0.0); // the first colour specified has to go at position 0

    if (position <= 0 || colours.size() <= 1)
        return colours.getReference(0).colour;

    int i = colours.size() - 1;
    while (position < colours.getReference(i).position)
        --i;

    auto& p1 = colours.getReference (i);

    if (i >= colours.size() - 1)
        return p1.colour;

    auto& p2 = colours.getReference (i + 1);

    return p1.colour.interpolatedWith (p2.colour, (float) ((position - p1.position) / (p2.position - p1.position)));
}

//==============================================================================
void ColourGradient::createLookupTable (PixelARGB* const lookupTable, const int numEntries) const noexcept
{
    JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED // Trying to use this object without setting its coordinates?
    jassert (colours.size() >= 2);
    jassert (numEntries > 0);
    jassert (colours.getReference(0).position == 0.0); // The first colour specified has to go at position 0

    auto pix1 = colours.getReference (0).colour.getPixelARGB();
    int index = 0;

    for (int j = 1; j < colours.size(); ++j)
    {
        auto& p = colours.getReference (j);
        auto numToDo = roundToInt (p.position * (numEntries - 1)) - index;
        auto pix2 = p.colour.getPixelARGB();

        for (int i = 0; i < numToDo; ++i)
        {
            jassert (index >= 0 && index < numEntries);

            lookupTable[index] = pix1;
            lookupTable[index].tween (pix2, (uint32) ((i << 8) / numToDo));
            ++index;
        }

        pix1 = pix2;
    }

    while (index < numEntries)
        lookupTable [index++] = pix1;
}

int ColourGradient::createLookupTable (const AffineTransform& transform, HeapBlock<PixelARGB>& lookupTable) const
{
    JUCE_COLOURGRADIENT_CHECK_COORDS_INITIALISED // Trying to use this object without setting its coordinates?
    jassert (colours.size() >= 2);

    auto numEntries = jlimit (1, jmax (1, (colours.size() - 1) << 8),
                              3 * (int) point1.transformedBy (transform)
                                              .getDistanceFrom (point2.transformedBy (transform)));
    lookupTable.malloc (numEntries);
    createLookupTable (lookupTable, numEntries);
    return numEntries;
}

bool ColourGradient::isOpaque() const noexcept
{
    for (auto& c : colours)
        if (! c.colour.isOpaque())
            return false;

    return true;
}

bool ColourGradient::isInvisible() const noexcept
{
    for (auto& c : colours)
        if (! c.colour.isTransparent())
            return false;

    return true;
}

bool ColourGradient::ColourPoint::operator== (const ColourPoint& other) const noexcept
{
    return position == other.position && colour == other.colour;
}

bool ColourGradient::ColourPoint::operator!= (const ColourPoint& other) const noexcept
{
    return position != other.position || colour != other.colour;
}

} // namespace juce


text:
/*
  ==============================================================================

   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
{

//==============================================================================
/**
    Represents a colour, also including a transparency value.

    The colour is stored internally as unsigned 8-bit red, green, blue and alpha values.
*/
class JUCE_API  Colour  final
{
public:
    //==============================================================================
    /** Creates a transparent black colour. */
    Colour() noexcept;

    /** Creates a copy of another Colour object. */
    Colour (const Colour& other) noexcept;

    /** Creates a colour from a 32-bit ARGB value.

        The format of this number is:
            ((alpha << 24) | (red << 16) | (green << 8) | blue).

        All components in the range 0x00 to 0xff.
        An alpha of 0x00 is completely transparent, alpha of 0xff is opaque.

        @see getPixelARGB
    */
    explicit Colour (uint32 argb) noexcept;

    /** Creates an opaque colour using 8-bit red, green and blue values */
    Colour (uint8 red,
            uint8 green,
            uint8 blue) noexcept;

    /** Creates an opaque colour using 8-bit red, green and blue values */
    static Colour fromRGB (uint8 red,
                           uint8 green,
                           uint8 blue) noexcept;

    /** Creates a colour using 8-bit red, green, blue and alpha values. */
    Colour (uint8 red,
            uint8 green,
            uint8 blue,
            uint8 alpha) noexcept;

    /** Creates a colour using 8-bit red, green, blue and alpha values. */
    static Colour fromRGBA (uint8 red,
                            uint8 green,
                            uint8 blue,
                            uint8 alpha) noexcept;

    /** Creates a colour from 8-bit red, green, and blue values, and a floating-point alpha.

        Alpha of 0.0 is transparent, alpha of 1.0f is opaque.
        Values outside the valid range will be clipped.
    */
    Colour (uint8 red,
            uint8 green,
            uint8 blue,
            float alpha) noexcept;

    /** Creates a colour using floating point red, green, blue and alpha values.
        Numbers outside the range 0..1 will be clipped.
    */
    static Colour fromFloatRGBA (float red,
                                 float green,
                                 float blue,
                                 float alpha) noexcept;

    /** Creates a colour using floating point hue, saturation and brightness values, and an 8-bit alpha.

        The floating point values must be between 0.0 and 1.0.
        An alpha of 0x00 is completely transparent, alpha of 0xff is opaque.
        Values outside the valid range will be clipped.
    */
    Colour (float hue,
            float saturation,
            float brightness,
            uint8 alpha) noexcept;

    /** Creates a colour using floating point hue, saturation, brightness and alpha values.

        All values must be between 0.0 and 1.0.
        Numbers outside the valid range will be clipped.
    */
    Colour (float hue,
            float saturation,
            float brightness,
            float alpha) noexcept;

    /** Creates a colour using a PixelARGB object. This function assumes that the argb pixel is
        not premultiplied.
     */
    Colour (PixelARGB argb) noexcept;

    /** Creates a colour using a PixelRGB object.
     */
    Colour (PixelRGB rgb) noexcept;

    /** Creates a colour using a PixelAlpha object.
     */
    Colour (PixelAlpha alpha) noexcept;

    /** Creates a colour using floating point hue, saturation and brightness values, and an 8-bit alpha.

        The floating point values must be between 0.0 and 1.0.
        An alpha of 0x00 is completely transparent, alpha of 0xff is opaque.
        Values outside the valid range will be clipped.
    */
    static Colour fromHSV (float hue,
                           float saturation,
                           float brightness,
                           float alpha) noexcept;

    /** Destructor. */
    ~Colour() noexcept;

    /** Copies another Colour object. */
    Colour& operator= (const Colour& other) noexcept;

    /** Compares two colours. */
    bool operator== (const Colour& other) const noexcept;
    /** Compares two colours. */
    bool operator!= (const Colour& other) const noexcept;

    //==============================================================================
    /** Returns the red component of this colour.
        @returns a value between 0x00 and 0xff.
    */
    uint8 getRed() const noexcept                       { return argb.getRed(); }

    /** Returns the green component of this colour.
        @returns a value between 0x00 and 0xff.
    */
    uint8 getGreen() const noexcept                     { return argb.getGreen(); }

    /** Returns the blue component of this colour.
        @returns a value between 0x00 and 0xff.
    */
    uint8 getBlue() const noexcept                      { return argb.getBlue(); }

    /** Returns the red component of this colour as a floating point value.
        @returns a value between 0.0 and 1.0
    */
    float getFloatRed() const noexcept;

    /** Returns the green component of this colour as a floating point value.
        @returns a value between 0.0 and 1.0
    */
    float getFloatGreen() const noexcept;

    /** Returns the blue component of this colour as a floating point value.
        @returns a value between 0.0 and 1.0
    */
    float getFloatBlue() const noexcept;

    /** Returns a premultiplied ARGB pixel object that represents this colour.
    */
    const PixelARGB getPixelARGB() const noexcept;

    /** Returns a 32-bit integer that represents this colour.

        The format of this number is:
            ((alpha << 24) | (red << 16) | (green << 16) | blue).
    */
    uint32 getARGB() const noexcept;

    //==============================================================================
    /** Returns the colour's alpha (opacity).

        Alpha of 0x00 is completely transparent, 0xff is completely opaque.
    */
    uint8 getAlpha() const noexcept                     { return argb.getAlpha(); }

    /** Returns the colour's alpha (opacity) as a floating point value.

        Alpha of 0.0 is completely transparent, 1.0 is completely opaque.
    */
    float getFloatAlpha() const noexcept;

    /** Returns true if this colour is completely opaque.

        Equivalent to (getAlpha() == 0xff).
    */
    bool isOpaque() const noexcept;

    /** Returns true if this colour is completely transparent.

        Equivalent to (getAlpha() == 0x00).
    */
    bool isTransparent() const noexcept;

    /** Returns a colour that's the same colour as this one, but with a new alpha value. */
    Colour withAlpha (uint8 newAlpha) const noexcept;

    /** Returns a colour that's the same colour as this one, but with a new alpha value. */
    Colour withAlpha (float newAlpha) const noexcept;

    /** Returns a colour that's the same colour as this one, but with a modified alpha value.
        The new colour's alpha will be this object's alpha multiplied by the value passed-in.
    */
    Colour withMultipliedAlpha (float alphaMultiplier) const noexcept;

    //==============================================================================
    /** Returns a colour that is the result of alpha-compositing a new colour over this one.
        If the foreground colour is semi-transparent, it is blended onto this colour accordingly.
    */
    Colour overlaidWith (Colour foregroundColour) const noexcept;

    /** Returns a colour that lies somewhere between this one and another.
        If amountOfOther is zero, the result is 100% this colour, if amountOfOther
        is 1.0, the result is 100% of the other colour.
    */
    Colour interpolatedWith (Colour other, float proportionOfOther) const noexcept;

    //==============================================================================
    /** Returns the colour's hue component.
        The value returned is in the range 0.0 to 1.0
    */
    float getHue() const noexcept;

    /** Returns the colour's saturation component.
        The value returned is in the range 0.0 to 1.0
    */
    float getSaturation() const noexcept;

    /** Returns the colour's brightness component.
        The value returned is in the range 0.0 to 1.0
    */
    float getBrightness() const noexcept;

    /** Returns a skewed brightness value, adjusted to better reflect the way the human
        eye responds to different colour channels. This makes it better than getBrightness()
        for comparing differences in brightness.
    */
    float getPerceivedBrightness() const noexcept;

    /** Returns the colour's hue, saturation and brightness components all at once.
        The values returned are in the range 0.0 to 1.0
    */
    void getHSB (float& hue,
                 float& saturation,
                 float& brightness) const noexcept;

    //==============================================================================
    /** Returns a copy of this colour with a different hue. */
    Colour withHue (float newHue) const noexcept;

    /** Returns a copy of this colour with a different saturation. */
    Colour withSaturation (float newSaturation) const noexcept;

    /** Returns a copy of this colour with a different brightness.
        @see brighter, darker, withMultipliedBrightness
    */
    Colour withBrightness (float newBrightness) const noexcept;

    /** Returns a copy of this colour with it hue rotated.
        The new colour's hue is ((this->getHue() + amountToRotate) % 1.0)
        @see brighter, darker, withMultipliedBrightness
    */
    Colour withRotatedHue (float amountToRotate) const noexcept;

    /** Returns a copy of this colour with its saturation multiplied by the given value.
        The new colour's saturation is (this->getSaturation() * multiplier)
        (the result is clipped to legal limits).
    */
    Colour withMultipliedSaturation (float multiplier) const noexcept;

    /** Returns a copy of this colour with its brightness multiplied by the given value.
        The new colour's brightness is (this->getBrightness() * multiplier)
        (the result is clipped to legal limits).
    */
    Colour withMultipliedBrightness (float amount) const noexcept;

    //==============================================================================
    /** Returns a brighter version of this colour.
        @param amountBrighter   how much brighter to make it - a value from 0 to 1.0 where 0 is
                                unchanged, and higher values make it brighter
        @see withMultipliedBrightness
    */
    Colour brighter (float amountBrighter = 0.4f) const noexcept;

    /** Returns a darker version of this colour.
        @param amountDarker     how much darker to make it - a value from 0 to 1.0 where 0 is
                                unchanged, and higher values make it darker
        @see withMultipliedBrightness
    */
    Colour darker (float amountDarker = 0.4f) const noexcept;

    //==============================================================================
    /** Returns a colour that will be clearly visible against this colour.

        The amount parameter indicates how contrasting the new colour should
        be, so e.g. Colours::black.contrasting (0.1f) will return a colour
        that's just a little bit lighter; Colours::black.contrasting (1.0f) will
        return white; Colours::white.contrasting (1.0f) will return black, etc.
    */
    Colour contrasting (float amount = 1.0f) const noexcept;

    /** Returns a colour that is as close as possible to a target colour whilst
        still being in contrast to this one.

        The colour that is returned will be the targetColour, but with its luminosity
        nudged up or down so that it differs from the luminosity of this colour
        by at least the amount specified by minLuminosityDiff.
    */
    Colour contrasting (Colour targetColour, float minLuminosityDiff) const noexcept;

    /** Returns a colour that contrasts against two colours.
        Looks for a colour that contrasts with both of the colours passed-in.
        Handy for things like choosing a highlight colour in text editors, etc.
    */
    static Colour contrasting (Colour colour1,
                               Colour colour2) noexcept;

    //==============================================================================
    /** Returns an opaque shade of grey.
        @param brightness the level of grey to return - 0 is black, 1.0 is white
    */
    static Colour greyLevel (float brightness) noexcept;

    //==============================================================================
    /** Returns a stringified version of this colour.
        The string can be turned back into a colour using the fromString() method.
    */
    String toString() const;

    /** Reads the colour from a string that was created with toString(). */
    static Colour fromString (StringRef encodedColourString);

    /** Returns the colour as a hex string in the form RRGGBB or AARRGGBB. */
    String toDisplayString (bool includeAlphaValue) const;

private:
    //==============================================================================
    PixelARGB argb;
};

} // namespace juce


text:
/*
  ==============================================================================

   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
{

const Colour Colours::transparentBlack (0);
const Colour Colours::transparentWhite (0x00ffffff);

const Colour Colours::aliceblue (0xfff0f8ff);
const Colour Colours::antiquewhite (0xfffaebd7);
const Colour Colours::aqua (0xff00ffff);
const Colour Colours::aquamarine (0xff7fffd4);
const Colour Colours::azure (0xfff0ffff);
const Colour Colours::beige (0xfff5f5dc);
const Colour Colours::bisque (0xffffe4c4);
const Colour Colours::black (0xff000000);
const Colour Colours::blanchedalmond (0xffffebcd);
const Colour Colours::blue (0xff0000ff);
const Colour Colours::blueviolet (0xff8a2be2);
const Colour Colours::brown (0xffa52a2a);
const Colour Colours::burlywood (0xffdeb887);
const Colour Colours::cadetblue (0xff5f9ea0);
const Colour Colours::chartreuse (0xff7fff00);
const Colour Colours::chocolate (0xffd2691e);
const Colour Colours::coral (0xffff7f50);
const Colour Colours::cornflowerblue (0xff6495ed);
const Colour Colours::cornsilk (0xfffff8dc);
const Colour Colours::crimson (0xffdc143c);
const Colour Colours::cyan (0xff00ffff);
const Colour Colours::darkblue (0xff00008b);
const Colour Colours::darkcyan (0xff008b8b);
const Colour Colours::darkgoldenrod (0xffb8860b);
const Colour Colours::darkgrey (0xff555555);
const Colour Colours::darkgreen (0xff006400);
const Colour Colours::darkkhaki (0xffbdb76b);
const Colour Colours::darkmagenta (0xff8b008b);
const Colour Colours::darkolivegreen (0xff556b2f);
const Colour Colours::darkorange (0xffff8c00);
const Colour Colours::darkorchid (0xff9932cc);
const Colour Colours::darkred (0xff8b0000);
const Colour Colours::darksalmon (0xffe9967a);
const Colour Colours::darkseagreen (0xff8fbc8f);
const Colour Colours::darkslateblue (0xff483d8b);
const Colour Colours::darkslategrey (0xff2f4f4f);
const Colour Colours::darkturquoise (0xff00ced1);
const Colour Colours::darkviolet (0xff9400d3);
const Colour Colours::deeppink (0xffff1493);
const Colour Colours::deepskyblue (0xff00bfff);
const Colour Colours::dimgrey (0xff696969);
const Colour Colours::dodgerblue (0xff1e90ff);
const Colour Colours::firebrick (0xffb22222);
const Colour Colours::floralwhite (0xfffffaf0);
const Colour Colours::forestgreen (0xff228b22);
const Colour Colours::fuchsia (0xffff00ff);
const Colour Colours::gainsboro (0xffdcdcdc);
const Colour Colours::ghostwhite (0xfff8f8ff);
const Colour Colours::gold (0xffffd700);
const Colour Colours::goldenrod (0xffdaa520);
const Colour Colours::grey (0xff808080);
const Colour Colours::green (0xff008000);
const Colour Colours::greenyellow (0xffadff2f);
const Colour Colours::honeydew (0xfff0fff0);
const Colour Colours::hotpink (0xffff69b4);
const Colour Colours::indianred (0xffcd5c5c);
const Colour Colours::indigo (0xff4b0082);
const Colour Colours::ivory (0xfffffff0);
const Colour Colours::khaki (0xfff0e68c);
const Colour Colours::lavender (0xffe6e6fa);
const Colour Colours::lavenderblush (0xfffff0f5);
const Colour Colours::lawngreen (0xff7cfc00);
const Colour Colours::lemonchiffon (0xfffffacd);
const Colour Colours::lightblue (0xffadd8e6);
const Colour Colours::lightcoral (0xfff08080);
const Colour Colours::lightcyan (0xffe0ffff);
const Colour Colours::lightgoldenrodyellow (0xfffafad2);
const Colour Colours::lightgreen (0xff90ee90);
const Colour Colours::lightgrey (0xffd3d3d3);
const Colour Colours::lightpink (0xffffb6c1);
const Colour Colours::lightsalmon (0xffffa07a);
const Colour Colours::lightseagreen (0xff20b2aa);
const Colour Colours::lightskyblue (0xff87cefa);
const Colour Colours::lightslategrey (0xff778899);
const Colour Colours::lightsteelblue (0xffb0c4de);
const Colour Colours::lightyellow (0xffffffe0);
const Colour Colours::lime (0xff00ff00);
const Colour Colours::limegreen (0xff32cd32);
const Colour Colours::linen (0xfffaf0e6);
const Colour Colours::magenta (0xffff00ff);
const Colour Colours::maroon (0xff800000);
const Colour Colours::mediumaquamarine (0xff66cdaa);
const Colour Colours::mediumblue (0xff0000cd);
const Colour Colours::mediumorchid (0xffba55d3);
const Colour Colours::mediumpurple (0xff9370db);
const Colour Colours::mediumseagreen (0xff3cb371);
const Colour Colours::mediumslateblue (0xff7b68ee);
const Colour Colours::mediumspringgreen (0xff00fa9a);
const Colour Colours::mediumturquoise (0xff48d1cc);
const Colour Colours::mediumvioletred (0xffc71585);
const Colour Colours::midnightblue (0xff191970);
const Colour Colours::mintcream (0xfff5fffa);
const Colour Colours::mistyrose (0xffffe4e1);
const Colour Colours::moccasin (0xffffe4b5);
const Colour Colours::navajowhite (0xffffdead);
const Colour Colours::navy (0xff000080);
const Colour Colours::oldlace (0xfffdf5e6);
const Colour Colours::olive (0xff808000);
const Colour Colours::olivedrab (0xff6b8e23);
const Colour Colours::orange (0xffffa500);
const Colour Colours::orangered (0xffff4500);
const Colour Colours::orchid (0xffda70d6);
const Colour Colours::palegoldenrod (0xffeee8aa);
const Colour Colours::palegreen (0xff98fb98);
const Colour Colours::paleturquoise (0xffafeeee);
const Colour Colours::palevioletred (0xffdb7093);
const Colour Colours::papayawhip (0xffffefd5);
const Colour Colours::peachpuff (0xffffdab9);
const Colour Colours::peru (0xffcd853f);
const Colour Colours::pink (0xffffc0cb);
const Colour Colours::plum (0xffdda0dd);
const Colour Colours::powderblue (0xffb0e0e6);
const Colour Colours::purple (0xff800080);
const Colour Colours::rebeccapurple (0xff663399);
const Colour Colours::red (0xffff0000);
const Colour Colours::rosybrown (0xffbc8f8f);
const Colour Colours::royalblue (0xff4169e1);
const Colour Colours::saddlebrown (0xff8b4513);
const Colour Colours::salmon (0xfffa8072);
const Colour Colours::sandybrown (0xfff4a460);
const Colour Colours::seagreen (0xff2e8b57);
const Colour Colours::seashell (0xfffff5ee);
const Colour Colours::sienna (0xffa0522d);
const Colour Colours::silver (0xffc0c0c0);
const Colour Colours::skyblue (0xff87ceeb);
const Colour Colours::slateblue (0xff6a5acd);
const Colour Colours::slategrey (0xff708090);
const Colour Colours::snow (0xfffffafa);
const Colour Colours::springgreen (0xff00ff7f);
const Colour Colours::steelblue (0xff4682b4);
const Colour Colours::tan (0xffd2b48c);
const Colour Colours::teal (0xff008080);
const Colour Colours::thistle (0xffd8bfd8);
const Colour Colours::tomato (0xffff6347);
const Colour Colours::turquoise (0xff40e0d0);
const Colour Colours::violet (0xffee82ee);
const Colour Colours::wheat (0xfff5deb3);
const Colour Colours::white (0xffffffff);
const Colour Colours::whitesmoke (0xfff5f5f5);
const Colour Colours::yellow (0xffffff00);
const Colour Colours::yellowgreen (0xff9acd32);

//==============================================================================
Colour Colours::findColourForName (const String& colourName,
                                   Colour defaultColour)
{
    static const uint32 presets[] =
    {
        // (first value is the string's hashcode, second is ARGB)

        0x05978fff, 0xff000000, /* black */
        0x06bdcc29, 0xffffffff, /* white */
        0x002e305a, 0xff0000ff, /* blue */
        0x00308adf, 0xff808080, /* grey */
        0x05e0cf03, 0xff008000, /* green */
        0x0001b891, 0xffff0000, /* red */
        0xd43c6474, 0xffffff00, /* yellow */
        0x620886da, 0xfff0f8ff, /* aliceblue */
        0x20a2676a, 0xfffaebd7, /* antiquewhite */
        0x002dcebc, 0xff00ffff, /* aqua */
        0x46bb5f7e, 0xff7fffd4, /* aquamarine */
        0x0590228f, 0xfff0ffff, /* azure */
        0x05947fe4, 0xfff5f5dc, /* beige */
        0xad388e35, 0xffffe4c4, /* bisque */
        0x00674f7e, 0xffffebcd, /* blanchedalmond */
        0x39129959, 0xff8a2be2, /* blueviolet */
        0x059a8136, 0xffa52a2a, /* brown */
        0x89cea8f9, 0xffdeb887, /* burlywood */
        0x0fa260cf, 0xff5f9ea0, /* cadetblue */
        0x6b748956, 0xff7fff00, /* chartreuse */
        0x2903623c, 0xffd2691e, /* chocolate */
        0x05a74431, 0xffff7f50, /* coral */
        0x618d42dd, 0xff6495ed, /* cornflowerblue */
        0xe4b479fd, 0xfffff8dc, /* cornsilk */
        0x3d8c4edf, 0xffdc143c, /* crimson */
        0x002ed323, 0xff00ffff, /* cyan */
        0x67cc74d0, 0xff00008b, /* darkblue */
        0x67cd1799, 0xff008b8b, /* darkcyan */
        0x31bbd168, 0xffb8860b, /* darkgoldenrod */
        0x67cecf55, 0xff555555, /* darkgrey */
        0x920b194d, 0xff006400, /* darkgreen */
        0x923edd4c, 0xffbdb76b, /* darkkhaki */
        0x5c293873, 0xff8b008b, /* darkmagenta */
        0x6b6671fe, 0xff556b2f, /* darkolivegreen */
        0xbcfd2524, 0xffff8c00, /* darkorange */
        0xbcfdf799, 0xff9932cc, /* darkorchid */
        0x55ee0d5b, 0xff8b0000, /* darkred */
        0xc2e5f564, 0xffe9967a, /* darksalmon */
        0x61be858a, 0xff8fbc8f, /* darkseagreen */
        0xc2b0f2bd, 0xff483d8b, /* darkslateblue */
        0xc2b34d42, 0xff2f4f4f, /* darkslategrey */
        0x7cf2b06b, 0xff00ced1, /* darkturquoise */
        0xc8769375, 0xff9400d3, /* darkviolet */
        0x25832862, 0xffff1493, /* deeppink */
        0xfcad568f, 0xff00bfff, /* deepskyblue */
        0x634c8b67, 0xff696969, /* dimgrey */
        0x45c1ce55, 0xff1e90ff, /* dodgerblue */
        0xef19e3cb, 0xffb22222, /* firebrick */
        0xb852b195, 0xfffffaf0, /* floralwhite */
        0xd086fd06, 0xff228b22, /* forestgreen */
        0xe106b6d7, 0xffff00ff, /* fuchsia */
        0x7880d61e, 0xffdcdcdc, /* gainsboro */
        0x2018a2fa, 0xfff8f8ff, /* ghostwhite */
        0x00308060, 0xffffd700, /* gold */
        0xb3b3bc1e, 0xffdaa520, /* goldenrod */
        0xbab8a537, 0xffadff2f, /* greenyellow */
        0xe4cacafb, 0xfff0fff0, /* honeydew */
        0x41892743, 0xffff69b4, /* hotpink */
        0xd5796f1a, 0xffcd5c5c, /* indianred */
        0xb969fed2, 0xff4b0082, /* indigo */
        0x05fef6a9, 0xfffffff0, /* ivory */
        0x06149302, 0xfff0e68c, /* khaki */
        0xad5a05c7, 0xffe6e6fa, /* lavender */
        0x7c4d5b99, 0xfffff0f5, /* lavenderblush */
        0x41cc4377, 0xff7cfc00, /* lawngreen */
        0x195756f0, 0xfffffacd, /* lemonchiffon */
        0x28e4ea70, 0xffadd8e6, /* lightblue */
        0xf3c7ccdb, 0xfff08080, /* lightcoral */
        0x28e58d39, 0xffe0ffff, /* lightcyan */
        0x21234e3c, 0xfffafad2, /* lightgoldenrodyellow */
        0xf40157ad, 0xff90ee90, /* lightgreen */
        0x28e744f5, 0xffd3d3d3, /* lightgrey */
        0x28eb3b8c, 0xffffb6c1, /* lightpink */
        0x9fb78304, 0xffffa07a, /* lightsalmon */
        0x50632b2a, 0xff20b2aa, /* lightseagreen */
        0x68fb7b25, 0xff87cefa, /* lightskyblue */
        0xa8a35ba2, 0xff778899, /* lightslategrey */
        0xa20d484f, 0xffb0c4de, /* lightsteelblue */
        0xaa2cf10a, 0xffffffe0, /* lightyellow */
        0x0032afd5, 0xff00ff00, /* lime */
        0x607bbc4e, 0xff32cd32, /* limegreen */
        0x06234efa, 0xfffaf0e6, /* linen */
        0x316858a9, 0xffff00ff, /* magenta */
        0xbf8ca470, 0xff800000, /* maroon */
        0xbd58e0b3, 0xff66cdaa, /* mediumaquamarine */
        0x967dfd4f, 0xff0000cd, /* mediumblue */
        0x056f5c58, 0xffba55d3, /* mediumorchid */
        0x07556b71, 0xff9370db, /* mediumpurple */
        0x5369b689, 0xff3cb371, /* mediumseagreen */
        0x066be19e, 0xff7b68ee, /* mediumslateblue */
        0x3256b281, 0xff00fa9a, /* mediumspringgreen */
        0xc0ad9f4c, 0xff48d1cc, /* mediumturquoise */
        0x628e63dd, 0xffc71585, /* mediumvioletred */
        0x168eb32a, 0xff191970, /* midnightblue */
        0x4306b960, 0xfff5fffa, /* mintcream */
        0x4cbc0e6b, 0xffffe4e1, /* mistyrose */
        0xd9447d59, 0xffffe4b5, /* moccasin */
        0xe97218a6, 0xffffdead, /* navajowhite */
        0x00337bb6, 0xff000080, /* navy */
        0xadd2d33e, 0xfffdf5e6, /* oldlace */
        0x064ee1db, 0xff808000, /* olive */
        0x9e33a98a, 0xff6b8e23, /* olivedrab */
        0xc3de262e, 0xffffa500, /* orange */
        0x58bebba3, 0xffff4500, /* orangered */
        0xc3def8a3, 0xffda70d6, /* orchid */
        0x28cb4834, 0xffeee8aa, /* palegoldenrod */
        0x3d9dd619, 0xff98fb98, /* palegreen */
        0x74022737, 0xffafeeee, /* paleturquoise */
        0x15e2ebc8, 0xffdb7093, /* palevioletred */
        0x5fd898e2, 0xffffefd5, /* papayawhip */
        0x93e1b776, 0xffffdab9, /* peachpuff */
        0x003472f8, 0xffcd853f, /* peru */
        0x00348176, 0xffffc0cb, /* pink */
        0x00348d94, 0xffdda0dd, /* plum */
        0xd036be93, 0xffb0e0e6, /* powderblue */
        0xc5c507bc, 0xff800080, /* purple */
        0xf381f607, 0xff663399, /* rebeccapurple */
        0xa89d65b3, 0xffbc8f8f, /* rosybrown */
        0xbd9413e1, 0xff4169e1, /* royalblue */
        0xf456044f, 0xff8b4513, /* saddlebrown */
        0xc9c6f66e, 0xfffa8072, /* salmon */
        0x0bb131e1, 0xfff4a460, /* sandybrown */
        0x34636c14, 0xff2e8b57, /* seagreen */
        0x3507fb41, 0xfffff5ee, /* seashell */
        0xca348772, 0xffa0522d, /* sienna */
        0xca37d30d, 0xffc0c0c0, /* silver */
        0x80da74fb, 0xff87ceeb, /* skyblue */
        0x44a8dd73, 0xff6a5acd, /* slateblue */
        0x44ab37f8, 0xff708090, /* slategrey */
        0x0035f183, 0xfffffafa, /* snow */
        0xd5440d16, 0xff00ff7f, /* springgreen */
        0x3e1524a5, 0xff4682b4, /* steelblue */
        0x0001bfa1, 0xffd2b48c, /* tan */
        0x0036425c, 0xff008080, /* teal */
        0xafc8858f, 0xffd8bfd8, /* thistle */
        0xcc41600a, 0xffff6347, /* tomato */
        0xfeea9b21, 0xff40e0d0, /* turquoise */
        0xcf57947f, 0xffee82ee, /* violet */
        0x06bdbae7, 0xfff5deb3, /* wheat */
        0x10802ee6, 0xfff5f5f5, /* whitesmoke */
        0xe1b5130f, 0xff9acd32  /* yellowgreen */
    };

    const uint32 hash = (uint32) colourName.trim().toLowerCase().hashCode();

    for (int i = 0; i < numElementsInArray (presets); i += 2)
        if (presets [i] == hash)
            return Colour (presets [i + 1]);

    return defaultColour;
}

} // namespace juce


text:
/*
  ==============================================================================

   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
{

//==============================================================================
#if JUCE_MSVC
 #pragma pack (push, 1)
#endif

class PixelRGB;
class PixelAlpha;

inline uint32 maskPixelComponents (uint32 x) noexcept
{
    return (x >> 8) & 0x00ff00ff;
}

inline uint32 clampPixelComponents (uint32 x) noexcept
{
    return (x | (0x01000100 - maskPixelComponents (x))) & 0x00ff00ff;
}

//==============================================================================
/**
    Represents a 32-bit INTERNAL pixel with premultiplied alpha, and can perform compositing
    operations with it.

    This is used internally by the imaging classes.

    @see PixelRGB
*/
class JUCE_API  PixelARGB
{
public:
    /** Creates a pixel without defining its colour. */
    PixelARGB() noexcept {}
    ~PixelARGB() noexcept {}

    PixelARGB (const uint8 a, const uint8 r, const uint8 g, const uint8 b) noexcept
    {
        components.b = b;
        components.g = g;
        components.r = r;
        components.a = a;
    }

    //==============================================================================
    /** Returns a uint32 which represents the pixel in a platform dependent format. */
    forcedinline uint32 getNativeARGB() const noexcept { return internal; }

    /** Returns a uint32 which will be in argb order as if constructed with the following mask operation
        ((alpha << 24) | (red << 16) | (green << 8) | blue). */
    forcedinline uint32 getInARGBMaskOrder() const noexcept
    {
       #if JUCE_ANDROID
        return (uint32) ((components.a << 24) | (components.r << 16) | (components.g << 8) | (components.b << 0));
       #else
        return getNativeARGB();
       #endif
    }

    /** Returns a uint32 which when written to memory, will be in the order a, r, g, b. In other words,
        if the return-value is read as a uint8 array then the elements will be in the order of a, r, g, b*/
    inline uint32 getInARGBMemoryOrder() const noexcept
    {
       #if JUCE_BIG_ENDIAN
        return getInARGBMaskOrder();
       #else
        return (uint32) ((components.b << 24) | (components.g << 16) | (components.r << 8) | components.a);
       #endif
    }

    /** Return channels with an even index and insert zero bytes between them. This is useful for blending
        operations. The exact channels which are returned is platform dependent. */
    forcedinline uint32 getEvenBytes() const noexcept { return 0x00ff00ff & internal; }

    /** Return channels with an odd index and insert zero bytes between them. This is useful for blending
        operations. The exact channels which are returned is platform dependent. */
    forcedinline uint32 getOddBytes() const noexcept  { return 0x00ff00ff & (internal >> 8); }

    //==============================================================================
    forcedinline uint8 getAlpha() const noexcept      { return components.a; }
    forcedinline uint8 getRed() const noexcept        { return components.r; }
    forcedinline uint8 getGreen() const noexcept      { return components.g; }
    forcedinline uint8 getBlue() const noexcept       { return components.b; }

   #if JUCE_GCC
    // NB these are here as a workaround because GCC refuses to bind to packed values.
    forcedinline uint8& getAlpha() noexcept           { return comps [indexA]; }
    forcedinline uint8& getRed() noexcept             { return comps [indexR]; }
    forcedinline uint8& getGreen() noexcept           { return comps [indexG]; }
    forcedinline uint8& getBlue() noexcept            { return comps [indexB]; }
   #else
    forcedinline uint8& getAlpha() noexcept           { return components.a; }
    forcedinline uint8& getRed() noexcept             { return components.r; }
    forcedinline uint8& getGreen() noexcept           { return components.g; }
    forcedinline uint8& getBlue() noexcept            { return components.b; }
   #endif

    //==============================================================================
    /** Copies another pixel colour over this one.

        This doesn't blend it - this colour is simply replaced by the other one.
    */
    template <class Pixel>
    forcedinline void set (const Pixel& src) noexcept
    {
        internal = src.getNativeARGB();
    }

    //==============================================================================
    /** Sets the pixel's colour from individual components. */
    void setARGB (const uint8 a, const uint8 r, const uint8 g, const uint8 b) noexcept
    {
        components.b = b;
        components.g = g;
        components.r = r;
        components.a = a;
    }

    //==============================================================================
    /** Blends another pixel onto this one.

        This takes into account the opacity of the pixel being overlaid, and blends
        it accordingly.
    */
    template <class Pixel>
    forcedinline void blend (const Pixel& src) noexcept
    {
        uint32 rb = src.getEvenBytes();
        uint32 ag = src.getOddBytes();

        const uint32 alpha = 0x100 - (ag >> 16);

        rb += maskPixelComponents (getEvenBytes() * alpha);
        ag += maskPixelComponents (getOddBytes() * alpha);

        internal = clampPixelComponents (rb) | (clampPixelComponents (ag) << 8);
    }

    /** Blends another pixel onto this one.

        This takes into account the opacity of the pixel being overlaid, and blends
        it accordingly.
    */
    forcedinline void blend (const PixelRGB src) noexcept;

    /** Blends another pixel onto this one, applying an extra multiplier to its opacity.

        The opacity of the pixel being overlaid is scaled by the extraAlpha factor before
        being used, so this can blend semi-transparently from a PixelRGB argument.
    */
    template <class Pixel>
    forcedinline void blend (const Pixel& src, uint32 extraAlpha) noexcept
    {
        uint32 rb = maskPixelComponents (extraAlpha * src.getEvenBytes());
        uint32 ag = maskPixelComponents (extraAlpha * src.getOddBytes());

        const uint32 alpha = 0x100 - (ag >> 16);

        rb += maskPixelComponents (getEvenBytes() * alpha);
        ag += maskPixelComponents (getOddBytes() * alpha);

        internal = clampPixelComponents (rb) | (clampPixelComponents (ag) << 8);
    }

    /** Blends another pixel with this one, creating a colour that is somewhere
        between the two, as specified by the amount.
    */
    template <class Pixel>
    forcedinline void tween (const Pixel& src, const uint32 amount) noexcept
    {
        uint32 dEvenBytes = getEvenBytes();
        dEvenBytes += (((src.getEvenBytes() - dEvenBytes) * amount) >> 8);
        dEvenBytes &= 0x00ff00ff;

        uint32 dOddBytes = getOddBytes();
        dOddBytes += (((src.getOddBytes() - dOddBytes) * amount) >> 8);
        dOddBytes &= 0x00ff00ff;
        dOddBytes <<= 8;

        dOddBytes |= dEvenBytes;
        internal = dOddBytes;
    }

    //==============================================================================
    /** Replaces the colour's alpha value with another one. */
    forcedinline void setAlpha (const uint8 newAlpha) noexcept
    {
        components.a = newAlpha;
    }

    /** Multiplies the colour's alpha value with another one. */
    forcedinline void multiplyAlpha (int multiplier) noexcept
    {
        // increment alpha by 1, so that if multiplier == 255 (full alpha),
        // this function will not change the values.
        ++multiplier;

        internal = ((((uint32) multiplier) * getOddBytes()) & 0xff00ff00)
                | (((((uint32) multiplier) * getEvenBytes()) >> 8) & 0x00ff00ff);
    }

    forcedinline void multiplyAlpha (const float multiplier) noexcept
    {
        multiplyAlpha ((int) (multiplier * 255.0f));
    }

    inline PixelARGB getUnpremultiplied() const noexcept { PixelARGB p (internal); p.unpremultiply(); return p; }

    /** Premultiplies the pixel's RGB values by its alpha. */
    forcedinline void premultiply() noexcept
    {
        const uint32 alpha = components.a;

        if (alpha < 0xff)
        {
            if (alpha == 0)
            {
                components.b = 0;
                components.g = 0;
                components.r = 0;
            }
            else
            {
                components.b = (uint8) ((components.b * alpha + 0x7f) >> 8);
                components.g = (uint8) ((components.g * alpha + 0x7f) >> 8);
                components.r = (uint8) ((components.r * alpha + 0x7f) >> 8);
            }
        }
    }

    /** Unpremultiplies the pixel's RGB values. */
    forcedinline void unpremultiply() noexcept
    {
        const uint32 alpha = components.a;

        if (alpha < 0xff)
        {
            if (alpha == 0)
            {
                components.b = 0;
                components.g = 0;
                components.r = 0;
            }
            else
            {
                components.b = (uint8) jmin ((uint32) 0xffu, (components.b * 0xffu) / alpha);
                components.g = (uint8) jmin ((uint32) 0xffu, (components.g * 0xffu) / alpha);
                components.r = (uint8) jmin ((uint32) 0xffu, (components.r * 0xffu) / alpha);
            }
        }
    }

    forcedinline void desaturate() noexcept
    {
        if (components.a < 0xff && components.a > 0)
        {
            const int newUnpremultipliedLevel = (0xff * ((int) components.r + (int) components.g + (int) components.b) / (3 * components.a));

            components.r = components.g = components.b
                = (uint8) ((newUnpremultipliedLevel * components.a + 0x7f) >> 8);
        }
        else
        {
            components.r = components.g = components.b
                = (uint8) (((int) components.r + (int) components.g + (int) components.b) / 3);
        }
    }

    //==============================================================================
    /** The indexes of the different components in the byte layout of this type of colour. */
  #if JUCE_ANDROID
   #if JUCE_BIG_ENDIAN
    enum { indexA = 0, indexR = 3, indexG = 2, indexB = 1 };
   #else
    enum { indexA = 3, indexR = 0, indexG = 1, indexB = 2 };
   #endif
  #else
   #if JUCE_BIG_ENDIAN
    enum { indexA = 0, indexR = 1, indexG = 2, indexB = 3 };
   #else
    enum { indexA = 3, indexR = 2, indexG = 1, indexB = 0 };
   #endif
  #endif

private:
    //==============================================================================
    PixelARGB (const uint32 internalValue) noexcept
        : internal (internalValue)
    {
    }

    //==============================================================================
    struct Components
    {
      #if JUCE_ANDROID
       #if JUCE_BIG_ENDIAN
        uint8 a, b, g, r;
       #else
        uint8 r, g, b, a;
       #endif
      #else
       #if JUCE_BIG_ENDIAN
        uint8 a, r, g, b;
       #else
        uint8 b, g, r, a;
       #endif
      #endif
    } JUCE_PACKED;

    union
    {
        uint32 internal;
        Components components;
       #if JUCE_GCC
        uint8 comps[4];  // helper struct needed because gcc does not allow references to packed union members
       #endif
    };
}
#ifndef DOXYGEN
 JUCE_PACKED
#endif
;

//==============================================================================
/**
    Represents a 24-bit RGB pixel, and can perform compositing operations on it.

    This is used internally by the imaging classes.

    @see PixelARGB
*/
class JUCE_API  PixelRGB
{
public:
    /** Creates a pixel without defining its colour. */
    PixelRGB() noexcept {}
    ~PixelRGB() noexcept {}

    //==============================================================================
    /** Returns a uint32 which represents the pixel in a platform dependent format which is compatible
        with the native format of a PixelARGB.

        @see PixelARGB::getNativeARGB */
    forcedinline uint32 getNativeARGB() const noexcept
    {
       #if JUCE_ANDROID
        return (uint32) ((0xff << 24) | r | (g << 8) | (b << 16));
       #else
        return (uint32) ((0xff << 24) | b | (g << 8) | (r << 16));
       #endif
    }

    /** Returns a uint32 which will be in argb order as if constructed with the following mask operation
        ((alpha << 24) | (red << 16) | (green << 8) | blue). */
    forcedinline uint32 getInARGBMaskOrder() const noexcept
    {
       #if JUCE_ANDROID
        return (uint32) ((0xff << 24) | (r << 16) | (g << 8) | (b << 0));
       #else
        return getNativeARGB();
       #endif
    }

    /** Returns a uint32 which when written to memory, will be in the order a, r, g, b. In other words,
        if the return-value is read as a uint8 array then the elements will be in the order of a, r, g, b*/
    inline uint32 getInARGBMemoryOrder() const noexcept
    {
       #if JUCE_BIG_ENDIAN
        return getInARGBMaskOrder();
       #else
        return (uint32) ((b << 24) | (g << 16) | (r << 8) | 0xff);
       #endif
    }

    /** Return channels with an even index and insert zero bytes between them. This is useful for blending
        operations. The exact channels which are returned is platform dependent but compatible with the
        return value of getEvenBytes of the PixelARGB class.

        @see PixelARGB::getEvenBytes */
    forcedinline uint32 getEvenBytes() const noexcept
    {
       #if JUCE_ANDROID
        return (uint32) (r | (b << 16));
       #else
        return (uint32) (b | (r << 16));
       #endif
    }

    /** Return channels with an odd index and insert zero bytes between them. This is useful for blending
        operations. The exact channels which are returned is platform dependent but compatible with the
        return value of getOddBytes of the PixelARGB class.

        @see PixelARGB::getOddBytes */
    forcedinline uint32 getOddBytes() const noexcept       { return (uint32)0xff0000 | g; }

    //==============================================================================
    forcedinline uint8 getAlpha() const noexcept    { return 0xff; }
    forcedinline uint8 getRed() const noexcept      { return r; }
    forcedinline uint8 getGreen() const noexcept    { return g; }
    forcedinline uint8 getBlue() const noexcept     { return b; }

    forcedinline uint8& getRed() noexcept           { return r; }
    forcedinline uint8& getGreen() noexcept         { return g; }
    forcedinline uint8& getBlue() noexcept          { return b; }

    //==============================================================================
    /** Copies another pixel colour over this one.

        This doesn't blend it - this colour is simply replaced by the other one.
        Because PixelRGB has no alpha channel, any alpha value in the source pixel
        is thrown away.
    */
    template <class Pixel>
    forcedinline void set (const Pixel& src) noexcept
    {
        b = src.getBlue();
        g = src.getGreen();
        r = src.getRed();
    }

    /** Sets the pixel's colour from individual components. */
    void setARGB (const uint8, const uint8 red, const uint8 green, const uint8 blue) noexcept
    {
        r = red;
        g = green;
        b = blue;
    }

    //==============================================================================
    /** Blends another pixel onto this one.

        This takes into account the opacity of the pixel being overlaid, and blends
        it accordingly.
    */
    template <class Pixel>
    forcedinline void blend (const Pixel& src) noexcept
    {
        const uint32 alpha = (uint32) (0x100 - src.getAlpha());

        // getEvenBytes returns 0x00rr00bb on non-android
        uint32 rb = clampPixelComponents (src.getEvenBytes() + maskPixelComponents (getEvenBytes() * alpha));
        // getOddBytes returns 0x00aa00gg on non-android
        uint32 ag = clampPixelComponents (src.getOddBytes() + ((g * alpha) >> 8));

        g = (uint8) (ag & 0xff);

       #if JUCE_ANDROID
        b = (uint8) (rb >> 16);
        r = (uint8) (rb & 0xff);
       #else
        r = (uint8) (rb >> 16);
        b = (uint8) (rb & 0xff);
       #endif
    }

    forcedinline void blend (const PixelRGB src) noexcept
    {
        set (src);
    }

    /** Blends another pixel onto this one, applying an extra multiplier to its opacity.

        The opacity of the pixel being overlaid is scaled by the extraAlpha factor before
        being used, so this can blend semi-transparently from a PixelRGB argument.
    */
    template <class Pixel>
    forcedinline void blend (const Pixel& src, uint32 extraAlpha) noexcept
    {
        uint32 ag = maskPixelComponents (extraAlpha * src.getOddBytes());
        uint32 rb = maskPixelComponents (extraAlpha * src.getEvenBytes());

        const uint32 alpha = 0x100 - (ag >> 16);

        ag = clampPixelComponents (ag + (g * alpha >> 8));
        rb = clampPixelComponents (rb + maskPixelComponents (getEvenBytes() * alpha));

        g = (uint8) (ag & 0xff);

       #if JUCE_ANDROID
        b = (uint8) (rb >> 16);
        r = (uint8) (rb & 0xff);
       #else
        r = (uint8) (rb >> 16);
        b = (uint8) (rb & 0xff);
       #endif
    }

    /** Blends another pixel with this one, creating a colour that is somewhere
        between the two, as specified by the amount.
    */
    template <class Pixel>
    forcedinline void tween (const Pixel& src, const uint32 amount) noexcept
    {
        uint32 dEvenBytes = getEvenBytes();
        dEvenBytes += (((src.getEvenBytes() - dEvenBytes) * amount) >> 8);

        uint32 dOddBytes = getOddBytes();
        dOddBytes += (((src.getOddBytes() - dOddBytes) * amount) >> 8);

        g = (uint8) (dOddBytes & 0xff);  // dOddBytes =  0x00aa00gg

       #if JUCE_ANDROID
        r = (uint8) (dEvenBytes & 0xff); // dEvenBytes = 0x00bb00rr
        b = (uint8) (dEvenBytes >> 16);
       #else
        b = (uint8) (dEvenBytes & 0xff); // dEvenBytes = 0x00rr00bb
        r = (uint8) (dEvenBytes >> 16);
       #endif
    }

    //==============================================================================
    /** This method is included for compatibility with the PixelARGB class. */
    forcedinline void setAlpha (const uint8) noexcept {}

    /** Multiplies the colour's alpha value with another one. */
    forcedinline void multiplyAlpha (int) noexcept {}

    /** Multiplies the colour's alpha value with another one. */
    forcedinline void multiplyAlpha (float) noexcept {}

    /** Premultiplies the pixel's RGB values by its alpha. */
    forcedinline void premultiply() noexcept {}

    /** Unpremultiplies the pixel's RGB values. */
    forcedinline void unpremultiply() noexcept {}

    forcedinline void desaturate() noexcept
    {
        r = g = b = (uint8) (((int) r + (int) g + (int) b) / 3);
    }

    //==============================================================================
    /** The indexes of the different components in the byte layout of this type of colour. */
   #if JUCE_MAC
    enum { indexR = 0, indexG = 1, indexB = 2 };
   #else
    enum { indexR = 2, indexG = 1, indexB = 0 };
   #endif

private:
    //==============================================================================
    PixelRGB (const uint32 internal) noexcept
    {
      #if JUCE_ANDROID
        b = (uint8) (internal >> 16);
        g = (uint8) (internal >> 8);
        r = (uint8) (internal);
      #else
        r = (uint8) (internal >> 16);
        g = (uint8) (internal >> 8);
        b = (uint8) (internal);
      #endif
    }

    //==============================================================================
   #if JUCE_MAC
    uint8 r, g, b;
   #else
    uint8 b, g, r;
   #endif

}
#ifndef DOXYGEN
 JUCE_PACKED
#endif
;

forcedinline void PixelARGB::blend (const PixelRGB src) noexcept
{
    set (src);
}

//==============================================================================
/**
    Represents an 8-bit single-channel pixel, and can perform compositing operations on it.

    This is used internally by the imaging classes.

    @see PixelARGB, PixelRGB
*/
class JUCE_API  PixelAlpha
{
public:
    /** Creates a pixel without defining its colour. */
    PixelAlpha() noexcept {}
    ~PixelAlpha() noexcept {}

    //==============================================================================
    /** Returns a uint32 which represents the pixel in a platform dependent format which is compatible
        with the native format of a PixelARGB.

        @see PixelARGB::getNativeARGB */
    forcedinline uint32 getNativeARGB() const noexcept      { return (uint32) ((a << 24) | (a << 16) | (a << 8) | a); }

    /** Returns a uint32 which will be in argb order as if constructed with the following mask operation
        ((alpha << 24) | (red << 16) | (green << 8) | blue). */
    forcedinline uint32 getInARGBMaskOrder() const noexcept { return getNativeARGB(); }

    /** Returns a uint32 which when written to memory, will be in the order a, r, g, b. In other words,
        if the return-value is read as a uint8 array then the elements will be in the order of a, r, g, b*/
    inline uint32 getInARGBMemoryOrder() const noexcept     { return getNativeARGB(); }

    /** Return channels with an even index and insert zero bytes between them. This is useful for blending
        operations. The exact channels which are returned is platform dependent but compatible with the
        return value of getEvenBytes of the PixelARGB class.

        @see PixelARGB::getEvenBytes */
    forcedinline uint32 getEvenBytes() const noexcept      { return (uint32) ((a << 16) | a); }

    /** Return channels with an odd index and insert zero bytes between them. This is useful for blending
        operations. The exact channels which are returned is platform dependent but compatible with the
        return value of getOddBytes of the PixelARGB class.

        @see PixelARGB::getOddBytes */
    forcedinline uint32 getOddBytes() const noexcept       { return (uint32) ((a << 16) | a); }

    //==============================================================================
    forcedinline uint8 getAlpha() const noexcept    { return a; }
    forcedinline uint8& getAlpha() noexcept         { return a; }

    forcedinline uint8 getRed() const noexcept      { return 0; }
    forcedinline uint8 getGreen() const noexcept    { return 0; }
    forcedinline uint8 getBlue() const noexcept     { return 0; }

    //==============================================================================
    /** Copies another pixel colour over this one.

        This doesn't blend it - this colour is simply replaced by the other one.
    */
    template <class Pixel>
    forcedinline void set (const Pixel& src) noexcept
    {
        a = src.getAlpha();
    }

    /** Sets the pixel's colour from individual components. */
    forcedinline void setARGB (const uint8 a_, const uint8 /*r*/, const uint8 /*g*/, const uint8 /*b*/) noexcept
    {
        a = a_;
    }

    //==============================================================================
    /** Blends another pixel onto this one.

        This takes into account the opacity of the pixel being overlaid, and blends
        it accordingly.
    */
    template <class Pixel>
    forcedinline void blend (const Pixel& src) noexcept
    {
        const int srcA = src.getAlpha();
        a = (uint8) ((a * (0x100 - srcA) >> 8) + srcA);
    }

    /** Blends another pixel onto this one, applying an extra multiplier to its opacity.

        The opacity of the pixel being overlaid is scaled by the extraAlpha factor before
        being used, so this can blend semi-transparently from a PixelRGB argument.
    */
    template <class Pixel>
    forcedinline void blend (const Pixel& src, uint32 extraAlpha) noexcept
    {
        ++extraAlpha;
        const int srcAlpha = (int) ((extraAlpha * src.getAlpha()) >> 8);
        a = (uint8) ((a * (0x100 - srcAlpha) >> 8) + srcAlpha);
    }

    /** Blends another pixel with this one, creating a colour that is somewhere
        between the two, as specified by the amount.
    */
    template <class Pixel>
    forcedinline void tween (const Pixel& src, const uint32 amount) noexcept
    {
        a += ((src.getAlpha() - a) * amount) >> 8;
    }

    //==============================================================================
    /** Replaces the colour's alpha value with another one. */
    forcedinline void setAlpha (const uint8 newAlpha) noexcept
    {
        a = newAlpha;
    }

    /** Multiplies the colour's alpha value with another one. */
    forcedinline void multiplyAlpha (int multiplier) noexcept
    {
        ++multiplier;
        a = (uint8) ((a * multiplier) >> 8);
    }

    forcedinline void multiplyAlpha (const float multiplier) noexcept
    {
        a = (uint8) (a * multiplier);
    }

    /** Premultiplies the pixel's RGB values by its alpha. */
    forcedinline void premultiply() noexcept {}

    /** Unpremultiplies the pixel's RGB values. */
    forcedinline void unpremultiply() noexcept {}

    forcedinline void desaturate() noexcept {}

    //==============================================================================
    /** The indexes of the different components in the byte layout of this type of colour. */
    enum { indexA = 0 };

private:
    //==============================================================================
    PixelAlpha (const uint32 internal) noexcept
    {
        a = (uint8) (internal >> 24);
    }

    //==============================================================================
    uint8 a;
}
#ifndef DOXYGEN
 JUCE_PACKED
#endif
;

#if JUCE_MSVC
 #pragma pack (pop)
#endif

} // namespace juce