| @@ -2168,42 +2168,6 @@ | |||||
| <Filter | <Filter | ||||
| Name="graphics" | Name="graphics" | ||||
| > | > | ||||
| <Filter | |||||
| Name="brushes" | |||||
| > | |||||
| <File | |||||
| RelativePath="..\..\..\src\gui\graphics\brushes\juce_Brush.cpp" | |||||
| > | |||||
| </File> | |||||
| <File | |||||
| RelativePath="..\..\..\src\gui\graphics\brushes\juce_Brush.h" | |||||
| > | |||||
| </File> | |||||
| <File | |||||
| RelativePath="..\..\..\src\gui\graphics\brushes\juce_GradientBrush.cpp" | |||||
| > | |||||
| </File> | |||||
| <File | |||||
| RelativePath="..\..\..\src\gui\graphics\brushes\juce_GradientBrush.h" | |||||
| > | |||||
| </File> | |||||
| <File | |||||
| RelativePath="..\..\..\src\gui\graphics\brushes\juce_ImageBrush.cpp" | |||||
| > | |||||
| </File> | |||||
| <File | |||||
| RelativePath="..\..\..\src\gui\graphics\brushes\juce_ImageBrush.h" | |||||
| > | |||||
| </File> | |||||
| <File | |||||
| RelativePath="..\..\..\src\gui\graphics\brushes\juce_SolidColourBrush.cpp" | |||||
| > | |||||
| </File> | |||||
| <File | |||||
| RelativePath="..\..\..\src\gui\graphics\brushes\juce_SolidColourBrush.h" | |||||
| > | |||||
| </File> | |||||
| </Filter> | |||||
| <Filter | <Filter | ||||
| Name="colour" | Name="colour" | ||||
| > | > | ||||
| @@ -130,20 +130,18 @@ public: | |||||
| } | } | ||||
| else if (type == 2 || type == 3) | else if (type == 2 || type == 3) | ||||
| { | { | ||||
| GradientBrush gb (Colours::blue.withAlpha ((float) opacitySlider->getValue()), | |||||
| getWidth() * 0.5f, getHeight() * 0.5f, | |||||
| Colours::red.withAlpha ((float) opacitySlider->getValue()), | |||||
| getWidth() * 0.6f, getHeight() * 0.7f, | |||||
| type == 3); | |||||
| ColourGradient gradient (Colours::blue.withAlpha ((float) opacitySlider->getValue()), | |||||
| getWidth() * 0.5f, getHeight() * 0.5f, | |||||
| Colours::red.withAlpha ((float) opacitySlider->getValue()), | |||||
| getWidth() * 0.6f, getHeight() * 0.7f, | |||||
| type == 3); | |||||
| g.setBrush (&gb); | |||||
| g.setGradientFill (gradient); | |||||
| g.fillPath (shape, getTransform()); | g.fillPath (shape, getTransform()); | ||||
| } | } | ||||
| else if (type == 8) | else if (type == 8) | ||||
| { | { | ||||
| ImageBrush ib (image, 100, 100, (float) opacitySlider->getValue()); | |||||
| g.setBrush (&ib); | |||||
| g.setTiledImageFill (*image, 100, 100, (float) opacitySlider->getValue()); | |||||
| g.fillPath (shape, getTransform()); | g.fillPath (shape, getTransform()); | ||||
| } | } | ||||
| else if (type == 4 || type == 5) | else if (type == 4 || type == 5) | ||||
| @@ -179,16 +177,16 @@ public: | |||||
| } | } | ||||
| else if (type == 7) | else if (type == 7) | ||||
| { | { | ||||
| GradientBrush gb (Colours::blue.withAlpha ((float) opacitySlider->getValue()), | |||||
| getWidth() * 0.5f, getHeight() * 0.5f, | |||||
| Colours::red.withAlpha ((float) opacitySlider->getValue()), | |||||
| getWidth() * 0.6f, getHeight() * 0.7f, | |||||
| false); | |||||
| g.setBrush (&gb); | |||||
| if (image != 0) | if (image != 0) | ||||
| { | { | ||||
| ColourGradient gradient (Colours::blue.withAlpha ((float) opacitySlider->getValue()), | |||||
| getWidth() * 0.5f, getHeight() * 0.5f, | |||||
| Colours::red.withAlpha ((float) opacitySlider->getValue()), | |||||
| getWidth() * 0.6f, getHeight() * 0.7f, | |||||
| false); | |||||
| g.setGradientFill (gradient); | |||||
| g.drawImageTransformed (image, | g.drawImageTransformed (image, | ||||
| 0, 0, image->getWidth(), image->getHeight(), | 0, 0, image->getWidth(), image->getHeight(), | ||||
| AffineTransform::translation (-0.5f * image->getWidth(), -0.5f * image->getHeight()) | AffineTransform::translation (-0.5f * image->getWidth(), -0.5f * image->getHeight()) | ||||
| @@ -198,11 +196,10 @@ public: | |||||
| } | } | ||||
| else if (type == 9) | else if (type == 9) | ||||
| { | { | ||||
| ImageBrush ib (image, 100, 100, (float) opacitySlider->getValue()); | |||||
| g.setBrush (&ib); | |||||
| if (image != 0) | if (image != 0) | ||||
| { | { | ||||
| g.setTiledImageFill (*image, 100, 100, (float) opacitySlider->getValue()); | |||||
| g.drawImageTransformed (image, | g.drawImageTransformed (image, | ||||
| 0, 0, image->getWidth(), image->getHeight(), | 0, 0, image->getWidth(), image->getHeight(), | ||||
| AffineTransform::translation (-0.5f * image->getWidth(), | AffineTransform::translation (-0.5f * image->getWidth(), | ||||
| @@ -110,15 +110,14 @@ void FillType::reset() | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| Brush* FillType::createBrush (JucerDocument* const document, | |||||
| const Rectangle& parentArea) | |||||
| void FillType::setFillType (Graphics& g, JucerDocument* const document, const Rectangle& parentArea) | |||||
| { | { | ||||
| if (mode == solidColour) | if (mode == solidColour) | ||||
| { | { | ||||
| ImageCache::release (image); | ImageCache::release (image); | ||||
| image = 0; | image = 0; | ||||
| return new SolidColourBrush (colour); | |||||
| g.setColour (colour); | |||||
| } | } | ||||
| else if (mode == imageBrush) | else if (mode == imageBrush) | ||||
| { | { | ||||
| @@ -126,7 +125,7 @@ Brush* FillType::createBrush (JucerDocument* const document, | |||||
| Rectangle r (imageAnchor.getRectangle (parentArea, document->getComponentLayout())); | Rectangle r (imageAnchor.getRectangle (parentArea, document->getComponentLayout())); | ||||
| return new ImageBrush (image, r.getX(), r.getY(), (float) imageOpacity); | |||||
| g.setTiledImageFill (*image, r.getX(), r.getY(), (float) imageOpacity); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -136,9 +135,9 @@ Brush* FillType::createBrush (JucerDocument* const document, | |||||
| Rectangle r1 (gradPos1.getRectangle (parentArea, document->getComponentLayout())); | Rectangle r1 (gradPos1.getRectangle (parentArea, document->getComponentLayout())); | ||||
| Rectangle r2 (gradPos2.getRectangle (parentArea, document->getComponentLayout())); | Rectangle r2 (gradPos2.getRectangle (parentArea, document->getComponentLayout())); | ||||
| return new GradientBrush (gradCol1, (float) r1.getX(), (float) r1.getY(), | |||||
| gradCol2, (float) r2.getX(), (float) r2.getY(), | |||||
| mode == radialGradient); | |||||
| g.setGradientFill (ColourGradient (gradCol1, (float) r1.getX(), (float) r1.getY(), | |||||
| gradCol2, (float) r2.getX(), (float) r2.getY(), | |||||
| mode == radialGradient)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -46,7 +46,7 @@ public: | |||||
| bool operator!= (const FillType& other) const throw(); | bool operator!= (const FillType& other) const throw(); | ||||
| //============================================================================== | //============================================================================== | ||||
| Brush* createBrush (JucerDocument* const document, const Rectangle& parentArea); | |||||
| void setFillType (Graphics& g, JucerDocument* const document, const Rectangle& parentArea); | |||||
| void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) const; | void fillInGeneratedCode (GeneratedCode& code, String& paintMethodCode) const; | ||||
| @@ -45,23 +45,17 @@ public: | |||||
| void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) | void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) | ||||
| { | { | ||||
| Brush* const brush = fillType.createBrush (getDocument(), parentArea); | |||||
| g.setBrush (brush); | |||||
| fillType.setFillType (g, getDocument(), parentArea); | |||||
| Rectangle r (position.getRectangle (parentArea, layout)); | Rectangle r (position.getRectangle (parentArea, layout)); | ||||
| g.fillEllipse ((float) r.getX(), (float) r.getY(), (float) r.getWidth(), (float) r.getHeight()); | g.fillEllipse ((float) r.getX(), (float) r.getY(), (float) r.getWidth(), (float) r.getHeight()); | ||||
| delete brush; | |||||
| if (isStrokePresent) | if (isStrokePresent) | ||||
| { | { | ||||
| Brush* const brush = strokeType.fill.createBrush (getDocument(), parentArea); | |||||
| g.setBrush (brush); | |||||
| strokeType.fill.setFillType (g, getDocument(), parentArea); | |||||
| g.drawEllipse ((float) r.getX(), (float) r.getY(), (float) r.getWidth(), (float) r.getHeight(), | g.drawEllipse ((float) r.getX(), (float) r.getY(), (float) r.getWidth(), (float) r.getHeight(), | ||||
| getStrokeType().stroke.getStrokeThickness()); | getStrokeType().stroke.getStrokeThickness()); | ||||
| delete brush; | |||||
| } | } | ||||
| } | } | ||||
| @@ -242,24 +242,16 @@ static void drawArrow (Graphics& g, float x1, float y1, float x2, float y2) | |||||
| void PaintElementPath::draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) | void PaintElementPath::draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) | ||||
| { | { | ||||
| Brush* const brush = fillType.createBrush (getDocument(), parentArea); | |||||
| g.setBrush (brush); | |||||
| updateStoredPath (layout, parentArea); | updateStoredPath (layout, parentArea); | ||||
| path.setUsingNonZeroWinding (nonZeroWinding); | path.setUsingNonZeroWinding (nonZeroWinding); | ||||
| g.fillPath (path); | |||||
| delete brush; | |||||
| fillType.setFillType (g, getDocument(), parentArea); | |||||
| g.fillPath (path); | |||||
| if (isStrokePresent) | if (isStrokePresent) | ||||
| { | { | ||||
| Brush* const brush = strokeType.fill.createBrush (getDocument(), parentArea); | |||||
| g.setBrush (brush); | |||||
| strokeType.fill.setFillType (g, getDocument(), parentArea); | |||||
| g.strokePath (path, getStrokeType().stroke); | g.strokePath (path, getStrokeType().stroke); | ||||
| delete brush; | |||||
| } | } | ||||
| } | } | ||||
| @@ -60,23 +60,17 @@ public: | |||||
| Component parentComponent; | Component parentComponent; | ||||
| parentComponent.setBounds (parentArea); | parentComponent.setBounds (parentArea); | ||||
| Brush* const brush = fillType.createBrush (getDocument(), parentArea); | |||||
| g.setBrush (brush); | |||||
| fillType.setFillType (g, getDocument(), parentArea); | |||||
| const Rectangle r (position.getRectangle (parentArea, layout)); | const Rectangle r (position.getRectangle (parentArea, layout)); | ||||
| g.fillRect (r); | g.fillRect (r); | ||||
| delete brush; | |||||
| if (isStrokePresent) | if (isStrokePresent) | ||||
| { | { | ||||
| Brush* const brush = strokeType.fill.createBrush (getDocument(), parentArea); | |||||
| g.setBrush (brush); | |||||
| strokeType.fill.setFillType (g, getDocument(), parentArea); | |||||
| g.drawRect (r.getX(), r.getY(), r.getWidth(), r.getHeight(), | g.drawRect (r.getX(), r.getY(), r.getWidth(), r.getHeight(), | ||||
| roundDoubleToInt (getStrokeType().stroke.getStrokeThickness())); | roundDoubleToInt (getStrokeType().stroke.getStrokeThickness())); | ||||
| delete brush; | |||||
| } | } | ||||
| } | } | ||||
| @@ -47,25 +47,18 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) | void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) | ||||
| { | { | ||||
| Brush* const brush = fillType.createBrush (getDocument(), parentArea); | |||||
| g.setBrush (brush); | |||||
| double x, y, w, h; | double x, y, w, h; | ||||
| position.getRectangleDouble (x, y, w, h, parentArea, layout); | position.getRectangleDouble (x, y, w, h, parentArea, layout); | ||||
| fillType.setFillType (g, getDocument(), parentArea); | |||||
| g.fillRoundedRectangle ((float) x, (float) y, (float) w, (float) h, (float) cornerSize); | g.fillRoundedRectangle ((float) x, (float) y, (float) w, (float) h, (float) cornerSize); | ||||
| delete brush; | |||||
| if (isStrokePresent) | if (isStrokePresent) | ||||
| { | { | ||||
| Brush* const brush = strokeType.fill.createBrush (getDocument(), parentArea); | |||||
| g.setBrush (brush); | |||||
| strokeType.fill.setFillType (g, getDocument(), parentArea); | |||||
| g.drawRoundedRectangle ((float) x, (float) y, (float) w, (float) h, (float) cornerSize, | g.drawRoundedRectangle ((float) x, (float) y, (float) w, (float) h, (float) cornerSize, | ||||
| getStrokeType().stroke.getStrokeThickness()); | getStrokeType().stroke.getStrokeThickness()); | ||||
| delete brush; | |||||
| } | } | ||||
| } | } | ||||
| @@ -57,8 +57,7 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) | void draw (Graphics& g, const ComponentLayout* layout, const Rectangle& parentArea) | ||||
| { | { | ||||
| Brush* const brush = fillType.createBrush (getDocument(), parentArea); | |||||
| g.setBrush (brush); | |||||
| fillType.setFillType (g, getDocument(), parentArea); | |||||
| font = FontPropertyComponent::applyNameToFont (typefaceName, font); | font = FontPropertyComponent::applyNameToFont (typefaceName, font); | ||||
| g.setFont (font); | g.setFont (font); | ||||
| @@ -67,8 +66,6 @@ public: | |||||
| g.drawText (replaceStringTranslations (text, owner->getDocument()), | g.drawText (replaceStringTranslations (text, owner->getDocument()), | ||||
| r.getX(), r.getY(), r.getWidth(), r.getHeight(), | r.getX(), r.getY(), r.getWidth(), r.getHeight(), | ||||
| justification, true); | justification, true); | ||||
| delete brush; | |||||
| } | } | ||||
| void getEditableProperties (Array <PropertyComponent*>& properties) | void getEditableProperties (Array <PropertyComponent*>& properties) | ||||
| @@ -1,70 +0,0 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-9 by Raw Material Software Ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||||
| Public License (Version 2), as published by the Free Software Foundation. | |||||
| A copy of the license is included in the JUCE distribution, or can be found | |||||
| online at www.gnu.org/licenses. | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "../../../core/juce_StandardHeader.h" | |||||
| BEGIN_JUCE_NAMESPACE | |||||
| #include "juce_Brush.h" | |||||
| #include "../contexts/juce_Graphics.h" | |||||
| #include "../contexts/juce_EdgeTable.h" | |||||
| //============================================================================== | |||||
| Brush::Brush() throw() | |||||
| { | |||||
| } | |||||
| Brush::~Brush() throw() | |||||
| { | |||||
| } | |||||
| void Brush::paintVerticalLine (LowLevelGraphicsContext& context, | |||||
| int x, float y1, float y2) throw() | |||||
| { | |||||
| Path p; | |||||
| p.addRectangle ((float) x, y1, 1.0f, y2 - y1); | |||||
| paintPath (context, p, AffineTransform::identity); | |||||
| } | |||||
| void Brush::paintHorizontalLine (LowLevelGraphicsContext& context, | |||||
| int y, float x1, float x2) throw() | |||||
| { | |||||
| Path p; | |||||
| p.addRectangle (x1, (float) y, x2 - x1, 1.0f); | |||||
| paintPath (context, p, AffineTransform::identity); | |||||
| } | |||||
| void Brush::paintLine (LowLevelGraphicsContext& context, | |||||
| float x1, float y1, float x2, float y2) throw() | |||||
| { | |||||
| Path p; | |||||
| p.addLineSegment (x1, y1, x2, y2, 1.0f); | |||||
| paintPath (context, p, AffineTransform::identity); | |||||
| } | |||||
| END_JUCE_NAMESPACE | |||||
| @@ -1,100 +0,0 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-9 by Raw Material Software Ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||||
| Public License (Version 2), as published by the Free Software Foundation. | |||||
| A copy of the license is included in the JUCE distribution, or can be found | |||||
| online at www.gnu.org/licenses. | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #ifndef __JUCE_BRUSH_JUCEHEADER__ | |||||
| #define __JUCE_BRUSH_JUCEHEADER__ | |||||
| class Path; | |||||
| class AffineTransform; | |||||
| class LowLevelGraphicsContext; | |||||
| class Image; | |||||
| class Graphics; | |||||
| //============================================================================== | |||||
| /** | |||||
| A brush is used to fill areas with colours, patterns, or images. | |||||
| The Graphics class has an idea of a current brush which it uses to render | |||||
| shapes, rectangles, lines, text, etc. | |||||
| This is the base class - there are subclasses for useful types of fill pattern, | |||||
| and applications can define their own brushes too. | |||||
| @see Graphics::setBrush, SolidColourBrush, GradientBrush, ImageBrush | |||||
| */ | |||||
| class JUCE_API Brush | |||||
| { | |||||
| protected: | |||||
| //============================================================================== | |||||
| /** Creates a Brush. | |||||
| (Nothing much happens in the base class). | |||||
| */ | |||||
| Brush() throw(); | |||||
| public: | |||||
| /** Destructor. */ | |||||
| virtual ~Brush() throw(); | |||||
| /** Creates a copy of whatever class of Brush this is. */ | |||||
| virtual Brush* createCopy() const throw() = 0; | |||||
| /** Does whatever is relevent to transform the geometry of this brush. */ | |||||
| virtual void applyTransform (const AffineTransform& transform) throw() = 0; | |||||
| /** Does whatever is relevent to change the opacity of this brush. */ | |||||
| virtual void multiplyOpacity (const float multiple) throw() = 0; | |||||
| /** Must return true if this brush won't draw any pixels. */ | |||||
| virtual bool isInvisible() const throw() = 0; | |||||
| //============================================================================== | |||||
| virtual void paintPath (LowLevelGraphicsContext& context, | |||||
| const Path& path, const AffineTransform& transform) throw() = 0; | |||||
| virtual void paintRectangle (LowLevelGraphicsContext& context, | |||||
| int x, int y, int w, int h) throw() = 0; | |||||
| virtual void paintAlphaChannel (LowLevelGraphicsContext& context, | |||||
| const Image& alphaChannelImage, int imageX, int imageY, | |||||
| int x, int y, int w, int h) throw() = 0; | |||||
| virtual void paintVerticalLine (LowLevelGraphicsContext& context, | |||||
| int x, float y1, float y2) throw(); | |||||
| virtual void paintHorizontalLine (LowLevelGraphicsContext& context, | |||||
| int y, float x1, float x2) throw(); | |||||
| virtual void paintLine (LowLevelGraphicsContext& context, | |||||
| float x1, float y1, float x2, float y2) throw(); | |||||
| private: | |||||
| //============================================================================== | |||||
| Brush (const Brush&); | |||||
| const Brush& operator= (const Brush&); | |||||
| }; | |||||
| #endif // __JUCE_BRUSH_JUCEHEADER__ | |||||
| @@ -1,108 +0,0 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-9 by Raw Material Software Ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||||
| Public License (Version 2), as published by the Free Software Foundation. | |||||
| A copy of the license is included in the JUCE distribution, or can be found | |||||
| online at www.gnu.org/licenses. | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "../../../core/juce_StandardHeader.h" | |||||
| BEGIN_JUCE_NAMESPACE | |||||
| #include "juce_GradientBrush.h" | |||||
| #include "../contexts/juce_LowLevelGraphicsContext.h" | |||||
| //============================================================================== | |||||
| GradientBrush::GradientBrush (const Colour& colour1, | |||||
| const float x1, | |||||
| const float y1, | |||||
| const Colour& colour2, | |||||
| const float x2, | |||||
| const float y2, | |||||
| const bool isRadial) throw() | |||||
| : gradient (colour1, x1, y1, | |||||
| colour2, x2, y2, | |||||
| isRadial) | |||||
| { | |||||
| } | |||||
| GradientBrush::GradientBrush (const ColourGradient& gradient_) throw() | |||||
| : gradient (gradient_) | |||||
| { | |||||
| } | |||||
| GradientBrush::~GradientBrush() throw() | |||||
| { | |||||
| } | |||||
| Brush* GradientBrush::createCopy() const throw() | |||||
| { | |||||
| return new GradientBrush (gradient); | |||||
| } | |||||
| void GradientBrush::applyTransform (const AffineTransform& transform) throw() | |||||
| { | |||||
| gradient.transform = gradient.transform.followedBy (transform); | |||||
| } | |||||
| void GradientBrush::multiplyOpacity (const float multiple) throw() | |||||
| { | |||||
| gradient.multiplyOpacity (multiple); | |||||
| } | |||||
| bool GradientBrush::isInvisible() const throw() | |||||
| { | |||||
| return gradient.isInvisible(); | |||||
| } | |||||
| //============================================================================== | |||||
| void GradientBrush::paintPath (LowLevelGraphicsContext& context, | |||||
| const Path& path, const AffineTransform& transform) throw() | |||||
| { | |||||
| context.setGradient (gradient); | |||||
| context.fillPath (path, transform); | |||||
| } | |||||
| void GradientBrush::paintRectangle (LowLevelGraphicsContext& context, | |||||
| int x, int y, int w, int h) throw() | |||||
| { | |||||
| context.setGradient (gradient); | |||||
| context.fillRect (x, y, w, h, false); | |||||
| } | |||||
| void GradientBrush::paintAlphaChannel (LowLevelGraphicsContext& context, | |||||
| const Image& alphaChannelImage, int imageX, int imageY, | |||||
| int x, int y, int w, int h) throw() | |||||
| { | |||||
| context.saveState(); | |||||
| if (context.reduceClipRegion (x, y, w, h)) | |||||
| { | |||||
| context.setGradient (gradient); | |||||
| context.fillAlphaChannel (alphaChannelImage, imageX, imageY); | |||||
| } | |||||
| context.restoreState(); | |||||
| } | |||||
| END_JUCE_NAMESPACE | |||||
| @@ -1,113 +0,0 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-9 by Raw Material Software Ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||||
| Public License (Version 2), as published by the Free Software Foundation. | |||||
| A copy of the license is included in the JUCE distribution, or can be found | |||||
| online at www.gnu.org/licenses. | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #ifndef __JUCE_GRADIENTBRUSH_JUCEHEADER__ | |||||
| #define __JUCE_GRADIENTBRUSH_JUCEHEADER__ | |||||
| #include "juce_Brush.h" | |||||
| #include "../colour/juce_ColourGradient.h" | |||||
| //============================================================================== | |||||
| /** | |||||
| A Brush that fills areas with a colour gradient. | |||||
| The gradient can either be linear or circular. | |||||
| @see Brush, Graphics::setBrush, SolidColourBrush, ImageBrush | |||||
| */ | |||||
| class JUCE_API GradientBrush : public Brush | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| /** Creates a gradient brush, ready for use in Graphics::setBrush(). | |||||
| (x1, y1) is the location relative to the origin of the Graphics context, | |||||
| at which the colour should be colour1. Likewise for (x2, y2) and colour2. | |||||
| If isRadial is true, the colours form a circular gradient with (x1, y1) at | |||||
| its centre. | |||||
| The alpha transparencies of the colours are used, so the brush | |||||
| need not be completely opaque. Note that this means that if you | |||||
| blend from transparent to a solid colour, the RGB of the transparent | |||||
| colour will become visible in parts of the gradient. e.g. blending | |||||
| from Colour::transparentBlack to Colours::white will produce a | |||||
| grey colour, but Colour::transparentWhite to Colours::white will be | |||||
| white all the way across. | |||||
| @see ColourGradient | |||||
| */ | |||||
| GradientBrush (const Colour& colour1, | |||||
| const float x1, | |||||
| const float y1, | |||||
| const Colour& colour2, | |||||
| const float x2, | |||||
| const float y2, | |||||
| const bool isRadial) throw(); | |||||
| /** Creates a gradient brush from a ColourGradient object. | |||||
| */ | |||||
| GradientBrush (const ColourGradient& gradient) throw(); | |||||
| /** Destructor. */ | |||||
| ~GradientBrush() throw(); | |||||
| //============================================================================== | |||||
| /** Returns the current gradient information */ | |||||
| const ColourGradient& getGradient() const throw() { return gradient; } | |||||
| //============================================================================== | |||||
| Brush* createCopy() const throw(); | |||||
| void applyTransform (const AffineTransform& transform) throw(); | |||||
| void multiplyOpacity (const float multiple) throw(); | |||||
| bool isInvisible() const throw(); | |||||
| void paintPath (LowLevelGraphicsContext& context, | |||||
| const Path& path, const AffineTransform& transform) throw(); | |||||
| void paintRectangle (LowLevelGraphicsContext& context, | |||||
| int x, int y, int w, int h) throw(); | |||||
| void paintAlphaChannel (LowLevelGraphicsContext& context, | |||||
| const Image& alphaChannelImage, int imageX, int imageY, | |||||
| int x, int y, int w, int h) throw(); | |||||
| //============================================================================== | |||||
| juce_UseDebuggingNewOperator | |||||
| protected: | |||||
| ColourGradient gradient; | |||||
| private: | |||||
| GradientBrush (const GradientBrush&); | |||||
| const GradientBrush& operator= (const GradientBrush&); | |||||
| }; | |||||
| #endif // __JUCE_GRADIENTBRUSH_JUCEHEADER__ | |||||
| @@ -1,224 +0,0 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-9 by Raw Material Software Ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||||
| Public License (Version 2), as published by the Free Software Foundation. | |||||
| A copy of the license is included in the JUCE distribution, or can be found | |||||
| online at www.gnu.org/licenses. | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "../../../core/juce_StandardHeader.h" | |||||
| BEGIN_JUCE_NAMESPACE | |||||
| #include "juce_ImageBrush.h" | |||||
| #include "../contexts/juce_LowLevelGraphicsContext.h" | |||||
| //============================================================================== | |||||
| ImageBrush::ImageBrush (Image* const image_, | |||||
| const int anchorX_, | |||||
| const int anchorY_, | |||||
| const float opacity_) throw() | |||||
| : image (image_), | |||||
| anchorX (anchorX_), | |||||
| anchorY (anchorY_), | |||||
| opacity (opacity_) | |||||
| { | |||||
| jassert (image != 0); // not much point creating a brush without an image, is there? | |||||
| if (image != 0) | |||||
| { | |||||
| if (image->getWidth() == 0 || image->getHeight() == 0) | |||||
| { | |||||
| jassertfalse // you've passed in an empty image - not exactly brilliant for tiling. | |||||
| image = 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| ImageBrush::~ImageBrush() throw() | |||||
| { | |||||
| } | |||||
| Brush* ImageBrush::createCopy() const throw() | |||||
| { | |||||
| return new ImageBrush (image, anchorX, anchorY, opacity); | |||||
| } | |||||
| void ImageBrush::multiplyOpacity (const float multiple) throw() | |||||
| { | |||||
| opacity *= multiple; | |||||
| } | |||||
| bool ImageBrush::isInvisible() const throw() | |||||
| { | |||||
| return opacity == 0.0f; | |||||
| } | |||||
| void ImageBrush::applyTransform (const AffineTransform& /*transform*/) throw() | |||||
| { | |||||
| //xxx should probably be smarter and warp the image | |||||
| } | |||||
| void ImageBrush::getStartXY (int& x, int& y) const throw() | |||||
| { | |||||
| x -= anchorX; | |||||
| y -= anchorY; | |||||
| const int iw = image->getWidth(); | |||||
| const int ih = image->getHeight(); | |||||
| if (x < 0) | |||||
| x = ((x / iw) - 1) * iw; | |||||
| else | |||||
| x = (x / iw) * iw; | |||||
| if (y < 0) | |||||
| y = ((y / ih) - 1) * ih; | |||||
| else | |||||
| y = (y / ih) * ih; | |||||
| x += anchorX; | |||||
| y += anchorY; | |||||
| } | |||||
| //============================================================================== | |||||
| void ImageBrush::paintRectangle (LowLevelGraphicsContext& context, | |||||
| int x, int y, int w, int h) throw() | |||||
| { | |||||
| context.saveState(); | |||||
| if (image != 0 && context.reduceClipRegion (x, y, w, h)) | |||||
| { | |||||
| const int right = x + w; | |||||
| const int bottom = y + h; | |||||
| const int iw = image->getWidth(); | |||||
| const int ih = image->getHeight(); | |||||
| int startX = x; | |||||
| getStartXY (startX, y); | |||||
| while (y < bottom) | |||||
| { | |||||
| x = startX; | |||||
| while (x < right) | |||||
| { | |||||
| context.setOpacity (opacity); | |||||
| context.blendImage (*image, x, y, iw, ih, 0, 0); | |||||
| x += iw; | |||||
| } | |||||
| y += ih; | |||||
| } | |||||
| } | |||||
| context.restoreState(); | |||||
| } | |||||
| void ImageBrush::paintPath (LowLevelGraphicsContext& context, | |||||
| const Path& path, const AffineTransform& transform) throw() | |||||
| { | |||||
| if (image != 0) | |||||
| { | |||||
| Rectangle clip (context.getClipBounds()); | |||||
| context.setOpacity (opacity); | |||||
| { | |||||
| float x, y, w, h; | |||||
| path.getBoundsTransformed (transform, x, y, w, h); | |||||
| clip = clip.getIntersection (Rectangle ((int) floorf (x), | |||||
| (int) floorf (y), | |||||
| 2 + (int) floorf (w), | |||||
| 2 + (int) floorf (h))); | |||||
| } | |||||
| int x = clip.getX(); | |||||
| int y = clip.getY(); | |||||
| const int right = clip.getRight(); | |||||
| const int bottom = clip.getBottom(); | |||||
| const int iw = image->getWidth(); | |||||
| const int ih = image->getHeight(); | |||||
| int startX = x; | |||||
| getStartXY (startX, y); | |||||
| while (y < bottom) | |||||
| { | |||||
| x = startX; | |||||
| while (x < right) | |||||
| { | |||||
| context.fillPathWithImage (path, transform, *image, x, y); | |||||
| x += iw; | |||||
| } | |||||
| y += ih; | |||||
| } | |||||
| } | |||||
| } | |||||
| void ImageBrush::paintAlphaChannel (LowLevelGraphicsContext& context, | |||||
| const Image& alphaChannelImage, int imageX, int imageY, | |||||
| int x, int y, int w, int h) throw() | |||||
| { | |||||
| context.saveState(); | |||||
| if (image != 0 && context.reduceClipRegion (x, y, w, h)) | |||||
| { | |||||
| context.setOpacity (opacity); | |||||
| const Rectangle clip (context.getClipBounds()); | |||||
| x = clip.getX(); | |||||
| y = clip.getY(); | |||||
| const int right = clip.getRight(); | |||||
| const int bottom = clip.getBottom(); | |||||
| const int iw = image->getWidth(); | |||||
| const int ih = image->getHeight(); | |||||
| int startX = x; | |||||
| getStartXY (startX, y); | |||||
| while (y < bottom) | |||||
| { | |||||
| x = startX; | |||||
| while (x < right) | |||||
| { | |||||
| context.fillAlphaChannelWithImage (alphaChannelImage, | |||||
| imageX, imageY, *image, | |||||
| x, y); | |||||
| x += iw; | |||||
| } | |||||
| y += ih; | |||||
| } | |||||
| } | |||||
| context.restoreState(); | |||||
| } | |||||
| END_JUCE_NAMESPACE | |||||
| @@ -1,104 +0,0 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-9 by Raw Material Software Ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||||
| Public License (Version 2), as published by the Free Software Foundation. | |||||
| A copy of the license is included in the JUCE distribution, or can be found | |||||
| online at www.gnu.org/licenses. | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #ifndef __JUCE_IMAGEBRUSH_JUCEHEADER__ | |||||
| #define __JUCE_IMAGEBRUSH_JUCEHEADER__ | |||||
| #include "juce_Brush.h" | |||||
| #include "../imaging/juce_Image.h" | |||||
| //============================================================================== | |||||
| /** | |||||
| A Brush that fills areas with tiled repetitions of an image. | |||||
| @see Brush, Graphics::setBrush, SolidColourBrush, GradientBrush | |||||
| */ | |||||
| class JUCE_API ImageBrush : public Brush | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| /* Creates an image brush, ready for use in Graphics::setBrush(). | |||||
| (x, y) is an anchor point for the top-left of the image | |||||
| A reference to the image passed in will be kept, so don't delete | |||||
| it within the lifetime of this object | |||||
| */ | |||||
| ImageBrush (Image* const image, | |||||
| const int anchorX, | |||||
| const int anchorY, | |||||
| const float opacity) throw(); | |||||
| /** Destructor. */ | |||||
| ~ImageBrush() throw(); | |||||
| //============================================================================== | |||||
| /** Returns the image currently being used. */ | |||||
| Image* getImage() const throw() { return image; } | |||||
| /** Returns the current anchor X position. */ | |||||
| int getAnchorX() const throw() { return anchorX; } | |||||
| /** Returns the current anchor Y position. */ | |||||
| int getAnchorY() const throw() { return anchorY; } | |||||
| /** Returns the current opacity. */ | |||||
| float getOpacity() const throw() { return opacity; } | |||||
| //============================================================================== | |||||
| Brush* createCopy() const throw(); | |||||
| void applyTransform (const AffineTransform& transform) throw(); | |||||
| void multiplyOpacity (const float multiple) throw(); | |||||
| bool isInvisible() const throw(); | |||||
| void paintPath (LowLevelGraphicsContext& context, | |||||
| const Path& path, const AffineTransform& transform) throw(); | |||||
| void paintRectangle (LowLevelGraphicsContext& context, | |||||
| int x, int y, int w, int h) throw(); | |||||
| void paintAlphaChannel (LowLevelGraphicsContext& context, | |||||
| const Image& alphaChannelImage, int imageX, int imageY, | |||||
| int x, int y, int w, int h) throw(); | |||||
| //============================================================================== | |||||
| juce_UseDebuggingNewOperator | |||||
| protected: | |||||
| Image* image; | |||||
| int anchorX, anchorY; | |||||
| float opacity; | |||||
| private: | |||||
| ImageBrush (const ImageBrush&); | |||||
| const ImageBrush& operator= (const ImageBrush&); | |||||
| void getStartXY (int& x, int& y) const throw(); | |||||
| }; | |||||
| #endif // __JUCE_IMAGEBRUSH_JUCEHEADER__ | |||||
| @@ -1,123 +0,0 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-9 by Raw Material Software Ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||||
| Public License (Version 2), as published by the Free Software Foundation. | |||||
| A copy of the license is included in the JUCE distribution, or can be found | |||||
| online at www.gnu.org/licenses. | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #include "../../../core/juce_StandardHeader.h" | |||||
| BEGIN_JUCE_NAMESPACE | |||||
| #include "juce_SolidColourBrush.h" | |||||
| #include "../contexts/juce_LowLevelGraphicsContext.h" | |||||
| //============================================================================== | |||||
| SolidColourBrush::SolidColourBrush() throw() | |||||
| : colour (0xff000000) | |||||
| { | |||||
| } | |||||
| SolidColourBrush::SolidColourBrush (const Colour& colour_) throw() | |||||
| : colour (colour_) | |||||
| { | |||||
| } | |||||
| SolidColourBrush::~SolidColourBrush() throw() | |||||
| { | |||||
| } | |||||
| Brush* SolidColourBrush::createCopy() const throw() | |||||
| { | |||||
| return new SolidColourBrush (colour); | |||||
| } | |||||
| void SolidColourBrush::applyTransform (const AffineTransform& /*transform*/) throw() | |||||
| { | |||||
| } | |||||
| void SolidColourBrush::multiplyOpacity (const float multiple) throw() | |||||
| { | |||||
| colour = colour.withMultipliedAlpha (multiple); | |||||
| } | |||||
| bool SolidColourBrush::isInvisible() const throw() | |||||
| { | |||||
| return colour.isTransparent(); | |||||
| } | |||||
| void SolidColourBrush::paintPath (LowLevelGraphicsContext& context, | |||||
| const Path& path, const AffineTransform& transform) throw() | |||||
| { | |||||
| context.setColour (colour); | |||||
| context.fillPath (path, transform); | |||||
| } | |||||
| void SolidColourBrush::paintRectangle (LowLevelGraphicsContext& context, | |||||
| int x, int y, int w, int h) throw() | |||||
| { | |||||
| context.setColour (colour); | |||||
| context.fillRect (x, y, w, h, false); | |||||
| } | |||||
| void SolidColourBrush::paintAlphaChannel (LowLevelGraphicsContext& context, | |||||
| const Image& alphaChannelImage, int imageX, int imageY, | |||||
| int x, int y, int w, int h) throw() | |||||
| { | |||||
| if (! colour.isTransparent()) | |||||
| { | |||||
| context.saveState(); | |||||
| if (context.reduceClipRegion (x, y, w, h)) | |||||
| { | |||||
| context.setColour (colour); | |||||
| context.fillAlphaChannel (alphaChannelImage, imageX, imageY); | |||||
| } | |||||
| context.restoreState(); | |||||
| } | |||||
| } | |||||
| void SolidColourBrush::paintVerticalLine (LowLevelGraphicsContext& context, | |||||
| int x, float y1, float y2) throw() | |||||
| { | |||||
| context.setColour (colour); | |||||
| context.drawVerticalLine (x, y1, y2); | |||||
| } | |||||
| void SolidColourBrush::paintHorizontalLine (LowLevelGraphicsContext& context, | |||||
| int y, float x1, float x2) throw() | |||||
| { | |||||
| context.setColour (colour); | |||||
| context.drawHorizontalLine (y, x1, x2); | |||||
| } | |||||
| void SolidColourBrush::paintLine (LowLevelGraphicsContext& context, | |||||
| float x1, float y1, float x2, float y2) throw() | |||||
| { | |||||
| context.setColour (colour); | |||||
| context.drawLine (x1, y1, x2, y2); | |||||
| } | |||||
| END_JUCE_NAMESPACE | |||||
| @@ -1,108 +0,0 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||||
| Copyright 2004-9 by Raw Material Software Ltd. | |||||
| ------------------------------------------------------------------------------ | |||||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||||
| Public License (Version 2), as published by the Free Software Foundation. | |||||
| A copy of the license is included in the JUCE distribution, or can be found | |||||
| online at www.gnu.org/licenses. | |||||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||||
| ------------------------------------------------------------------------------ | |||||
| To release a closed-source product which uses JUCE, commercial licenses are | |||||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||||
| ============================================================================== | |||||
| */ | |||||
| #ifndef __JUCE_SOLIDCOLOURBRUSH_JUCEHEADER__ | |||||
| #define __JUCE_SOLIDCOLOURBRUSH_JUCEHEADER__ | |||||
| #include "juce_Brush.h" | |||||
| #include "../colour/juce_Colour.h" | |||||
| //============================================================================== | |||||
| /** | |||||
| A Brush that fills its area with a solid (or semi-transparent) colour. | |||||
| An application won't normally need to use this class directly, as drawing | |||||
| with solid colours is taken care of automatically by the Graphics class | |||||
| (it actually uses one of these brushes internally when you set the colour | |||||
| with the Graphics::setColour() method). | |||||
| @see Brush, Graphics::setBrush, GradientBrush, ImageBrush | |||||
| */ | |||||
| class JUCE_API SolidColourBrush : public Brush | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| /** Creates a SolidColourBrush to draw with the given colour. | |||||
| The colour can be changed later with the setColour() method. | |||||
| */ | |||||
| SolidColourBrush (const Colour& colour) throw(); | |||||
| /** Creates a SolidColourBrush set to black. | |||||
| The colour can be changed later with the setColour() method. | |||||
| */ | |||||
| SolidColourBrush() throw(); | |||||
| /** Destructor. */ | |||||
| ~SolidColourBrush() throw(); | |||||
| //============================================================================== | |||||
| /** Returns the colour currently being used. */ | |||||
| const Colour& getColour() const throw() { return colour; } | |||||
| /** Sets the colour to use for drawing. */ | |||||
| void setColour (const Colour& newColour) throw() { colour = newColour; } | |||||
| //============================================================================== | |||||
| Brush* createCopy() const throw(); | |||||
| void applyTransform (const AffineTransform& transform) throw(); | |||||
| bool isInvisible() const throw(); | |||||
| void multiplyOpacity (const float multiple) throw(); | |||||
| void paintPath (LowLevelGraphicsContext& context, | |||||
| const Path& path, const AffineTransform& transform) throw(); | |||||
| void paintRectangle (LowLevelGraphicsContext& context, | |||||
| int x, int y, int w, int h) throw(); | |||||
| void paintAlphaChannel (LowLevelGraphicsContext& context, | |||||
| const Image& alphaChannelImage, int imageX, int imageY, | |||||
| int x, int y, int w, int h) throw(); | |||||
| void paintVerticalLine (LowLevelGraphicsContext& context, | |||||
| int x, float y1, float y2) throw(); | |||||
| void paintHorizontalLine (LowLevelGraphicsContext& context, | |||||
| int y, float x1, float x2) throw(); | |||||
| void paintLine (LowLevelGraphicsContext& context, | |||||
| float x1, float y1, float x2, float y2) throw(); | |||||
| //============================================================================== | |||||
| juce_UseDebuggingNewOperator | |||||
| private: | |||||
| Colour colour; | |||||
| SolidColourBrush (const SolidColourBrush&); | |||||
| const SolidColourBrush& operator= (const SolidColourBrush&); | |||||
| }; | |||||
| #endif // __JUCE_SOLIDCOLOURBRUSH_JUCEHEADER__ | |||||
| @@ -301,12 +301,18 @@ const Colour Colour::overlaidWith (const Colour& src) const throw() | |||||
| const Colour Colour::interpolatedWith (const Colour& other, float proportionOfOther) const throw() | const Colour Colour::interpolatedWith (const Colour& other, float proportionOfOther) const throw() | ||||
| { | { | ||||
| const int amount = jlimit (0, 256, (int) (proportionOfOther * 256.0f)); | |||||
| if (proportionOfOther <= 0) | |||||
| return *this; | |||||
| if (proportionOfOther >= 1.0f) | |||||
| return other; | |||||
| PixelARGB c1 (getPixelARGB()); | |||||
| const PixelARGB c2 (other.getPixelARGB()); | |||||
| c1.tween (c2, roundFloatToInt (proportionOfOther * 255.0f)); | |||||
| c1.unpremultiply(); | |||||
| return Colour ((uint8) (getRed() + (((other.getRed() - getRed()) * amount) >> 8)), | |||||
| (uint8) (getGreen() + (((other.getGreen() - getGreen()) * amount) >> 8)), | |||||
| (uint8) (getBlue() + (((other.getBlue() - getBlue()) * amount) >> 8)), | |||||
| (uint8) (getAlpha() + (((other.getAlpha() - getAlpha()) * amount) >> 8))); | |||||
| return Colour (c1.getARGB()); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -49,7 +49,8 @@ EdgeTable::EdgeTable (const Rectangle& bounds_, | |||||
| const Path& path, const AffineTransform& transform) throw() | const Path& path, const AffineTransform& transform) throw() | ||||
| : bounds (bounds_), | : bounds (bounds_), | ||||
| maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), | maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), | ||||
| lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1) | |||||
| lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), | |||||
| needToCheckEmptinesss (true) | |||||
| { | { | ||||
| table = (int*) juce_malloc ((bounds.getHeight() + 1) * lineStrideElements * sizeof (int)); | table = (int*) juce_malloc ((bounds.getHeight() + 1) * lineStrideElements * sizeof (int)); | ||||
| int* t = table; | int* t = table; | ||||
| @@ -167,7 +168,8 @@ EdgeTable::EdgeTable (const Rectangle& bounds_, | |||||
| EdgeTable::EdgeTable (const Rectangle& rectangleToAdd) throw() | EdgeTable::EdgeTable (const Rectangle& rectangleToAdd) throw() | ||||
| : bounds (rectangleToAdd), | : bounds (rectangleToAdd), | ||||
| maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), | maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), | ||||
| lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1) | |||||
| lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), | |||||
| needToCheckEmptinesss (true) | |||||
| { | { | ||||
| table = (int*) juce_malloc (jmax (1, bounds.getHeight()) * lineStrideElements * sizeof (int)); | table = (int*) juce_malloc (jmax (1, bounds.getHeight()) * lineStrideElements * sizeof (int)); | ||||
| *table = 0; | *table = 0; | ||||
| @@ -190,7 +192,8 @@ EdgeTable::EdgeTable (const Rectangle& rectangleToAdd) throw() | |||||
| EdgeTable::EdgeTable (const float x, const float y, const float w, const float h) throw() | EdgeTable::EdgeTable (const float x, const float y, const float w, const float h) throw() | ||||
| : bounds (Rectangle ((int) floorf (x), roundFloatToInt (y * 256.0f) >> 8, 2 + (int) w, 2 + (int) h)), | : bounds (Rectangle ((int) floorf (x), roundFloatToInt (y * 256.0f) >> 8, 2 + (int) w, 2 + (int) h)), | ||||
| maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), | maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine), | ||||
| lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1) | |||||
| lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1), | |||||
| needToCheckEmptinesss (true) | |||||
| { | { | ||||
| jassert (w > 0 && h > 0); | jassert (w > 0 && h > 0); | ||||
| table = (int*) juce_malloc (jmax (1, bounds.getHeight()) * lineStrideElements * sizeof (int)); | table = (int*) juce_malloc (jmax (1, bounds.getHeight()) * lineStrideElements * sizeof (int)); | ||||
| @@ -274,6 +277,7 @@ const EdgeTable& EdgeTable::operator= (const EdgeTable& other) throw() | |||||
| bounds = other.bounds; | bounds = other.bounds; | ||||
| maxEdgesPerLine = other.maxEdgesPerLine; | maxEdgesPerLine = other.maxEdgesPerLine; | ||||
| lineStrideElements = other.lineStrideElements; | lineStrideElements = other.lineStrideElements; | ||||
| needToCheckEmptinesss = other.needToCheckEmptinesss; | |||||
| const int tableSize = jmax (1, bounds.getHeight()) * lineStrideElements * sizeof (int); | const int tableSize = jmax (1, bounds.getHeight()) * lineStrideElements * sizeof (int); | ||||
| table = (int*) juce_malloc (tableSize); | table = (int*) juce_malloc (tableSize); | ||||
| @@ -358,6 +362,27 @@ void EdgeTable::addEdgePoint (const int x, const int y, const int winding) throw | |||||
| line[0]++; | line[0]++; | ||||
| } | } | ||||
| void EdgeTable::translate (float dx, int dy) throw() | |||||
| { | |||||
| bounds.setPosition (bounds.getX() + (int) floorf (dx), bounds.getY() + dy); | |||||
| int* lineStart = table; | |||||
| const int intDx = (int) (dx * 256.0f); | |||||
| for (int i = bounds.getHeight(); --i >= 0;) | |||||
| { | |||||
| int* line = lineStart; | |||||
| lineStart += lineStrideElements; | |||||
| int num = *line++; | |||||
| while (--num >= 0) | |||||
| { | |||||
| *line += intDx; | |||||
| line += 2; | |||||
| } | |||||
| } | |||||
| } | |||||
| void EdgeTable::intersectWithEdgeTableLine (const int y, const int* otherLine) throw() | void EdgeTable::intersectWithEdgeTableLine (const int y, const int* otherLine) throw() | ||||
| { | { | ||||
| jassert (y >= 0 && y < bounds.getHeight()); | jassert (y >= 0 && y < bounds.getHeight()); | ||||
| @@ -482,6 +507,7 @@ void EdgeTable::clipToRectangle (const Rectangle& r) throw() | |||||
| if (clipped.isEmpty()) | if (clipped.isEmpty()) | ||||
| { | { | ||||
| needToCheckEmptinesss = false; | |||||
| bounds.setHeight (0); | bounds.setHeight (0); | ||||
| } | } | ||||
| else | else | ||||
| @@ -505,6 +531,8 @@ void EdgeTable::clipToRectangle (const Rectangle& r) throw() | |||||
| for (int i = top; i < bottom; ++i) | for (int i = top; i < bottom; ++i) | ||||
| intersectWithEdgeTableLine (i, rectLine); | intersectWithEdgeTableLine (i, rectLine); | ||||
| } | } | ||||
| needToCheckEmptinesss = true; | |||||
| } | } | ||||
| } | } | ||||
| @@ -523,6 +551,8 @@ void EdgeTable::excludeRectangle (const Rectangle& r) throw() | |||||
| for (int i = top; i < bottom; ++i) | for (int i = top; i < bottom; ++i) | ||||
| intersectWithEdgeTableLine (i, rectLine); | intersectWithEdgeTableLine (i, rectLine); | ||||
| needToCheckEmptinesss = true; | |||||
| } | } | ||||
| } | } | ||||
| @@ -532,6 +562,7 @@ void EdgeTable::clipToEdgeTable (const EdgeTable& other) | |||||
| if (clipped.isEmpty()) | if (clipped.isEmpty()) | ||||
| { | { | ||||
| needToCheckEmptinesss = false; | |||||
| bounds.setHeight (0); | bounds.setHeight (0); | ||||
| } | } | ||||
| else | else | ||||
| @@ -555,109 +586,74 @@ void EdgeTable::clipToEdgeTable (const EdgeTable& other) | |||||
| intersectWithEdgeTableLine (i, otherLine); | intersectWithEdgeTableLine (i, otherLine); | ||||
| otherLine += other.lineStrideElements; | otherLine += other.lineStrideElements; | ||||
| } | } | ||||
| needToCheckEmptinesss = true; | |||||
| } | } | ||||
| } | } | ||||
| void EdgeTable::clipToImageAlpha (const Image& image, int x, int y) throw() | |||||
| void EdgeTable::clipLineToMask (int x, int y, uint8* mask, int maskStride, int numPixels) throw() | |||||
| { | { | ||||
| const Rectangle clipped (bounds.getIntersection (Rectangle (x, y, image.getWidth(), image.getHeight()))); | |||||
| y -= bounds.getY(); | |||||
| if (clipped.isEmpty()) | |||||
| { | |||||
| bounds.setHeight (0); | |||||
| } | |||||
| else | |||||
| { | |||||
| if (! image.hasAlphaChannel()) | |||||
| { | |||||
| clipToRectangle (clipped); | |||||
| return; | |||||
| } | |||||
| const int top = clipped.getY() - bounds.getY(); | |||||
| const int bottom = clipped.getBottom() - bounds.getY(); | |||||
| if (bottom < bounds.getHeight()) | |||||
| bounds.setHeight (bottom); | |||||
| if (y < 0 || y >= bounds.getHeight()) | |||||
| return; | |||||
| if (clipped.getRight() < bounds.getRight()) | |||||
| bounds.setRight (clipped.getRight()); | |||||
| needToCheckEmptinesss = true; | |||||
| for (int i = top; --i >= 0;) | |||||
| table [lineStrideElements * i] = 0; | |||||
| int imageX = clipped.getX() - x; | |||||
| int imageY = clipped.getY() - y; | |||||
| if (numPixels <= 0) | |||||
| { | |||||
| table [lineStrideElements * y] = 0; | |||||
| return; | |||||
| } | |||||
| int* temp = (int*) alloca ((clipped.getWidth() * 2 + 4) * sizeof (int)); | |||||
| int* tempLine = (int*) alloca ((numPixels * 2 + 4) * sizeof (int)); | |||||
| int destIndex = 0, lastLevel = 0; | |||||
| Image::BitmapData srcData (image, imageX, imageY, clipped.getWidth(), clipped.getHeight()); | |||||
| while (--numPixels >= 0) | |||||
| { | |||||
| const int alpha = *mask; | |||||
| mask += maskStride; | |||||
| for (int i = 0; i < clipped.getHeight(); ++i) | |||||
| if (alpha != lastLevel) | |||||
| { | { | ||||
| int destIndex = 0, lastLevel = 0; | |||||
| const uint8* pixels = srcData.getLinePointer (i); | |||||
| if (image.getFormat() == Image::ARGB) | |||||
| { | |||||
| for (int px = 0; px < clipped.getWidth(); ++px) | |||||
| { | |||||
| const int alpha = ((const PixelARGB*) pixels)->getAlpha(); | |||||
| pixels += srcData.pixelStride; | |||||
| if (alpha != lastLevel) | |||||
| { | |||||
| temp[++destIndex] = (clipped.getX() + px) << 8; | |||||
| temp[++destIndex] = alpha; | |||||
| lastLevel = alpha; | |||||
| } | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| jassert (image.getFormat() == Image::SingleChannel); | |||||
| tempLine[++destIndex] = (x << 8); | |||||
| tempLine[++destIndex] = alpha; | |||||
| lastLevel = alpha; | |||||
| } | |||||
| for (int px = 0; px < clipped.getWidth(); ++px) | |||||
| { | |||||
| const int alpha = *pixels; | |||||
| pixels += srcData.pixelStride; | |||||
| if (alpha != lastLevel) | |||||
| { | |||||
| temp[++destIndex] = (clipped.getX() + px) << 8; | |||||
| temp[++destIndex] = alpha; | |||||
| lastLevel = alpha; | |||||
| } | |||||
| } | |||||
| } | |||||
| ++x; | |||||
| } | |||||
| if (lastLevel > 0) | |||||
| { | |||||
| temp[++destIndex] = clipped.getRight() << 8; | |||||
| temp[++destIndex] = 0; | |||||
| } | |||||
| if (lastLevel > 0) | |||||
| { | |||||
| tempLine[++destIndex] = (x << 8); | |||||
| tempLine[++destIndex] = 0; | |||||
| } | |||||
| temp[0] = destIndex >> 1; | |||||
| tempLine[0] = destIndex >> 1; | |||||
| intersectWithEdgeTableLine (top + i, temp); | |||||
| ++y; | |||||
| } | |||||
| } | |||||
| intersectWithEdgeTableLine (y, tempLine); | |||||
| } | } | ||||
| bool EdgeTable::isEmpty() const throw() | |||||
| bool EdgeTable::isEmpty() throw() | |||||
| { | { | ||||
| int* t = table; | |||||
| for (int i = bounds.getHeight(); --i >= 0;) | |||||
| if (needToCheckEmptinesss) | |||||
| { | { | ||||
| if (t[0] > 1) | |||||
| return false; | |||||
| needToCheckEmptinesss = false; | |||||
| int* t = table; | |||||
| t += lineStrideElements; | |||||
| for (int i = bounds.getHeight(); --i >= 0;) | |||||
| { | |||||
| if (t[0] > 1) | |||||
| return false; | |||||
| t += lineStrideElements; | |||||
| } | |||||
| bounds.setHeight (0); | |||||
| } | } | ||||
| return true; | |||||
| return bounds.getHeight() == 0; | |||||
| } | } | ||||
| END_JUCE_NAMESPACE | END_JUCE_NAMESPACE | ||||
| @@ -78,9 +78,10 @@ public: | |||||
| void clipToRectangle (const Rectangle& r) throw(); | void clipToRectangle (const Rectangle& r) throw(); | ||||
| void excludeRectangle (const Rectangle& r) throw(); | void excludeRectangle (const Rectangle& r) throw(); | ||||
| void clipToEdgeTable (const EdgeTable& other); | void clipToEdgeTable (const EdgeTable& other); | ||||
| void clipToImageAlpha (const Image& image, int x, int y) throw(); | |||||
| bool isEmpty() const throw(); | |||||
| void clipLineToMask (int x, int y, uint8* mask, int maskStride, int numPixels) throw(); | |||||
| bool isEmpty() throw(); | |||||
| const Rectangle& getMaximumBounds() const throw() { return bounds; } | const Rectangle& getMaximumBounds() const throw() { return bounds; } | ||||
| void translate (float dx, int dy) throw(); | |||||
| /** Reduces the amount of space the table has allocated. | /** Reduces the amount of space the table has allocated. | ||||
| @@ -192,6 +193,7 @@ private: | |||||
| int* table; | int* table; | ||||
| Rectangle bounds; | Rectangle bounds; | ||||
| int maxEdgesPerLine, lineStrideElements; | int maxEdgesPerLine, lineStrideElements; | ||||
| bool needToCheckEmptinesss; | |||||
| void addEdgePoint (const int x, const int y, const int winding) throw(); | void addEdgePoint (const int x, const int y, const int winding) throw(); | ||||
| void remapTableForNumEdges (const int newNumEdgesPerLine) throw(); | void remapTableForNumEdges (const int newNumEdgesPerLine) throw(); | ||||
| @@ -31,8 +31,6 @@ BEGIN_JUCE_NAMESPACE | |||||
| #include "../fonts/juce_GlyphArrangement.h" | #include "../fonts/juce_GlyphArrangement.h" | ||||
| #include "../geometry/juce_PathStrokeType.h" | #include "../geometry/juce_PathStrokeType.h" | ||||
| #include "juce_LowLevelGraphicsContext.h" | #include "juce_LowLevelGraphicsContext.h" | ||||
| #include "../brushes/juce_GradientBrush.h" | |||||
| #include "../brushes/juce_ImageBrush.h" | |||||
| static const Graphics::ResamplingQuality defaultQuality = Graphics::mediumResamplingQuality; | static const Graphics::ResamplingQuality defaultQuality = Graphics::mediumResamplingQuality; | ||||
| @@ -65,7 +63,6 @@ LowLevelGraphicsContext::~LowLevelGraphicsContext() | |||||
| Graphics::Graphics (Image& imageToDrawOnto) throw() | Graphics::Graphics (Image& imageToDrawOnto) throw() | ||||
| : context (imageToDrawOnto.createLowLevelContext()), | : context (imageToDrawOnto.createLowLevelContext()), | ||||
| ownsContext (true), | ownsContext (true), | ||||
| state (new GraphicsState()), | |||||
| saveStatePending (false) | saveStatePending (false) | ||||
| { | { | ||||
| resetToDefaultState(); | resetToDefaultState(); | ||||
| @@ -74,7 +71,6 @@ Graphics::Graphics (Image& imageToDrawOnto) throw() | |||||
| Graphics::Graphics (LowLevelGraphicsContext* const internalContext) throw() | Graphics::Graphics (LowLevelGraphicsContext* const internalContext) throw() | ||||
| : context (internalContext), | : context (internalContext), | ||||
| ownsContext (false), | ownsContext (false), | ||||
| state (new GraphicsState()), | |||||
| saveStatePending (false) | saveStatePending (false) | ||||
| { | { | ||||
| resetToDefaultState(); | resetToDefaultState(); | ||||
| @@ -82,8 +78,6 @@ Graphics::Graphics (LowLevelGraphicsContext* const internalContext) throw() | |||||
| Graphics::~Graphics() throw() | Graphics::~Graphics() throw() | ||||
| { | { | ||||
| delete state; | |||||
| if (ownsContext) | if (ownsContext) | ||||
| delete context; | delete context; | ||||
| } | } | ||||
| @@ -106,20 +100,20 @@ bool Graphics::reduceClipRegion (const int x, const int y, | |||||
| const int w, const int h) throw() | const int w, const int h) throw() | ||||
| { | { | ||||
| saveStateIfPending(); | saveStateIfPending(); | ||||
| return context->reduceClipRegion (x, y, w, h); | |||||
| return context->clipToRectangle (Rectangle (x, y, w, h)); | |||||
| } | } | ||||
| bool Graphics::reduceClipRegion (const RectangleList& clipRegion) throw() | bool Graphics::reduceClipRegion (const RectangleList& clipRegion) throw() | ||||
| { | { | ||||
| saveStateIfPending(); | saveStateIfPending(); | ||||
| return context->reduceClipRegion (clipRegion); | |||||
| return context->clipToRectangleList (clipRegion); | |||||
| } | } | ||||
| void Graphics::excludeClipRegion (const int x, const int y, | void Graphics::excludeClipRegion (const int x, const int y, | ||||
| const int w, const int h) throw() | const int w, const int h) throw() | ||||
| { | { | ||||
| saveStateIfPending(); | saveStateIfPending(); | ||||
| context->excludeClipRegion (x, y, w, h); | |||||
| context->excludeClipRectangle (Rectangle (x, y, w, h)); | |||||
| } | } | ||||
| bool Graphics::isClipEmpty() const throw() | bool Graphics::isClipEmpty() const throw() | ||||
| @@ -141,29 +135,9 @@ void Graphics::saveState() throw() | |||||
| void Graphics::restoreState() throw() | void Graphics::restoreState() throw() | ||||
| { | { | ||||
| if (saveStatePending) | if (saveStatePending) | ||||
| { | |||||
| saveStatePending = false; | saveStatePending = false; | ||||
| } | |||||
| else | else | ||||
| { | |||||
| const int stackSize = stateStack.size(); | |||||
| if (stackSize > 0) | |||||
| { | |||||
| context->restoreState(); | |||||
| delete state; | |||||
| state = stateStack.getUnchecked (stackSize - 1); | |||||
| stateStack.removeLast (1, false); | |||||
| } | |||||
| else | |||||
| { | |||||
| // Trying to call restoreState() more times than you've called saveState() ! | |||||
| // Be careful to correctly match each saveState() with exactly one call to restoreState(). | |||||
| jassertfalse | |||||
| } | |||||
| } | |||||
| context->restoreState(); | |||||
| } | } | ||||
| void Graphics::saveStateIfPending() throw() | void Graphics::saveStateIfPending() throw() | ||||
| @@ -171,9 +145,7 @@ void Graphics::saveStateIfPending() throw() | |||||
| if (saveStatePending) | if (saveStatePending) | ||||
| { | { | ||||
| saveStatePending = false; | saveStatePending = false; | ||||
| context->saveState(); | context->saveState(); | ||||
| stateStack.add (new GraphicsState (*state)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -187,15 +159,13 @@ void Graphics::setOrigin (const int newOriginX, | |||||
| bool Graphics::clipRegionIntersects (const int x, const int y, | bool Graphics::clipRegionIntersects (const int x, const int y, | ||||
| const int w, const int h) const throw() | const int w, const int h) const throw() | ||||
| { | { | ||||
| return context->clipRegionIntersects (x, y, w, h); | |||||
| return context->clipRegionIntersects (Rectangle (x, y, w, h)); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void Graphics::setColour (const Colour& newColour) throw() | void Graphics::setColour (const Colour& newColour) throw() | ||||
| { | { | ||||
| saveStateIfPending(); | saveStateIfPending(); | ||||
| deleteAndZero (state->brush); | |||||
| context->setColour (newColour); | context->setColour (newColour); | ||||
| } | } | ||||
| @@ -205,75 +175,26 @@ void Graphics::setOpacity (const float newOpacity) throw() | |||||
| context->setOpacity (newOpacity); | context->setOpacity (newOpacity); | ||||
| } | } | ||||
| void Graphics::setBrush (const Brush* const newBrush) throw() | |||||
| { | |||||
| saveStateIfPending(); | |||||
| delete state->brush; | |||||
| state->brush = 0; | |||||
| if (newBrush != 0) | |||||
| { | |||||
| const SolidColourBrush* cb = dynamic_cast <const SolidColourBrush*> (newBrush); | |||||
| if (cb != 0) | |||||
| { | |||||
| setColour (cb->getColour()); | |||||
| } | |||||
| else | |||||
| { | |||||
| const GradientBrush* gb = dynamic_cast <const GradientBrush*> (newBrush); | |||||
| if (gb != 0) | |||||
| { | |||||
| setGradientFill (gb->getGradient()); | |||||
| } | |||||
| else | |||||
| { | |||||
| state->brush = newBrush->createCopy(); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| void Graphics::setGradientFill (const ColourGradient& gradient) throw() | void Graphics::setGradientFill (const ColourGradient& gradient) throw() | ||||
| { | { | ||||
| saveStateIfPending(); | saveStateIfPending(); | ||||
| deleteAndZero (state->brush); | |||||
| context->setGradient (gradient); | context->setGradient (gradient); | ||||
| } | } | ||||
| void Graphics::setTiledImageFill (Image& imageToUse, | |||||
| void Graphics::setTiledImageFill (const Image& imageToUse, | |||||
| const int anchorX, | const int anchorX, | ||||
| const int anchorY, | const int anchorY, | ||||
| const float opacity) throw() | const float opacity) throw() | ||||
| { | { | ||||
| saveStateIfPending(); | saveStateIfPending(); | ||||
| delete state->brush; | |||||
| state->brush = new ImageBrush (&imageToUse, anchorX, anchorY, opacity); | |||||
| } | |||||
| //============================================================================== | |||||
| Graphics::GraphicsState::GraphicsState() throw() | |||||
| : brush (0) | |||||
| { | |||||
| } | |||||
| Graphics::GraphicsState::GraphicsState (const GraphicsState& other) throw() | |||||
| : brush (other.brush != 0 ? other.brush->createCopy() : 0), | |||||
| font (other.font) | |||||
| { | |||||
| } | |||||
| Graphics::GraphicsState::~GraphicsState() throw() | |||||
| { | |||||
| delete brush; | |||||
| context->setTiledFill (imageToUse, anchorX, anchorY); | |||||
| context->setOpacity (opacity); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void Graphics::setFont (const Font& newFont) throw() | void Graphics::setFont (const Font& newFont) throw() | ||||
| { | { | ||||
| saveStateIfPending(); | saveStateIfPending(); | ||||
| state->font = newFont; | |||||
| context->setFont (newFont); | context->setFont (newFont); | ||||
| } | } | ||||
| @@ -281,8 +202,9 @@ void Graphics::setFont (const float newFontHeight, | |||||
| const int newFontStyleFlags) throw() | const int newFontStyleFlags) throw() | ||||
| { | { | ||||
| saveStateIfPending(); | saveStateIfPending(); | ||||
| state->font.setSizeAndStyle (newFontHeight, newFontStyleFlags, 1.0f, 0); | |||||
| context->setFont (state->font); | |||||
| Font f (context->getFont()); | |||||
| f.setSizeAndStyle (newFontHeight, newFontStyleFlags, 1.0f, 0); | |||||
| context->setFont (f); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -294,7 +216,7 @@ void Graphics::drawSingleLineText (const String& text, | |||||
| && startX < context->getClipBounds().getRight()) | && startX < context->getClipBounds().getRight()) | ||||
| { | { | ||||
| GlyphArrangement arr; | GlyphArrangement arr; | ||||
| arr.addLineOfText (state->font, text, (float) startX, (float) baselineY); | |||||
| arr.addLineOfText (context->getFont(), text, (float) startX, (float) baselineY); | |||||
| arr.draw (*this); | arr.draw (*this); | ||||
| } | } | ||||
| } | } | ||||
| @@ -305,7 +227,7 @@ void Graphics::drawTextAsPath (const String& text, | |||||
| if (text.isNotEmpty()) | if (text.isNotEmpty()) | ||||
| { | { | ||||
| GlyphArrangement arr; | GlyphArrangement arr; | ||||
| arr.addLineOfText (state->font, text, 0.0f, 0.0f); | |||||
| arr.addLineOfText (context->getFont(), text, 0.0f, 0.0f); | |||||
| arr.draw (*this, transform); | arr.draw (*this, transform); | ||||
| } | } | ||||
| } | } | ||||
| @@ -319,7 +241,7 @@ void Graphics::drawMultiLineText (const String& text, | |||||
| && startX < context->getClipBounds().getRight()) | && startX < context->getClipBounds().getRight()) | ||||
| { | { | ||||
| GlyphArrangement arr; | GlyphArrangement arr; | ||||
| arr.addJustifiedText (state->font, text, | |||||
| arr.addJustifiedText (context->getFont(), text, | |||||
| (float) startX, (float) baselineY, (float) maximumLineWidth, | (float) startX, (float) baselineY, (float) maximumLineWidth, | ||||
| Justification::left); | Justification::left); | ||||
| arr.draw (*this); | arr.draw (*this); | ||||
| @@ -334,11 +256,11 @@ void Graphics::drawText (const String& text, | |||||
| const Justification& justificationType, | const Justification& justificationType, | ||||
| const bool useEllipsesIfTooBig) const throw() | const bool useEllipsesIfTooBig) const throw() | ||||
| { | { | ||||
| if (text.isNotEmpty() && context->clipRegionIntersects (x, y, width, height)) | |||||
| if (text.isNotEmpty() && context->clipRegionIntersects (Rectangle (x, y, width, height))) | |||||
| { | { | ||||
| GlyphArrangement arr; | GlyphArrangement arr; | ||||
| arr.addCurtailedLineOfText (state->font, text, | |||||
| arr.addCurtailedLineOfText (context->getFont(), text, | |||||
| 0.0f, 0.0f, (float)width, | 0.0f, 0.0f, (float)width, | ||||
| useEllipsesIfTooBig); | useEllipsesIfTooBig); | ||||
| @@ -361,11 +283,11 @@ void Graphics::drawFittedText (const String& text, | |||||
| { | { | ||||
| if (text.isNotEmpty() | if (text.isNotEmpty() | ||||
| && width > 0 && height > 0 | && width > 0 && height > 0 | ||||
| && context->clipRegionIntersects (x, y, width, height)) | |||||
| && context->clipRegionIntersects (Rectangle (x, y, width, height))) | |||||
| { | { | ||||
| GlyphArrangement arr; | GlyphArrangement arr; | ||||
| arr.addFittedText (state->font, text, | |||||
| arr.addFittedText (context->getFont(), text, | |||||
| (float) x, (float) y, | (float) x, (float) y, | ||||
| (float) width, (float) height, | (float) width, (float) height, | ||||
| justification, | justification, | ||||
| @@ -385,18 +307,12 @@ void Graphics::fillRect (int x, | |||||
| // passing in a silly number can cause maths problems in rendering! | // passing in a silly number can cause maths problems in rendering! | ||||
| ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); | ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); | ||||
| if (state->brush == 0) | |||||
| context->fillRect (x, y, width, height, false); | |||||
| else | |||||
| state->brush->paintRectangle (*context, x, y, width, height); | |||||
| context->fillRect (Rectangle (x, y, width, height), false); | |||||
| } | } | ||||
| void Graphics::fillRect (const Rectangle& r) const throw() | void Graphics::fillRect (const Rectangle& r) const throw() | ||||
| { | { | ||||
| fillRect (r.getX(), | |||||
| r.getY(), | |||||
| r.getWidth(), | |||||
| r.getHeight()); | |||||
| context->fillRect (r, false); | |||||
| } | } | ||||
| void Graphics::fillRect (const float x, | void Graphics::fillRect (const float x, | ||||
| @@ -414,13 +330,7 @@ void Graphics::fillRect (const float x, | |||||
| void Graphics::setPixel (int x, int y) const throw() | void Graphics::setPixel (int x, int y) const throw() | ||||
| { | { | ||||
| if (context->clipRegionIntersects (x, y, 1, 1)) | |||||
| { | |||||
| if (state->brush == 0) | |||||
| context->fillRect (x, y, 1, 1, false); | |||||
| else | |||||
| state->brush->paintRectangle (*context, x, y, 1, 1); | |||||
| } | |||||
| context->fillRect (Rectangle (x, y, 1, 1), false); | |||||
| } | } | ||||
| void Graphics::fillAll() const throw() | void Graphics::fillAll() const throw() | ||||
| @@ -436,7 +346,7 @@ void Graphics::fillAll (const Colour& colourToUse) const throw() | |||||
| context->saveState(); | context->saveState(); | ||||
| context->setColour (colourToUse); | context->setColour (colourToUse); | ||||
| context->fillRect (clip.getX(), clip.getY(), clip.getWidth(), clip.getHeight(), false); | |||||
| context->fillRect (clip, false); | |||||
| context->restoreState(); | context->restoreState(); | ||||
| } | } | ||||
| } | } | ||||
| @@ -447,24 +357,16 @@ void Graphics::fillPath (const Path& path, | |||||
| const AffineTransform& transform) const throw() | const AffineTransform& transform) const throw() | ||||
| { | { | ||||
| if ((! context->isClipEmpty()) && ! path.isEmpty()) | if ((! context->isClipEmpty()) && ! path.isEmpty()) | ||||
| { | |||||
| if (state->brush == 0) | |||||
| context->fillPath (path, transform); | |||||
| else | |||||
| state->brush->paintPath (*context, path, transform); | |||||
| } | |||||
| context->fillPath (path, transform); | |||||
| } | } | ||||
| void Graphics::strokePath (const Path& path, | void Graphics::strokePath (const Path& path, | ||||
| const PathStrokeType& strokeType, | const PathStrokeType& strokeType, | ||||
| const AffineTransform& transform) const throw() | const AffineTransform& transform) const throw() | ||||
| { | { | ||||
| // if ((! state->colour.isTransparent()) || state->brush != 0) | |||||
| { | |||||
| Path stroke; | |||||
| strokeType.createStrokedPath (stroke, path, transform); | |||||
| fillPath (stroke); | |||||
| } | |||||
| Path stroke; | |||||
| strokeType.createStrokedPath (stroke, path, transform); | |||||
| fillPath (stroke); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -477,21 +379,10 @@ void Graphics::drawRect (const int x, | |||||
| // passing in a silly number can cause maths problems in rendering! | // passing in a silly number can cause maths problems in rendering! | ||||
| ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); | ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (x, y, width, height); | ||||
| if (state->brush == 0) | |||||
| { | |||||
| context->fillRect (x, y, width, lineThickness, false); | |||||
| context->fillRect (x, y + lineThickness, lineThickness, height - lineThickness * 2, false); | |||||
| context->fillRect (x + width - lineThickness, y + lineThickness, lineThickness, height - lineThickness * 2, false); | |||||
| context->fillRect (x, y + height - lineThickness, width, lineThickness, false); | |||||
| } | |||||
| else | |||||
| { | |||||
| Brush& b = *(state->brush); | |||||
| b.paintRectangle (*context, x, y, width, lineThickness); | |||||
| b.paintRectangle (*context, x, y + lineThickness, lineThickness, height - lineThickness * 2); | |||||
| b.paintRectangle (*context, x + width - lineThickness, y + lineThickness, lineThickness, height - lineThickness * 2); | |||||
| b.paintRectangle (*context, x, y + height - lineThickness, width, lineThickness); | |||||
| } | |||||
| context->fillRect (Rectangle (x, y, width, lineThickness), false); | |||||
| context->fillRect (Rectangle (x, y + lineThickness, lineThickness, height - lineThickness * 2), false); | |||||
| context->fillRect (Rectangle (x + width - lineThickness, y + lineThickness, lineThickness, height - lineThickness * 2), false); | |||||
| context->fillRect (Rectangle (x, y + height - lineThickness, width, lineThickness), false); | |||||
| } | } | ||||
| void Graphics::drawRect (const float x, | void Graphics::drawRect (const float x, | ||||
| @@ -545,13 +436,13 @@ void Graphics::drawBevel (const int x, | |||||
| : oldOpacity; | : oldOpacity; | ||||
| context->setColour (topLeftColour.withMultipliedAlpha (op)); | context->setColour (topLeftColour.withMultipliedAlpha (op)); | ||||
| context->fillRect (x + i, y + i, width - i * 2, 1, false); | |||||
| context->fillRect (Rectangle (x + i, y + i, width - i * 2, 1), false); | |||||
| context->setColour (topLeftColour.withMultipliedAlpha (op * 0.75f)); | context->setColour (topLeftColour.withMultipliedAlpha (op * 0.75f)); | ||||
| context->fillRect (x + i, y + i + 1, 1, height - i * 2 - 2, false); | |||||
| context->fillRect (Rectangle (x + i, y + i + 1, 1, height - i * 2 - 2), false); | |||||
| context->setColour (bottomRightColour.withMultipliedAlpha (op)); | context->setColour (bottomRightColour.withMultipliedAlpha (op)); | ||||
| context->fillRect (x + i, y + height - i - 1, width - i * 2, 1, false); | |||||
| context->fillRect (Rectangle (x + i, y + height - i - 1, width - i * 2, 1), false); | |||||
| context->setColour (bottomRightColour.withMultipliedAlpha (op * 0.75f)); | context->setColour (bottomRightColour.withMultipliedAlpha (op * 0.75f)); | ||||
| context->fillRect (x + width - i - 1, y + i + 1, 1, height - i * 2 - 2, false); | |||||
| context->fillRect (Rectangle (x + width - i - 1, y + i + 1, 1, height - i * 2 - 2), false); | |||||
| } | } | ||||
| context->restoreState(); | context->restoreState(); | ||||
| @@ -667,7 +558,7 @@ void Graphics::fillCheckerBoard (int x, int y, | |||||
| if (colour1 == colour2) | if (colour1 == colour2) | ||||
| { | { | ||||
| context->setColour (colour1); | context->setColour (colour1); | ||||
| context->fillRect (x, y, width, height, false); | |||||
| context->fillRect (Rectangle (x, y, width, height), false); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -684,9 +575,7 @@ void Graphics::fillCheckerBoard (int x, int y, | |||||
| for (int xx = x; xx < right; xx += checkWidth) | for (int xx = x; xx < right; xx += checkWidth) | ||||
| { | { | ||||
| context->setColour (((cx++ & 1) == 0) ? colour1 : colour2); | context->setColour (((cx++ & 1) == 0) ? colour1 : colour2); | ||||
| context->fillRect (xx, y, | |||||
| jmin (checkWidth, right - xx), | |||||
| jmin (checkHeight, bottom - y), | |||||
| context->fillRect (Rectangle (xx, y, jmin (checkWidth, right - xx), jmin (checkHeight, bottom - y)), | |||||
| false); | false); | ||||
| } | } | ||||
| @@ -702,30 +591,17 @@ void Graphics::fillCheckerBoard (int x, int y, | |||||
| //============================================================================== | //============================================================================== | ||||
| void Graphics::drawVerticalLine (const int x, float top, float bottom) const throw() | void Graphics::drawVerticalLine (const int x, float top, float bottom) const throw() | ||||
| { | { | ||||
| if (state->brush == 0) | |||||
| context->drawVerticalLine (x, top, bottom); | |||||
| else | |||||
| state->brush->paintVerticalLine (*context, x, top, bottom); | |||||
| context->drawVerticalLine (x, top, bottom); | |||||
| } | } | ||||
| void Graphics::drawHorizontalLine (const int y, float left, float right) const throw() | void Graphics::drawHorizontalLine (const int y, float left, float right) const throw() | ||||
| { | { | ||||
| if (state->brush == 0) | |||||
| context->drawHorizontalLine (y, left, right); | |||||
| else | |||||
| state->brush->paintHorizontalLine (*context, y, left, right); | |||||
| context->drawHorizontalLine (y, left, right); | |||||
| } | } | ||||
| void Graphics::drawLine (float x1, float y1, | |||||
| float x2, float y2) const throw() | |||||
| void Graphics::drawLine (float x1, float y1, float x2, float y2) const throw() | |||||
| { | { | ||||
| if (! context->isClipEmpty()) | |||||
| { | |||||
| if (state->brush == 0) | |||||
| context->drawLine (x1, y1, x2, y2); | |||||
| else | |||||
| state->brush->paintLine (*context, x1, y1, x2, y2); | |||||
| } | |||||
| context->drawLine (x1, y1, x2, y2); | |||||
| } | } | ||||
| void Graphics::drawLine (const float startX, | void Graphics::drawLine (const float startX, | ||||
| @@ -864,126 +740,14 @@ void Graphics::drawImage (const Image* const imageToDraw, | |||||
| ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (dx, dy, dw, dh); | ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (dx, dy, dw, dh); | ||||
| ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (sx, sy, sw, sh); | ASSERT_COORDS_ARE_SENSIBLE_NUMBERS (sx, sy, sw, sh); | ||||
| if (imageToDraw == 0 || ! context->clipRegionIntersects (dx, dy, dw, dh)) | |||||
| if (! context->clipRegionIntersects (Rectangle (dx, dy, dw, dh))) | |||||
| return; | return; | ||||
| if (sw == dw && sh == dh) | |||||
| { | |||||
| if (sx < 0) | |||||
| { | |||||
| dx -= sx; | |||||
| dw += sx; | |||||
| sw += sx; | |||||
| sx = 0; | |||||
| } | |||||
| if (sx + sw > imageToDraw->getWidth()) | |||||
| { | |||||
| const int amount = sx + sw - imageToDraw->getWidth(); | |||||
| dw -= amount; | |||||
| sw -= amount; | |||||
| } | |||||
| if (sy < 0) | |||||
| { | |||||
| dy -= sy; | |||||
| dh += sy; | |||||
| sh += sy; | |||||
| sy = 0; | |||||
| } | |||||
| if (sy + sh > imageToDraw->getHeight()) | |||||
| { | |||||
| const int amount = sy + sh - imageToDraw->getHeight(); | |||||
| dh -= amount; | |||||
| sh -= amount; | |||||
| } | |||||
| if (dw <= 0 || dh <= 0 || sw <= 0 || sh <= 0) | |||||
| return; | |||||
| if (fillAlphaChannelWithCurrentBrush) | |||||
| { | |||||
| if (state->brush == 0) | |||||
| { | |||||
| context->saveState(); | |||||
| if (context->reduceClipRegion (dx, dy, dw, dh)) | |||||
| context->fillAlphaChannel (*imageToDraw, dx - sx, dy - sy); | |||||
| context->restoreState(); | |||||
| } | |||||
| else | |||||
| { | |||||
| state->brush->paintAlphaChannel (*context, *imageToDraw, | |||||
| dx - sx, dy - sy, | |||||
| dx, dy, dw, dh); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| context->blendImage (*imageToDraw, | |||||
| dx, dy, dw, dh, sx, sy); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| if (dw <= 0 || dh <= 0 || sw <= 0 || sh <= 0) | |||||
| return; | |||||
| if (fillAlphaChannelWithCurrentBrush) | |||||
| { | |||||
| if (imageToDraw->isRGB()) | |||||
| { | |||||
| fillRect (dx, dy, dw, dh); | |||||
| } | |||||
| else | |||||
| { | |||||
| int tx = dx; | |||||
| int ty = dy; | |||||
| int tw = dw; | |||||
| int th = dh; | |||||
| if (context->getClipBounds().intersectRectangle (tx, ty, tw, th)) | |||||
| { | |||||
| Image temp (imageToDraw->getFormat(), tw, th, true); | |||||
| Graphics g (temp); | |||||
| //xxx g.setImageResamplingQuality (state->quality); | |||||
| g.setOrigin (dx - tx, dy - ty); | |||||
| g.drawImage (imageToDraw, | |||||
| 0, 0, dw, dh, | |||||
| sx, sy, sw, sh, | |||||
| false); | |||||
| if (state->brush == 0) | |||||
| { | |||||
| context->saveState(); | |||||
| if (context->reduceClipRegion (tx, ty, tw, th)) | |||||
| context->fillAlphaChannel (temp, tx, ty); | |||||
| context->restoreState(); | |||||
| } | |||||
| else | |||||
| { | |||||
| state->brush->paintAlphaChannel (*context, temp, tx, ty, tx, ty, tw, th); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| context->blendImageWarping (*imageToDraw, | |||||
| sx, sy, sw, sh, | |||||
| AffineTransform::translation ((float) -sx, | |||||
| (float) -sy) | |||||
| .scaled (dw / (float) sw, | |||||
| dh / (float) sh) | |||||
| .translated ((float) dx, | |||||
| (float) dy)); | |||||
| } | |||||
| } | |||||
| drawImageTransformed (imageToDraw, sx, sy, sw, sh, | |||||
| AffineTransform::translation ((float) -sx, (float) -sy) | |||||
| .scaled (dw / (float) sw, dh / (float) sh) | |||||
| .translated ((float) dx, (float) dy), | |||||
| fillAlphaChannelWithCurrentBrush); | |||||
| } | } | ||||
| void Graphics::drawImageTransformed (const Image* const imageToDraw, | void Graphics::drawImageTransformed (const Image* const imageToDraw, | ||||
| @@ -994,72 +758,96 @@ void Graphics::drawImageTransformed (const Image* const imageToDraw, | |||||
| const AffineTransform& transform, | const AffineTransform& transform, | ||||
| const bool fillAlphaChannelWithCurrentBrush) const throw() | const bool fillAlphaChannelWithCurrentBrush) const throw() | ||||
| { | { | ||||
| if (imageToDraw != 0 | |||||
| && (! context->isClipEmpty()) | |||||
| && ! transform.isSingularity()) | |||||
| if (imageToDraw != 0 && ! context->isClipEmpty()) | |||||
| { | { | ||||
| if (transform.isIdentity()) | |||||
| const Rectangle srcClip (Rectangle (sourceClipX, sourceClipY, sourceClipWidth, sourceClipHeight)); | |||||
| if (fillAlphaChannelWithCurrentBrush) | |||||
| { | { | ||||
| drawImage (imageToDraw, | |||||
| sourceClipX, sourceClipY, sourceClipWidth, sourceClipHeight, | |||||
| sourceClipX, sourceClipY, sourceClipWidth, sourceClipHeight, | |||||
| fillAlphaChannelWithCurrentBrush); | |||||
| context->saveState(); | |||||
| context->clipToImageAlpha (*imageToDraw, srcClip, transform); | |||||
| fillAll(); | |||||
| context->restoreState(); | |||||
| } | } | ||||
| else if (fillAlphaChannelWithCurrentBrush) | |||||
| else | |||||
| { | { | ||||
| Path p; | |||||
| p.addRectangle ((float) sourceClipX, (float) sourceClipY, | |||||
| (float) sourceClipWidth, (float) sourceClipHeight); | |||||
| context->drawImage (*imageToDraw, srcClip, transform, false); | |||||
| } | |||||
| } | |||||
| } | |||||
| p.applyTransform (transform); | |||||
| //============================================================================== | |||||
| Graphics::FillType::FillType() throw() | |||||
| : colour (0xff000000), gradient (0), | |||||
| image (0), imageX (0), imageY (0) | |||||
| { | |||||
| } | |||||
| float dx, dy, dw, dh; | |||||
| p.getBounds (dx, dy, dw, dh); | |||||
| int tx = (int) dx; | |||||
| int ty = (int) dy; | |||||
| int tw = roundFloatToInt (dw) + 2; | |||||
| int th = roundFloatToInt (dh) + 2; | |||||
| Graphics::FillType::FillType (const Colour& colour_) throw() | |||||
| : colour (colour_), gradient (0), | |||||
| image (0), imageX (0), imageY (0) | |||||
| { | |||||
| } | |||||
| if (context->getClipBounds().intersectRectangle (tx, ty, tw, th)) | |||||
| { | |||||
| Image temp (imageToDraw->getFormat(), tw, th, true); | |||||
| Graphics g (temp); | |||||
| //xxx g.setImageResamplingQuality (state->quality); | |||||
| g.drawImageTransformed (imageToDraw, | |||||
| sourceClipX, | |||||
| sourceClipY, | |||||
| sourceClipWidth, | |||||
| sourceClipHeight, | |||||
| transform.translated ((float) -tx, (float) -ty), | |||||
| false); | |||||
| if (state->brush == 0) | |||||
| { | |||||
| context->saveState(); | |||||
| Graphics::FillType::FillType (const ColourGradient& gradient) throw() | |||||
| : colour (0xff000000), gradient (new ColourGradient (gradient)), | |||||
| image (0), imageX (0), imageY (0) | |||||
| { | |||||
| } | |||||
| if (context->reduceClipRegion (tx, ty, tw, th)) | |||||
| context->fillAlphaChannel (temp, tx, ty); | |||||
| Graphics::FillType::FillType (Image* const image_, const int x, const int y) throw() | |||||
| : colour (0xff000000), gradient (0), | |||||
| image (image_), imageX (x), imageY (y) | |||||
| { | |||||
| } | |||||
| context->restoreState(); | |||||
| } | |||||
| else | |||||
| { | |||||
| state->brush->paintAlphaChannel (*context, temp, tx, ty, tx, ty, tw, th); | |||||
| } | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| context->blendImageWarping (*imageToDraw, | |||||
| sourceClipX, | |||||
| sourceClipY, | |||||
| sourceClipWidth, | |||||
| sourceClipHeight, | |||||
| transform); | |||||
| } | |||||
| Graphics::FillType::FillType (const FillType& other) throw() | |||||
| : colour (other.colour), | |||||
| gradient (other.gradient != 0 ? new ColourGradient (*other.gradient) : 0), | |||||
| image (other.image), imageX (other.imageX), imageY (other.imageY) | |||||
| { | |||||
| } | |||||
| const Graphics::FillType& Graphics::FillType::operator= (const FillType& other) throw() | |||||
| { | |||||
| if (this != &other) | |||||
| { | |||||
| colour = other.colour; | |||||
| delete gradient; | |||||
| gradient = (other.gradient != 0 ? new ColourGradient (*other.gradient) : 0); | |||||
| image = other.image; | |||||
| imageX = other.imageX; | |||||
| imageY = other.imageY; | |||||
| } | } | ||||
| return *this; | |||||
| } | |||||
| Graphics::FillType::~FillType() throw() | |||||
| { | |||||
| delete gradient; | |||||
| } | } | ||||
| void Graphics::FillType::setColour (const Colour& newColour) throw() | |||||
| { | |||||
| deleteAndZero (gradient); | |||||
| colour = newColour; | |||||
| } | |||||
| void Graphics::FillType::setGradient (const ColourGradient& newGradient) throw() | |||||
| { | |||||
| if (gradient != 0) | |||||
| *gradient = newGradient; | |||||
| else | |||||
| gradient = new ColourGradient (newGradient); | |||||
| } | |||||
| void Graphics::FillType::setTiledImage (const Image& image_, const int imageX_, const int imageY_) throw() | |||||
| { | |||||
| deleteAndZero (gradient); | |||||
| image = &image_; | |||||
| imageX = imageX_; | |||||
| imageY = imageY_; | |||||
| } | |||||
| END_JUCE_NAMESPACE | END_JUCE_NAMESPACE | ||||
| @@ -32,7 +32,6 @@ | |||||
| #include "../geometry/juce_Line.h" | #include "../geometry/juce_Line.h" | ||||
| #include "../colour/juce_Colours.h" | #include "../colour/juce_Colours.h" | ||||
| #include "../colour/juce_ColourGradient.h" | #include "../colour/juce_ColourGradient.h" | ||||
| #include "../brushes/juce_SolidColourBrush.h" | |||||
| #include "juce_RectanglePlacement.h" | #include "juce_RectanglePlacement.h" | ||||
| class LowLevelGraphicsContext; | class LowLevelGraphicsContext; | ||||
| class Image; | class Image; | ||||
| @@ -79,7 +78,7 @@ public: | |||||
| If a brush is being used when this method is called, the brush will be deselected, | If a brush is being used when this method is called, the brush will be deselected, | ||||
| and any subsequent drawing will be done with a solid colour brush instead. | and any subsequent drawing will be done with a solid colour brush instead. | ||||
| @see setOpacity, setBrush | |||||
| @see setOpacity | |||||
| */ | */ | ||||
| void setColour (const Colour& newColour) throw(); | void setColour (const Colour& newColour) throw(); | ||||
| @@ -94,18 +93,6 @@ public: | |||||
| */ | */ | ||||
| void setOpacity (const float newOpacity) throw(); | void setOpacity (const float newOpacity) throw(); | ||||
| /** Changes the current brush to use for drawing. | |||||
| If a null pointer is passed in, the context will revert to using a solid | |||||
| colour for drawing (using the last colour set by setColour()). | |||||
| If a brush is passed in, a copy of it will be used for subsequent drawing | |||||
| operations until setColour() or setBrush() is called. | |||||
| @see SolidColourBrush, GradientBrush, ImageBrush, Brush | |||||
| */ | |||||
| void setBrush (const Brush* const newBrush) throw(); | |||||
| /** Sets the context to use a gradient for its fill pattern. | /** Sets the context to use a gradient for its fill pattern. | ||||
| */ | */ | ||||
| void setGradientFill (const ColourGradient& gradient) throw(); | void setGradientFill (const ColourGradient& gradient) throw(); | ||||
| @@ -114,7 +101,7 @@ public: | |||||
| Make sure that you don't delete this image while it's still being used by | Make sure that you don't delete this image while it's still being used by | ||||
| this context! | this context! | ||||
| */ | */ | ||||
| void setTiledImageFill (Image& imageToUse, | |||||
| void setTiledImageFill (const Image& imageToUse, | |||||
| const int anchorX, | const int anchorX, | ||||
| const int anchorY, | const int anchorY, | ||||
| const float opacity) throw(); | const float opacity) throw(); | ||||
| @@ -698,12 +685,13 @@ public: | |||||
| LowLevelGraphicsContext* getInternalContext() const throw() { return context; } | LowLevelGraphicsContext* getInternalContext() const throw() { return context; } | ||||
| //============================================================================== | //============================================================================== | ||||
| /*class FillType | |||||
| class FillType | |||||
| { | { | ||||
| public: | public: | ||||
| FillType() throw(); | |||||
| FillType (const Colour& colour) throw(); | FillType (const Colour& colour) throw(); | ||||
| FillType (const ColourGradient& gradient) throw(); | FillType (const ColourGradient& gradient) throw(); | ||||
| FillType (Image* image, int x, int y) throw(); | |||||
| FillType (Image* const image, const int x, const int y) throw(); | |||||
| FillType (const FillType& other) throw(); | FillType (const FillType& other) throw(); | ||||
| const FillType& operator= (const FillType& other) throw(); | const FillType& operator= (const FillType& other) throw(); | ||||
| ~FillType() throw(); | ~FillType() throw(); | ||||
| @@ -714,35 +702,22 @@ public: | |||||
| void setColour (const Colour& newColour) throw(); | void setColour (const Colour& newColour) throw(); | ||||
| void setGradient (const ColourGradient& newGradient) throw(); | void setGradient (const ColourGradient& newGradient) throw(); | ||||
| void setTiledImage (Image* image, const int imageX, const int imageY) throw(); | |||||
| void setTiledImage (const Image& image, const int imageX, const int imageY) throw(); | |||||
| Colour colour; | Colour colour; | ||||
| ColourGradient* gradient; | ColourGradient* gradient; | ||||
| Image* image; | |||||
| const Image* image; | |||||
| int imageX, imageY; | int imageX, imageY; | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| };*/ | |||||
| }; | |||||
| private: | private: | ||||
| //============================================================================== | //============================================================================== | ||||
| LowLevelGraphicsContext* const context; | LowLevelGraphicsContext* const context; | ||||
| const bool ownsContext; | const bool ownsContext; | ||||
| struct GraphicsState | |||||
| { | |||||
| GraphicsState() throw(); | |||||
| GraphicsState (const GraphicsState&) throw(); | |||||
| ~GraphicsState() throw(); | |||||
| Brush* brush; | |||||
| Font font; | |||||
| }; | |||||
| GraphicsState* state; | |||||
| OwnedArray <GraphicsState> stateStack; | |||||
| bool saveStatePending; | bool saveStatePending; | ||||
| void saveStateIfPending() throw(); | void saveStateIfPending() throw(); | ||||
| const Graphics& operator= (const Graphics& other); | const Graphics& operator= (const Graphics& other); | ||||
| @@ -66,57 +66,40 @@ public: | |||||
| */ | */ | ||||
| virtual void setOrigin (int x, int y) = 0; | virtual void setOrigin (int x, int y) = 0; | ||||
| /** Cliping co-ords are relative to the origin. */ | |||||
| virtual bool reduceClipRegion (int x, int y, int w, int h) = 0; | |||||
| virtual bool clipToRectangle (const Rectangle& r) = 0; | |||||
| virtual bool clipToRectangleList (const RectangleList& clipRegion) = 0; | |||||
| virtual void excludeClipRectangle (const Rectangle& r) = 0; | |||||
| virtual void clipToPath (const Path& path, const AffineTransform& transform) = 0; | |||||
| virtual void clipToImageAlpha (const Image& sourceImage, const Rectangle& srcClip, const AffineTransform& transform) = 0; | |||||
| /** Cliping co-ords are relative to the origin. */ | |||||
| virtual bool reduceClipRegion (const RectangleList& clipRegion) = 0; | |||||
| //virtual bool clipToPath (const Path& path) = 0; | |||||
| //virtual bool clipToImageAlpha (Image& image, int imageX, int imageY) = 0; | |||||
| /** Cliping co-ords are relative to the origin. */ | |||||
| virtual void excludeClipRegion (int x, int y, int w, int h) = 0; | |||||
| virtual bool clipRegionIntersects (const Rectangle& r) = 0; | |||||
| virtual const Rectangle getClipBounds() const = 0; | |||||
| virtual bool isClipEmpty() const = 0; | |||||
| virtual void saveState() = 0; | virtual void saveState() = 0; | ||||
| virtual void restoreState() = 0; | virtual void restoreState() = 0; | ||||
| virtual bool clipRegionIntersects (int x, int y, int w, int h) = 0; | |||||
| virtual const Rectangle getClipBounds() const = 0; | |||||
| virtual bool isClipEmpty() const = 0; | |||||
| //============================================================================== | //============================================================================== | ||||
| virtual void setColour (const Colour& colour) = 0; | virtual void setColour (const Colour& colour) = 0; | ||||
| virtual void setGradient (const ColourGradient& gradient) = 0; | virtual void setGradient (const ColourGradient& gradient) = 0; | ||||
| virtual void setTiledFill (const Image& image, int x, int y) = 0; | |||||
| virtual void setOpacity (float opacity) = 0; | virtual void setOpacity (float opacity) = 0; | ||||
| virtual void setInterpolationQuality (Graphics::ResamplingQuality quality) = 0; | virtual void setInterpolationQuality (Graphics::ResamplingQuality quality) = 0; | ||||
| //============================================================================== | //============================================================================== | ||||
| virtual void fillRect (int x, int y, int w, int h, const bool replaceExistingContents) = 0; | |||||
| virtual void fillRect (const Rectangle& r, const bool replaceExistingContents) = 0; | |||||
| virtual void fillPath (const Path& path, const AffineTransform& transform) = 0; | virtual void fillPath (const Path& path, const AffineTransform& transform) = 0; | ||||
| virtual void fillPathWithImage (const Path& path, const AffineTransform& transform, | |||||
| const Image& image, int imageX, int imageY) = 0; | |||||
| virtual void fillAlphaChannel (const Image& alphaImage, int alphaImageX, int alphaImageY) = 0; | |||||
| virtual void fillAlphaChannelWithImage (const Image& alphaImage, int alphaImageX, int alphaImageY, | |||||
| const Image& fillerImage, int fillerImageX, int fillerImageY) = 0; | |||||
| //============================================================================== | |||||
| virtual void blendImage (const Image& sourceImage, | |||||
| int destX, int destY, int destW, int destH, int sourceX, int sourceY) = 0; | |||||
| virtual void blendImageWarping (const Image& sourceImage, | |||||
| int srcClipX, int srcClipY, int srcClipW, int srcClipH, | |||||
| const AffineTransform& transform) = 0; | |||||
| virtual void drawImage (const Image& sourceImage, const Rectangle& srcClip, | |||||
| const AffineTransform& transform, const bool fillEntireClipAsTiles) = 0; | |||||
| //============================================================================== | |||||
| virtual void drawLine (double x1, double y1, double x2, double y2) = 0; | virtual void drawLine (double x1, double y1, double x2, double y2) = 0; | ||||
| virtual void drawVerticalLine (const int x, double top, double bottom) = 0; | virtual void drawVerticalLine (const int x, double top, double bottom) = 0; | ||||
| virtual void drawHorizontalLine (const int y, double left, double right) = 0; | virtual void drawHorizontalLine (const int y, double left, double right) = 0; | ||||
| virtual void setFont (const Font& newFont) = 0; | virtual void setFont (const Font& newFont) = 0; | ||||
| virtual void drawGlyph (int glyphNumber, float x, float y) = 0; | |||||
| virtual const Font getFont() = 0; | |||||
| virtual void drawGlyph (int glyphNumber, const AffineTransform& transform) = 0; | virtual void drawGlyph (int glyphNumber, const AffineTransform& transform) = 0; | ||||
| }; | }; | ||||
| @@ -613,7 +613,10 @@ void LowLevelGraphicsPostScriptRenderer::drawGlyph (int glyphNumber, float x, fl | |||||
| void LowLevelGraphicsPostScriptRenderer::drawGlyph (int glyphNumber, const AffineTransform& transform) | void LowLevelGraphicsPostScriptRenderer::drawGlyph (int glyphNumber, const AffineTransform& transform) | ||||
| { | { | ||||
| font.renderGlyphIndirectly (*this, glyphNumber, transform); | |||||
| Path p; | |||||
| font.getTypeface()->getOutlineForGlyph (glyphNumber, p); | |||||
| fillPath (p, AffineTransform::scale (font.getHeight() * font.getHorizontalScale(), font.getHeight()).followedBy (transform)); | |||||
| } | } | ||||
| END_JUCE_NAMESPACE | END_JUCE_NAMESPACE | ||||
| @@ -49,45 +49,35 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| void setOrigin (int x, int y); | void setOrigin (int x, int y); | ||||
| bool reduceClipRegion (int x, int y, int w, int h); | |||||
| bool reduceClipRegion (const RectangleList& clipRegion); | |||||
| void excludeClipRegion (int x, int y, int w, int h); | |||||
| bool clipToRectangle (const Rectangle& r); | |||||
| bool clipToRectangleList (const RectangleList& clipRegion); | |||||
| void excludeClipRectangle (const Rectangle& r); | |||||
| void clipToPath (const Path& path, const AffineTransform& transform); | void clipToPath (const Path& path, const AffineTransform& transform); | ||||
| void clipToImage (Image& image, int imageX, int imageY); | |||||
| void saveState(); | |||||
| void restoreState(); | |||||
| void clipToImageAlpha (const Image& sourceImage, const Rectangle& srcClip, const AffineTransform& transform); | |||||
| bool clipRegionIntersects (int x, int y, int w, int h); | |||||
| bool clipRegionIntersects (const Rectangle& r); | |||||
| const Rectangle getClipBounds() const; | const Rectangle getClipBounds() const; | ||||
| bool isClipEmpty() const; | bool isClipEmpty() const; | ||||
| void saveState(); | |||||
| void restoreState(); | |||||
| //============================================================================== | //============================================================================== | ||||
| void setColour (const Colour& colour); | void setColour (const Colour& colour); | ||||
| void setGradient (const ColourGradient& gradient); | void setGradient (const ColourGradient& gradient); | ||||
| void setTiledFill (const Image& image, int x, int y); | |||||
| void setOpacity (float opacity); | void setOpacity (float opacity); | ||||
| void setInterpolationQuality (Graphics::ResamplingQuality quality); | void setInterpolationQuality (Graphics::ResamplingQuality quality); | ||||
| //============================================================================== | //============================================================================== | ||||
| void fillRect (int x, int y, int w, int h, const bool replaceExistingContents); | |||||
| void fillAll (const bool replaceContents); | |||||
| void fillRect (const Rectangle& r, const bool replaceExistingContents); | |||||
| void fillPath (const Path& path, const AffineTransform& transform); | void fillPath (const Path& path, const AffineTransform& transform); | ||||
| void fillPathWithImage (const Path& path, const AffineTransform& transform, | |||||
| const Image& image, int imageX, int imageY); | |||||
| void fillAlphaChannel (const Image& alphaImage, int imageX, int imageY); | |||||
| void fillAlphaChannelWithImage (const Image& alphaImage, int alphaImageX, int alphaImageY, | |||||
| const Image& fillerImage, int fillerImageX, int fillerImageY); | |||||
| //============================================================================== | |||||
| void blendImage (const Image& sourceImage, int destX, int destY, int destW, int destH, | |||||
| int sourceX, int sourceY); | |||||
| void blendImageWarping (const Image& sourceImage, int srcClipX, int srcClipY, int srcClipW, int srcClipH, | |||||
| const AffineTransform& transform); | |||||
| void drawImage (const Image& sourceImage, const Rectangle& srcClip, | |||||
| const AffineTransform& transform, const bool fillEntireClipAsTiles); | |||||
| //============================================================================== | |||||
| void drawLine (double x1, double y1, double x2, double y2); | void drawLine (double x1, double y1, double x2, double y2); | ||||
| void drawVerticalLine (const int x, double top, double bottom); | void drawVerticalLine (const int x, double top, double bottom); | ||||
| @@ -95,6 +85,7 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| void setFont (const Font& newFont); | void setFont (const Font& newFont); | ||||
| const Font getFont(); | |||||
| void drawGlyph (int glyphNumber, float x, float y); | void drawGlyph (int glyphNumber, float x, float y); | ||||
| void drawGlyph (int glyphNumber, const AffineTransform& transform); | void drawGlyph (int glyphNumber, const AffineTransform& transform); | ||||
| @@ -108,33 +99,6 @@ protected: | |||||
| LLGCSavedState* currentState; | LLGCSavedState* currentState; | ||||
| OwnedArray <LLGCSavedState> stateStack; | OwnedArray <LLGCSavedState> stateStack; | ||||
| /* void drawVertical (const int x, const double top, const double bottom); | |||||
| void drawHorizontal (const int y, const double top, const double bottom); | |||||
| void clippedFillRectWithColour (const Rectangle& clipRect, int x, int y, int w, int h, const Colour& colour, const bool replaceExistingContents); | |||||
| void clippedFillPath (int clipX, int clipY, int clipW, int clipH, const Path& path, const AffineTransform& transform); | |||||
| void clippedFillPathWithImage (int clipX, int clipY, int clipW, int clipH, const Path& path, const AffineTransform& transform, | |||||
| const Image& image, int imageX, int imageY, float alpha); | |||||
| void clippedFillAlphaChannel (int clipX, int clipY, int clipW, int clipH, const Image& alphaImage, int alphaImageX, int alphaImageY); | |||||
| void clippedFillAlphaChannelWithImage (int clipX, int clipY, int clipW, int clipH, const Image& alphaImage, int alphaImageX, int alphaImageY, | |||||
| const Image& fillerImage, int fillerImageX, int fillerImageY, const float opacity); | |||||
| //============================================================================== | |||||
| void clippedBlendImage (int clipX, int clipY, int clipW, int clipH, const Image& sourceImage, | |||||
| int destX, int destY, int destW, int destH, int sourceX, int sourceY); | |||||
| void clippedBlendImageWarping (int clipX, int clipY, int clipW, int clipH, const Image& sourceImage, | |||||
| int srcClipX, int srcClipY, int srcClipW, int srcClipH, | |||||
| const AffineTransform& transform); | |||||
| //============================================================================== | |||||
| void clippedDrawLine (int clipX, int clipY, int clipW, int clipH, double x1, double y1, double x2, double y2); | |||||
| void clippedDrawVerticalLine (int clipX, int clipY, int clipW, int clipH, const int x, double top, double bottom); | |||||
| void clippedDrawHorizontalLine (int clipX, int clipY, int clipW, int clipH, const int x, double top, double bottom);*/ | |||||
| LowLevelGraphicsSoftwareRenderer (const LowLevelGraphicsSoftwareRenderer& other); | LowLevelGraphicsSoftwareRenderer (const LowLevelGraphicsSoftwareRenderer& other); | ||||
| const LowLevelGraphicsSoftwareRenderer& operator= (const LowLevelGraphicsSoftwareRenderer&); | const LowLevelGraphicsSoftwareRenderer& operator= (const LowLevelGraphicsSoftwareRenderer&); | ||||
| }; | }; | ||||
| @@ -433,190 +433,4 @@ Typeface* Font::getTypeface() const throw() | |||||
| } | } | ||||
| //============================================================================== | |||||
| class FontGlyphAlphaMap | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| FontGlyphAlphaMap() throw() | |||||
| : glyph (0), lastAccessCount (0) | |||||
| { | |||||
| bitmap[0] = bitmap[1] = 0; | |||||
| } | |||||
| ~FontGlyphAlphaMap() throw() | |||||
| { | |||||
| delete bitmap[0]; | |||||
| delete bitmap[1]; | |||||
| } | |||||
| void draw (LowLevelGraphicsContext& g, float x, const float y) const throw() | |||||
| { | |||||
| if (bitmap[0] != 0) | |||||
| { | |||||
| const float xFloor = floorf (x); | |||||
| const int bitmapToUse = ((x - xFloor) >= 0.5f && bitmap[1] != 0) ? 1 : 0; | |||||
| g.fillAlphaChannel (*bitmap [bitmapToUse], | |||||
| xOrigin [bitmapToUse] + (int) xFloor, | |||||
| yOrigin [bitmapToUse] + roundFloatToInt(y)); | |||||
| } | |||||
| } | |||||
| void generate (const Font& font_, const int glyph_) throw() | |||||
| { | |||||
| font = font_; | |||||
| glyph = glyph_; | |||||
| deleteAndZero (bitmap[0]); | |||||
| deleteAndZero (bitmap[1]); | |||||
| Path glyphPath; | |||||
| font.getTypeface()->getOutlineForGlyph (glyph_, glyphPath); | |||||
| if (! glyphPath.isEmpty()) | |||||
| { | |||||
| const float fontHeight = font.getHeight(); | |||||
| const float fontHScale = fontHeight * font.getHorizontalScale(); | |||||
| AffineTransform transform (AffineTransform::scale (fontHScale, fontHeight)); | |||||
| Rectangle clip (-2048, -2048, 4096, 4096), pos; | |||||
| bitmap[0] = glyphPath.createMaskBitmap (transform, clip, pos); | |||||
| xOrigin[0] = pos.getX(); | |||||
| yOrigin[0] = pos.getY(); | |||||
| if (fontHScale < 30.0f) | |||||
| { | |||||
| bitmap[1] = glyphPath.createMaskBitmap (transform.translated (0.5f, 0.0f), clip, pos); | |||||
| xOrigin[1] = pos.getX(); | |||||
| yOrigin[1] = pos.getY(); | |||||
| } | |||||
| } | |||||
| } | |||||
| int glyph, lastAccessCount; | |||||
| Font font; | |||||
| //============================================================================== | |||||
| juce_UseDebuggingNewOperator | |||||
| private: | |||||
| Image* bitmap[2]; | |||||
| int xOrigin[2], yOrigin[2]; | |||||
| FontGlyphAlphaMap (const FontGlyphAlphaMap&); | |||||
| const FontGlyphAlphaMap& operator= (const FontGlyphAlphaMap&); | |||||
| }; | |||||
| //============================================================================== | |||||
| class GlyphCache : private DeletedAtShutdown | |||||
| { | |||||
| public: | |||||
| GlyphCache() throw() | |||||
| : accessCounter (0) | |||||
| { | |||||
| setCacheSize (120); | |||||
| } | |||||
| ~GlyphCache() throw() | |||||
| { | |||||
| clearSingletonInstance(); | |||||
| } | |||||
| juce_DeclareSingleton_SingleThreaded_Minimal (GlyphCache); | |||||
| //============================================================================== | |||||
| void drawGlyph (LowLevelGraphicsContext& g, const Font& font, int glyphNumber, float x, float y) throw() | |||||
| { | |||||
| ++accessCounter; | |||||
| int oldestCounter = INT_MAX; | |||||
| FontGlyphAlphaMap* oldest = 0; | |||||
| for (int i = glyphs.size(); --i >= 0;) | |||||
| { | |||||
| FontGlyphAlphaMap* const glyph = glyphs.getUnchecked (i); | |||||
| if (glyph->glyph == glyphNumber | |||||
| && glyph->font == font) | |||||
| { | |||||
| ++hits; | |||||
| glyph->lastAccessCount = accessCounter; | |||||
| glyph->draw (g, x, y); | |||||
| return; | |||||
| } | |||||
| if (glyph->lastAccessCount <= oldestCounter) | |||||
| { | |||||
| oldestCounter = glyph->lastAccessCount; | |||||
| oldest = glyph; | |||||
| } | |||||
| } | |||||
| ++misses; | |||||
| if (hits + misses > (glyphs.size() << 4)) | |||||
| { | |||||
| if (misses * 2 > hits) | |||||
| setCacheSize (glyphs.size() + 32); | |||||
| hits = 0; | |||||
| misses = 0; | |||||
| oldest = glyphs.getUnchecked (0); | |||||
| } | |||||
| jassert (oldest != 0); | |||||
| oldest->lastAccessCount = accessCounter; | |||||
| oldest->generate (font, glyphNumber); | |||||
| oldest->draw (g, x, y); | |||||
| } | |||||
| void setCacheSize (int num) throw() | |||||
| { | |||||
| if (glyphs.size() != num) | |||||
| { | |||||
| glyphs.clear(); | |||||
| while (--num >= 0) | |||||
| glyphs.add (new FontGlyphAlphaMap()); | |||||
| hits = 0; | |||||
| misses = 0; | |||||
| } | |||||
| } | |||||
| //============================================================================== | |||||
| juce_UseDebuggingNewOperator | |||||
| private: | |||||
| OwnedArray <FontGlyphAlphaMap> glyphs; | |||||
| int accessCounter, hits, misses; | |||||
| GlyphCache (const GlyphCache&); | |||||
| const GlyphCache& operator= (const GlyphCache&); | |||||
| }; | |||||
| juce_ImplementSingleton_SingleThreaded (GlyphCache); | |||||
| //============================================================================== | |||||
| void Font::renderGlyphIndirectly (LowLevelGraphicsContext& g, int glyphNumber, float x, float y) | |||||
| { | |||||
| if (font->height < 80.0f) | |||||
| GlyphCache::getInstance()->drawGlyph (g, *this, glyphNumber, x, y); | |||||
| else | |||||
| renderGlyphIndirectly (g, glyphNumber, AffineTransform::translation (x, y)); | |||||
| } | |||||
| void Font::renderGlyphIndirectly (LowLevelGraphicsContext& g, int glyphNumber, const AffineTransform& transform) | |||||
| { | |||||
| Path p; | |||||
| getTypeface()->getOutlineForGlyph (glyphNumber, p); | |||||
| g.fillPath (p, AffineTransform::scale (font->height * font->horizontalScale, font->height) | |||||
| .followedBy (transform)); | |||||
| } | |||||
| END_JUCE_NAMESPACE | END_JUCE_NAMESPACE | ||||
| @@ -307,24 +307,6 @@ public: | |||||
| */ | */ | ||||
| void getGlyphPositions (const String& text, Array <int>& glyphs, Array <float>& xOffsets) const throw(); | void getGlyphPositions (const String& text, Array <int>& glyphs, Array <float>& xOffsets) const throw(); | ||||
| //============================================================================== | |||||
| /** Renders a glyph in a context without using methods other than the context's glyph-rendering | |||||
| methods. | |||||
| For smaller fonts, this uses an internal cache of glyph images to speed things up, and renders | |||||
| them using the context's image blending methods. For larger fonts, it gets the glyph's path | |||||
| from the typeface and renders it as a shape. | |||||
| This method is primarily called by graphics contexts as a way of drawing a glyph if they can't do | |||||
| it by native means. | |||||
| */ | |||||
| void renderGlyphIndirectly (LowLevelGraphicsContext& g, int glyphNumber, float x, float y); | |||||
| /** Renders a transformed glyph using path-filling techniques rather than calling a context's | |||||
| actual glyph-rendering methods. | |||||
| */ | |||||
| void renderGlyphIndirectly (LowLevelGraphicsContext& g, int glyphNumber, const AffineTransform& transform); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Returns the typeface used by this font. | /** Returns the typeface used by this font. | ||||
| @@ -45,7 +45,7 @@ void PositionedGlyph::draw (const Graphics& g) const throw() | |||||
| if (! isWhitespace()) | if (! isWhitespace()) | ||||
| { | { | ||||
| g.getInternalContext()->setFont (font); | g.getInternalContext()->setFont (font); | ||||
| g.getInternalContext()->drawGlyph (glyph, x, y); | |||||
| g.getInternalContext()->drawGlyph (glyph, AffineTransform::translation (x, y)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -323,11 +323,40 @@ const Point Path::getCurrentPosition() const | |||||
| void Path::addRectangle (const float x, const float y, | void Path::addRectangle (const float x, const float y, | ||||
| const float w, const float h) throw() | const float w, const float h) throw() | ||||
| { | { | ||||
| startNewSubPath (x, y + h); | |||||
| lineTo (x, y); | |||||
| lineTo (x + w, y); | |||||
| lineTo (x + w, y + h); | |||||
| closeSubPath(); | |||||
| float x1 = x, y1 = y, x2 = x + w, y2 = y + h; | |||||
| if (w < 0) | |||||
| swapVariables (x1, x2); | |||||
| if (h < 0) | |||||
| swapVariables (y1, y2); | |||||
| ensureAllocatedSize (numElements + 13); | |||||
| elements [numElements++] = moveMarker; | |||||
| elements [numElements++] = x1; | |||||
| elements [numElements++] = y2; | |||||
| elements [numElements++] = lineMarker; | |||||
| elements [numElements++] = x1; | |||||
| elements [numElements++] = y1; | |||||
| elements [numElements++] = lineMarker; | |||||
| elements [numElements++] = x2; | |||||
| elements [numElements++] = y1; | |||||
| elements [numElements++] = lineMarker; | |||||
| elements [numElements++] = x2; | |||||
| elements [numElements++] = y2; | |||||
| elements [numElements++] = closeSubPathMarker; | |||||
| pathXMin = jmin (pathXMin, x1); | |||||
| pathXMax = jmax (pathXMax, x2); | |||||
| pathYMin = jmin (pathYMin, y1); | |||||
| pathYMax = jmax (pathYMax, y2); | |||||
| } | |||||
| void Path::addRectangle (const Rectangle& rectangle) throw() | |||||
| { | |||||
| addRectangle ((float) rectangle.getX(), (float) rectangle.getY(), | |||||
| (float) rectangle.getWidth(), (float) rectangle.getHeight()); | |||||
| } | } | ||||
| void Path::addRoundedRectangle (const float x, const float y, | void Path::addRoundedRectangle (const float x, const float y, | ||||
| @@ -1549,70 +1578,5 @@ bool Path::Iterator::next() | |||||
| return false; | return false; | ||||
| } | } | ||||
| //============================================================================== | |||||
| class MaskBitmapRenderer | |||||
| { | |||||
| public: | |||||
| MaskBitmapRenderer (const Image::BitmapData& destData_) throw() | |||||
| : destData (destData_) | |||||
| { | |||||
| } | |||||
| forcedinline void setEdgeTableYPos (const int y) throw() | |||||
| { | |||||
| lineStart = destData.getLinePointer (y); | |||||
| } | |||||
| forcedinline void handleEdgeTablePixel (const int x, const int alphaLevel) const throw() | |||||
| { | |||||
| lineStart [x] = (uint8) alphaLevel; | |||||
| } | |||||
| forcedinline void handleEdgeTableLine (const int x, int width, const int alphaLevel) const throw() | |||||
| { | |||||
| uint8* d = lineStart + x; | |||||
| while (--width >= 0) | |||||
| *d++ = (uint8) alphaLevel; | |||||
| } | |||||
| private: | |||||
| const Image::BitmapData& destData; | |||||
| uint8* lineStart; | |||||
| MaskBitmapRenderer (const MaskBitmapRenderer&); | |||||
| const MaskBitmapRenderer& operator= (const MaskBitmapRenderer&); | |||||
| }; | |||||
| Image* Path::createMaskBitmap (const AffineTransform& transform, | |||||
| const Rectangle& clipRegion, | |||||
| Rectangle& imagePosition) const throw() | |||||
| { | |||||
| if (isEmpty()) | |||||
| return 0; | |||||
| float px, py, pw, ph; | |||||
| getBoundsTransformed (transform, px, py, pw, ph); | |||||
| imagePosition = clipRegion.getIntersection (Rectangle ((int) floorf (px), (int) floorf (py), | |||||
| roundFloatToInt (pw) + 2, roundFloatToInt (ph) + 2)); | |||||
| if (imagePosition.isEmpty()) | |||||
| return 0; | |||||
| Image* im = Image::createNativeImage (Image::SingleChannel, imagePosition.getWidth(), imagePosition.getHeight(), true); | |||||
| EdgeTable edgeTable (Rectangle (0, 0, imagePosition.getWidth(), imagePosition.getHeight()), | |||||
| *this, transform.translated ((float) -imagePosition.getX(), (float) -imagePosition.getY())); | |||||
| const Image::BitmapData destData (*im, 0, 0, imagePosition.getWidth(), imagePosition.getHeight(), true); | |||||
| jassert (destData.pixelStride == 1); | |||||
| MaskBitmapRenderer renderer (destData); | |||||
| edgeTable.iterate (renderer); | |||||
| return im; | |||||
| } | |||||
| END_JUCE_NAMESPACE | END_JUCE_NAMESPACE | ||||
| @@ -221,6 +221,15 @@ public: | |||||
| void addRectangle (const float x, const float y, | void addRectangle (const float x, const float y, | ||||
| const float w, const float h) throw(); | const float w, const float h) throw(); | ||||
| /** Adds a rectangle to the path. | |||||
| The rectangle is added as a new sub-path. (Any currently open paths will be | |||||
| left open). | |||||
| @see addRoundedRectangle, addTriangle | |||||
| */ | |||||
| void addRectangle (const Rectangle& rectangle) throw(); | |||||
| /** Adds a rectangle with rounded corners to the path. | /** Adds a rectangle with rounded corners to the path. | ||||
| The rectangle is added as a new sub-path. (Any currently open paths will be | The rectangle is added as a new sub-path. (Any currently open paths will be | ||||
| @@ -616,21 +625,6 @@ public: | |||||
| */ | */ | ||||
| void restoreFromString (const String& stringVersion); | void restoreFromString (const String& stringVersion); | ||||
| //============================================================================== | |||||
| /** Creates a single-channel bitmap containing a mask of this path. | |||||
| The smallest bitmap that contains the path will be created, and on return, the | |||||
| imagePosition rectangle indicates the position of the newly created image, relative | |||||
| to the path's origin. | |||||
| Only the intersection of the path's bounds with the specified clipRegion rectangle | |||||
| will be rendered. | |||||
| If the path is empty or doesn't intersect the clip region, this may return 0. | |||||
| */ | |||||
| Image* createMaskBitmap (const AffineTransform& transform, | |||||
| const Rectangle& clipRegion, | |||||
| Rectangle& imagePosition) const throw(); | |||||
| //============================================================================== | //============================================================================== | ||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| @@ -284,10 +284,6 @@ | |||||
| #include "gui/components/windows/juce_ThreadWithProgressWindow.cpp" | #include "gui/components/windows/juce_ThreadWithProgressWindow.cpp" | ||||
| #include "gui/components/windows/juce_TooltipWindow.cpp" | #include "gui/components/windows/juce_TooltipWindow.cpp" | ||||
| #include "gui/components/windows/juce_TopLevelWindow.cpp" | #include "gui/components/windows/juce_TopLevelWindow.cpp" | ||||
| #include "gui/graphics/brushes/juce_Brush.cpp" | |||||
| #include "gui/graphics/brushes/juce_GradientBrush.cpp" | |||||
| #include "gui/graphics/brushes/juce_ImageBrush.cpp" | |||||
| #include "gui/graphics/brushes/juce_SolidColourBrush.cpp" | |||||
| #include "gui/graphics/colour/juce_Colour.cpp" | #include "gui/graphics/colour/juce_Colour.cpp" | ||||
| #include "gui/graphics/colour/juce_ColourGradient.cpp" | #include "gui/graphics/colour/juce_ColourGradient.cpp" | ||||
| #include "gui/graphics/colour/juce_Colours.cpp" | #include "gui/graphics/colour/juce_Colours.cpp" | ||||
| @@ -185,12 +185,6 @@ | |||||
| #ifndef __JUCE_AIFFAUDIOFORMAT_JUCEHEADER__ | #ifndef __JUCE_AIFFAUDIOFORMAT_JUCEHEADER__ | ||||
| #include "audio/audio_file_formats/juce_AiffAudioFormat.h" | #include "audio/audio_file_formats/juce_AiffAudioFormat.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_AUDIOCDBURNER_JUCEHEADER__ | |||||
| #include "audio/audio_file_formats/juce_AudioCDBurner.h" | |||||
| #endif | |||||
| #ifndef __JUCE_AUDIOCDREADER_JUCEHEADER__ | |||||
| #include "audio/audio_file_formats/juce_AudioCDReader.h" | |||||
| #endif | |||||
| #ifndef __JUCE_AUDIOFORMAT_JUCEHEADER__ | #ifndef __JUCE_AUDIOFORMAT_JUCEHEADER__ | ||||
| #include "audio/audio_file_formats/juce_AudioFormat.h" | #include "audio/audio_file_formats/juce_AudioFormat.h" | ||||
| #endif | #endif | ||||
| @@ -215,14 +209,20 @@ | |||||
| #ifndef __JUCE_FLACAUDIOFORMAT_JUCEHEADER__ | #ifndef __JUCE_FLACAUDIOFORMAT_JUCEHEADER__ | ||||
| #include "audio/audio_file_formats/juce_FlacAudioFormat.h" | #include "audio/audio_file_formats/juce_FlacAudioFormat.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_WAVAUDIOFORMAT_JUCEHEADER__ | |||||
| #include "audio/audio_file_formats/juce_WavAudioFormat.h" | |||||
| #endif | |||||
| #ifndef __JUCE_AUDIOCDREADER_JUCEHEADER__ | |||||
| #include "audio/audio_file_formats/juce_AudioCDReader.h" | |||||
| #endif | |||||
| #ifndef __JUCE_OGGVORBISAUDIOFORMAT_JUCEHEADER__ | #ifndef __JUCE_OGGVORBISAUDIOFORMAT_JUCEHEADER__ | ||||
| #include "audio/audio_file_formats/juce_OggVorbisAudioFormat.h" | #include "audio/audio_file_formats/juce_OggVorbisAudioFormat.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_QUICKTIMEAUDIOFORMAT_JUCEHEADER__ | #ifndef __JUCE_QUICKTIMEAUDIOFORMAT_JUCEHEADER__ | ||||
| #include "audio/audio_file_formats/juce_QuickTimeAudioFormat.h" | #include "audio/audio_file_formats/juce_QuickTimeAudioFormat.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_WAVAUDIOFORMAT_JUCEHEADER__ | |||||
| #include "audio/audio_file_formats/juce_WavAudioFormat.h" | |||||
| #ifndef __JUCE_AUDIOCDBURNER_JUCEHEADER__ | |||||
| #include "audio/audio_file_formats/juce_AudioCDBurner.h" | |||||
| #endif | #endif | ||||
| #ifndef __JUCE_ACTIONBROADCASTER_JUCEHEADER__ | #ifndef __JUCE_ACTIONBROADCASTER_JUCEHEADER__ | ||||
| #include "events/juce_ActionBroadcaster.h" | #include "events/juce_ActionBroadcaster.h" | ||||
| @@ -269,21 +269,6 @@ | |||||
| #ifndef __JUCE_TIMER_JUCEHEADER__ | #ifndef __JUCE_TIMER_JUCEHEADER__ | ||||
| #include "events/juce_Timer.h" | #include "events/juce_Timer.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_BRUSH_JUCEHEADER__ | |||||
| #include "gui/graphics/brushes/juce_Brush.h" | |||||
| #endif | |||||
| #ifndef __JUCE_GRADIENTBRUSH_JUCEHEADER__ | |||||
| #include "gui/graphics/brushes/juce_GradientBrush.h" | |||||
| #endif | |||||
| #ifndef __JUCE_IMAGEBRUSH_JUCEHEADER__ | |||||
| #include "gui/graphics/brushes/juce_ImageBrush.h" | |||||
| #endif | |||||
| #ifndef __JUCE_SOLIDCOLOURBRUSH_JUCEHEADER__ | |||||
| #include "gui/graphics/brushes/juce_SolidColourBrush.h" | |||||
| #endif | |||||
| #ifndef __JUCE_PIXELFORMATS_JUCEHEADER__ | |||||
| #include "gui/graphics/colour/juce_PixelFormats.h" | |||||
| #endif | |||||
| #ifndef __JUCE_COLOUR_JUCEHEADER__ | #ifndef __JUCE_COLOUR_JUCEHEADER__ | ||||
| #include "gui/graphics/colour/juce_Colour.h" | #include "gui/graphics/colour/juce_Colour.h" | ||||
| #endif | #endif | ||||
| @@ -293,41 +278,44 @@ | |||||
| #ifndef __JUCE_COLOURGRADIENT_JUCEHEADER__ | #ifndef __JUCE_COLOURGRADIENT_JUCEHEADER__ | ||||
| #include "gui/graphics/colour/juce_ColourGradient.h" | #include "gui/graphics/colour/juce_ColourGradient.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_FONT_JUCEHEADER__ | |||||
| #include "gui/graphics/fonts/juce_Font.h" | |||||
| #ifndef __JUCE_PIXELFORMATS_JUCEHEADER__ | |||||
| #include "gui/graphics/colour/juce_PixelFormats.h" | |||||
| #endif | |||||
| #ifndef __JUCE_TYPEFACE_JUCEHEADER__ | |||||
| #include "gui/graphics/fonts/juce_Typeface.h" | |||||
| #endif | #endif | ||||
| #ifndef __JUCE_TEXTLAYOUT_JUCEHEADER__ | #ifndef __JUCE_TEXTLAYOUT_JUCEHEADER__ | ||||
| #include "gui/graphics/fonts/juce_TextLayout.h" | #include "gui/graphics/fonts/juce_TextLayout.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_TYPEFACE_JUCEHEADER__ | |||||
| #include "gui/graphics/fonts/juce_Typeface.h" | |||||
| #ifndef __JUCE_FONT_JUCEHEADER__ | |||||
| #include "gui/graphics/fonts/juce_Font.h" | |||||
| #endif | #endif | ||||
| #ifndef __JUCE_GLYPHARRANGEMENT_JUCEHEADER__ | #ifndef __JUCE_GLYPHARRANGEMENT_JUCEHEADER__ | ||||
| #include "gui/graphics/fonts/juce_GlyphArrangement.h" | #include "gui/graphics/fonts/juce_GlyphArrangement.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_EDGETABLE_JUCEHEADER__ | |||||
| #include "gui/graphics/contexts/juce_EdgeTable.h" | |||||
| #ifndef __JUCE_GRAPHICS_JUCEHEADER__ | |||||
| #include "gui/graphics/contexts/juce_Graphics.h" | |||||
| #endif | #endif | ||||
| #ifndef __JUCE_JUSTIFICATION_JUCEHEADER__ | #ifndef __JUCE_JUSTIFICATION_JUCEHEADER__ | ||||
| #include "gui/graphics/contexts/juce_Justification.h" | #include "gui/graphics/contexts/juce_Justification.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_RECTANGLEPLACEMENT_JUCEHEADER__ | |||||
| #include "gui/graphics/contexts/juce_RectanglePlacement.h" | |||||
| #endif | |||||
| #ifndef __JUCE_EDGETABLE_JUCEHEADER__ | |||||
| #include "gui/graphics/contexts/juce_EdgeTable.h" | |||||
| #endif | |||||
| #ifndef __JUCE_LOWLEVELGRAPHICSCONTEXT_JUCEHEADER__ | #ifndef __JUCE_LOWLEVELGRAPHICSCONTEXT_JUCEHEADER__ | ||||
| #include "gui/graphics/contexts/juce_LowLevelGraphicsContext.h" | #include "gui/graphics/contexts/juce_LowLevelGraphicsContext.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_LOWLEVELGRAPHICSSOFTWARERENDERER_JUCEHEADER__ | #ifndef __JUCE_LOWLEVELGRAPHICSSOFTWARERENDERER_JUCEHEADER__ | ||||
| #include "gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h" | #include "gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_RECTANGLEPLACEMENT_JUCEHEADER__ | |||||
| #include "gui/graphics/contexts/juce_RectanglePlacement.h" | |||||
| #endif | |||||
| #ifndef __JUCE_GRAPHICS_JUCEHEADER__ | |||||
| #include "gui/graphics/contexts/juce_Graphics.h" | |||||
| #endif | |||||
| #ifndef __JUCE_LOWLEVELGRAPHICSPOSTSCRIPTRENDERER_JUCEHEADER__ | #ifndef __JUCE_LOWLEVELGRAPHICSPOSTSCRIPTRENDERER_JUCEHEADER__ | ||||
| #include "gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h" | #include "gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_AFFINETRANSFORM_JUCEHEADER__ | |||||
| #include "gui/graphics/geometry/juce_AffineTransform.h" | |||||
| #ifndef __JUCE_PATH_JUCEHEADER__ | |||||
| #include "gui/graphics/geometry/juce_Path.h" | |||||
| #endif | #endif | ||||
| #ifndef __JUCE_BORDERSIZE_JUCEHEADER__ | #ifndef __JUCE_BORDERSIZE_JUCEHEADER__ | ||||
| #include "gui/graphics/geometry/juce_BorderSize.h" | #include "gui/graphics/geometry/juce_BorderSize.h" | ||||
| @@ -335,36 +323,36 @@ | |||||
| #ifndef __JUCE_LINE_JUCEHEADER__ | #ifndef __JUCE_LINE_JUCEHEADER__ | ||||
| #include "gui/graphics/geometry/juce_Line.h" | #include "gui/graphics/geometry/juce_Line.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_PATH_JUCEHEADER__ | |||||
| #include "gui/graphics/geometry/juce_Path.h" | |||||
| #ifndef __JUCE_POINT_JUCEHEADER__ | |||||
| #include "gui/graphics/geometry/juce_Point.h" | |||||
| #endif | #endif | ||||
| #ifndef __JUCE_PATHITERATOR_JUCEHEADER__ | |||||
| #include "gui/graphics/geometry/juce_PathIterator.h" | |||||
| #ifndef __JUCE_RECTANGLE_JUCEHEADER__ | |||||
| #include "gui/graphics/geometry/juce_Rectangle.h" | |||||
| #endif | #endif | ||||
| #ifndef __JUCE_PATHSTROKETYPE_JUCEHEADER__ | #ifndef __JUCE_PATHSTROKETYPE_JUCEHEADER__ | ||||
| #include "gui/graphics/geometry/juce_PathStrokeType.h" | #include "gui/graphics/geometry/juce_PathStrokeType.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_POINT_JUCEHEADER__ | |||||
| #include "gui/graphics/geometry/juce_Point.h" | |||||
| #endif | |||||
| #ifndef __JUCE_POSITIONEDRECTANGLE_JUCEHEADER__ | #ifndef __JUCE_POSITIONEDRECTANGLE_JUCEHEADER__ | ||||
| #include "gui/graphics/geometry/juce_PositionedRectangle.h" | #include "gui/graphics/geometry/juce_PositionedRectangle.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_RECTANGLE_JUCEHEADER__ | |||||
| #include "gui/graphics/geometry/juce_Rectangle.h" | |||||
| #endif | |||||
| #ifndef __JUCE_RECTANGLELIST_JUCEHEADER__ | #ifndef __JUCE_RECTANGLELIST_JUCEHEADER__ | ||||
| #include "gui/graphics/geometry/juce_RectangleList.h" | #include "gui/graphics/geometry/juce_RectangleList.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_PATHITERATOR_JUCEHEADER__ | |||||
| #include "gui/graphics/geometry/juce_PathIterator.h" | |||||
| #endif | |||||
| #ifndef __JUCE_AFFINETRANSFORM_JUCEHEADER__ | |||||
| #include "gui/graphics/geometry/juce_AffineTransform.h" | |||||
| #endif | |||||
| #ifndef __JUCE_CAMERADEVICE_JUCEHEADER__ | #ifndef __JUCE_CAMERADEVICE_JUCEHEADER__ | ||||
| #include "gui/graphics/imaging/juce_CameraDevice.h" | #include "gui/graphics/imaging/juce_CameraDevice.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_IMAGE_JUCEHEADER__ | |||||
| #include "gui/graphics/imaging/juce_Image.h" | |||||
| #endif | |||||
| #ifndef __JUCE_IMAGECACHE_JUCEHEADER__ | #ifndef __JUCE_IMAGECACHE_JUCEHEADER__ | ||||
| #include "gui/graphics/imaging/juce_ImageCache.h" | #include "gui/graphics/imaging/juce_ImageCache.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_IMAGE_JUCEHEADER__ | |||||
| #include "gui/graphics/imaging/juce_Image.h" | |||||
| #endif | |||||
| #ifndef __JUCE_IMAGEFILEFORMAT_JUCEHEADER__ | #ifndef __JUCE_IMAGEFILEFORMAT_JUCEHEADER__ | ||||
| #include "gui/graphics/imaging/juce_ImageFileFormat.h" | #include "gui/graphics/imaging/juce_ImageFileFormat.h" | ||||
| #endif | #endif | ||||
| @@ -380,12 +368,12 @@ | |||||
| #ifndef __JUCE_DRAWABLEIMAGE_JUCEHEADER__ | #ifndef __JUCE_DRAWABLEIMAGE_JUCEHEADER__ | ||||
| #include "gui/graphics/drawables/juce_DrawableImage.h" | #include "gui/graphics/drawables/juce_DrawableImage.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_DRAWABLEPATH_JUCEHEADER__ | |||||
| #include "gui/graphics/drawables/juce_DrawablePath.h" | |||||
| #endif | |||||
| #ifndef __JUCE_DRAWABLETEXT_JUCEHEADER__ | #ifndef __JUCE_DRAWABLETEXT_JUCEHEADER__ | ||||
| #include "gui/graphics/drawables/juce_DrawableText.h" | #include "gui/graphics/drawables/juce_DrawableText.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_DRAWABLEPATH_JUCEHEADER__ | |||||
| #include "gui/graphics/drawables/juce_DrawablePath.h" | |||||
| #endif | |||||
| #ifndef __JUCE_COMPONENT_JUCEHEADER__ | #ifndef __JUCE_COMPONENT_JUCEHEADER__ | ||||
| #include "gui/components/juce_Component.h" | #include "gui/components/juce_Component.h" | ||||
| #endif | #endif | ||||
| @@ -458,12 +446,12 @@ | |||||
| #ifndef __JUCE_CODEEDITORCOMPONENT_JUCEHEADER__ | #ifndef __JUCE_CODEEDITORCOMPONENT_JUCEHEADER__ | ||||
| #include "gui/components/code_editor/juce_CodeEditorComponent.h" | #include "gui/components/code_editor/juce_CodeEditorComponent.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_CODEDOCUMENT_JUCEHEADER__ | |||||
| #include "gui/components/code_editor/juce_CodeDocument.h" | |||||
| #endif | |||||
| #ifndef __JUCE_CPLUSPLUSCODETOKENISER_JUCEHEADER__ | #ifndef __JUCE_CPLUSPLUSCODETOKENISER_JUCEHEADER__ | ||||
| #include "gui/components/code_editor/juce_CPlusPlusCodeTokeniser.h" | #include "gui/components/code_editor/juce_CPlusPlusCodeTokeniser.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_CODEDOCUMENT_JUCEHEADER__ | |||||
| #include "gui/components/code_editor/juce_CodeDocument.h" | |||||
| #endif | |||||
| #ifndef __JUCE_CODETOKENISER_JUCEHEADER__ | #ifndef __JUCE_CODETOKENISER_JUCEHEADER__ | ||||
| #include "gui/components/code_editor/juce_CodeTokeniser.h" | #include "gui/components/code_editor/juce_CodeTokeniser.h" | ||||
| #endif | #endif | ||||
| @@ -545,12 +533,12 @@ | |||||
| #ifndef __JUCE_TOOLBARITEMPALETTE_JUCEHEADER__ | #ifndef __JUCE_TOOLBARITEMPALETTE_JUCEHEADER__ | ||||
| #include "gui/components/controls/juce_ToolbarItemPalette.h" | #include "gui/components/controls/juce_ToolbarItemPalette.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_TOOLBARITEMCOMPONENT_JUCEHEADER__ | |||||
| #include "gui/components/controls/juce_ToolbarItemComponent.h" | |||||
| #endif | |||||
| #ifndef __JUCE_TREEVIEW_JUCEHEADER__ | #ifndef __JUCE_TREEVIEW_JUCEHEADER__ | ||||
| #include "gui/components/controls/juce_TreeView.h" | #include "gui/components/controls/juce_TreeView.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_TOOLBARITEMCOMPONENT_JUCEHEADER__ | |||||
| #include "gui/components/controls/juce_ToolbarItemComponent.h" | |||||
| #endif | |||||
| #ifndef __JUCE_BOOLEANPROPERTYCOMPONENT_JUCEHEADER__ | #ifndef __JUCE_BOOLEANPROPERTYCOMPONENT_JUCEHEADER__ | ||||
| #include "gui/components/properties/juce_BooleanPropertyComponent.h" | #include "gui/components/properties/juce_BooleanPropertyComponent.h" | ||||
| #endif | #endif | ||||
| @@ -560,12 +548,12 @@ | |||||
| #ifndef __JUCE_CHOICEPROPERTYCOMPONENT_JUCEHEADER__ | #ifndef __JUCE_CHOICEPROPERTYCOMPONENT_JUCEHEADER__ | ||||
| #include "gui/components/properties/juce_ChoicePropertyComponent.h" | #include "gui/components/properties/juce_ChoicePropertyComponent.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_PROPERTYCOMPONENT_JUCEHEADER__ | |||||
| #include "gui/components/properties/juce_PropertyComponent.h" | |||||
| #endif | |||||
| #ifndef __JUCE_PROPERTYPANEL_JUCEHEADER__ | #ifndef __JUCE_PROPERTYPANEL_JUCEHEADER__ | ||||
| #include "gui/components/properties/juce_PropertyPanel.h" | #include "gui/components/properties/juce_PropertyPanel.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_PROPERTYCOMPONENT_JUCEHEADER__ | |||||
| #include "gui/components/properties/juce_PropertyComponent.h" | |||||
| #endif | |||||
| #ifndef __JUCE_SLIDERPROPERTYCOMPONENT_JUCEHEADER__ | #ifndef __JUCE_SLIDERPROPERTYCOMPONENT_JUCEHEADER__ | ||||
| #include "gui/components/properties/juce_SliderPropertyComponent.h" | #include "gui/components/properties/juce_SliderPropertyComponent.h" | ||||
| #endif | #endif | ||||
| @@ -629,33 +617,33 @@ | |||||
| #ifndef __JUCE_FILECHOOSER_JUCEHEADER__ | #ifndef __JUCE_FILECHOOSER_JUCEHEADER__ | ||||
| #include "gui/components/filebrowser/juce_FileChooser.h" | #include "gui/components/filebrowser/juce_FileChooser.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_FILECHOOSERDIALOGBOX_JUCEHEADER__ | |||||
| #include "gui/components/filebrowser/juce_FileChooserDialogBox.h" | |||||
| #endif | |||||
| #ifndef __JUCE_FILEFILTER_JUCEHEADER__ | #ifndef __JUCE_FILEFILTER_JUCEHEADER__ | ||||
| #include "gui/components/filebrowser/juce_FileFilter.h" | #include "gui/components/filebrowser/juce_FileFilter.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_FILECHOOSERDIALOGBOX_JUCEHEADER__ | |||||
| #include "gui/components/filebrowser/juce_FileChooserDialogBox.h" | |||||
| #endif | |||||
| #ifndef __JUCE_FILELISTCOMPONENT_JUCEHEADER__ | #ifndef __JUCE_FILELISTCOMPONENT_JUCEHEADER__ | ||||
| #include "gui/components/filebrowser/juce_FileListComponent.h" | #include "gui/components/filebrowser/juce_FileListComponent.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_FILEPREVIEWCOMPONENT_JUCEHEADER__ | #ifndef __JUCE_FILEPREVIEWCOMPONENT_JUCEHEADER__ | ||||
| #include "gui/components/filebrowser/juce_FilePreviewComponent.h" | #include "gui/components/filebrowser/juce_FilePreviewComponent.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_FILESEARCHPATHLISTCOMPONENT_JUCEHEADER__ | |||||
| #include "gui/components/filebrowser/juce_FileSearchPathListComponent.h" | |||||
| #endif | |||||
| #ifndef __JUCE_FILETREECOMPONENT_JUCEHEADER__ | #ifndef __JUCE_FILETREECOMPONENT_JUCEHEADER__ | ||||
| #include "gui/components/filebrowser/juce_FileTreeComponent.h" | #include "gui/components/filebrowser/juce_FileTreeComponent.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_FILESEARCHPATHLISTCOMPONENT_JUCEHEADER__ | |||||
| #include "gui/components/filebrowser/juce_FileSearchPathListComponent.h" | |||||
| #endif | |||||
| #ifndef __JUCE_FILENAMECOMPONENT_JUCEHEADER__ | #ifndef __JUCE_FILENAMECOMPONENT_JUCEHEADER__ | ||||
| #include "gui/components/filebrowser/juce_FilenameComponent.h" | #include "gui/components/filebrowser/juce_FilenameComponent.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_IMAGEPREVIEWCOMPONENT_JUCEHEADER__ | |||||
| #include "gui/components/filebrowser/juce_ImagePreviewComponent.h" | |||||
| #endif | |||||
| #ifndef __JUCE_WILDCARDFILEFILTER_JUCEHEADER__ | #ifndef __JUCE_WILDCARDFILEFILTER_JUCEHEADER__ | ||||
| #include "gui/components/filebrowser/juce_WildcardFileFilter.h" | #include "gui/components/filebrowser/juce_WildcardFileFilter.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_IMAGEPREVIEWCOMPONENT_JUCEHEADER__ | |||||
| #include "gui/components/filebrowser/juce_ImagePreviewComponent.h" | |||||
| #endif | |||||
| #ifndef __JUCE_ALERTWINDOW_JUCEHEADER__ | #ifndef __JUCE_ALERTWINDOW_JUCEHEADER__ | ||||
| #include "gui/components/windows/juce_AlertWindow.h" | #include "gui/components/windows/juce_AlertWindow.h" | ||||
| #endif | #endif | ||||
| @@ -716,12 +704,12 @@ | |||||
| #ifndef __JUCE_PREFERENCESPANEL_JUCEHEADER__ | #ifndef __JUCE_PREFERENCESPANEL_JUCEHEADER__ | ||||
| #include "gui/components/special/juce_PreferencesPanel.h" | #include "gui/components/special/juce_PreferencesPanel.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_SYSTEMTRAYICONCOMPONENT_JUCEHEADER__ | |||||
| #include "gui/components/special/juce_SystemTrayIconComponent.h" | |||||
| #endif | |||||
| #ifndef __JUCE_WEBBROWSERCOMPONENT_JUCEHEADER__ | #ifndef __JUCE_WEBBROWSERCOMPONENT_JUCEHEADER__ | ||||
| #include "gui/components/special/juce_WebBrowserComponent.h" | #include "gui/components/special/juce_WebBrowserComponent.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_SYSTEMTRAYICONCOMPONENT_JUCEHEADER__ | |||||
| #include "gui/components/special/juce_SystemTrayIconComponent.h" | |||||
| #endif | |||||
| #ifndef __JUCE_QUICKTIMEMOVIECOMPONENT_JUCEHEADER__ | #ifndef __JUCE_QUICKTIMEMOVIECOMPONENT_JUCEHEADER__ | ||||
| #include "gui/components/special/juce_QuickTimeMovieComponent.h" | #include "gui/components/special/juce_QuickTimeMovieComponent.h" | ||||
| #endif | #endif | ||||
| @@ -41,8 +41,8 @@ | |||||
| #ifndef __JUCE_LOGGER_JUCEHEADER__ | #ifndef __JUCE_LOGGER_JUCEHEADER__ | ||||
| #include "core/juce_Logger.h" | #include "core/juce_Logger.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_MATHSFUNCTIONS_JUCEHEADER__ | |||||
| #include "core/juce_MathsFunctions.h" | |||||
| #ifndef __JUCE_PLATFORMUTILITIES_JUCEHEADER__ | |||||
| #include "core/juce_PlatformUtilities.h" | |||||
| #endif | #endif | ||||
| #ifndef __JUCE_MEMORY_JUCEHEADER__ | #ifndef __JUCE_MEMORY_JUCEHEADER__ | ||||
| #include "core/juce_Memory.h" | #include "core/juce_Memory.h" | ||||
| @@ -53,8 +53,8 @@ | |||||
| #ifndef __JUCE_PLATFORMDEFS_JUCEHEADER__ | #ifndef __JUCE_PLATFORMDEFS_JUCEHEADER__ | ||||
| #include "core/juce_PlatformDefs.h" | #include "core/juce_PlatformDefs.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_PLATFORMUTILITIES_JUCEHEADER__ | |||||
| #include "core/juce_PlatformUtilities.h" | |||||
| #ifndef __JUCE_SINGLETON_JUCEHEADER__ | |||||
| #include "core/juce_Singleton.h" | |||||
| #endif | #endif | ||||
| #ifndef __JUCE_RANDOM_JUCEHEADER__ | #ifndef __JUCE_RANDOM_JUCEHEADER__ | ||||
| #include "core/juce_Random.h" | #include "core/juce_Random.h" | ||||
| @@ -62,24 +62,24 @@ | |||||
| #ifndef __JUCE_RELATIVETIME_JUCEHEADER__ | #ifndef __JUCE_RELATIVETIME_JUCEHEADER__ | ||||
| #include "core/juce_RelativeTime.h" | #include "core/juce_RelativeTime.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_SINGLETON_JUCEHEADER__ | |||||
| #include "core/juce_Singleton.h" | |||||
| #endif | |||||
| #ifndef __JUCE_STANDARDHEADER_JUCEHEADER__ | |||||
| #include "core/juce_StandardHeader.h" | |||||
| #endif | |||||
| #ifndef __JUCE_SYSTEMSTATS_JUCEHEADER__ | #ifndef __JUCE_SYSTEMSTATS_JUCEHEADER__ | ||||
| #include "core/juce_SystemStats.h" | #include "core/juce_SystemStats.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_TARGETPLATFORM_JUCEHEADER__ | |||||
| #include "core/juce_TargetPlatform.h" | |||||
| #endif | |||||
| #ifndef __JUCE_TIME_JUCEHEADER__ | #ifndef __JUCE_TIME_JUCEHEADER__ | ||||
| #include "core/juce_Time.h" | #include "core/juce_Time.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_UUID_JUCEHEADER__ | #ifndef __JUCE_UUID_JUCEHEADER__ | ||||
| #include "core/juce_Uuid.h" | #include "core/juce_Uuid.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_STANDARDHEADER_JUCEHEADER__ | |||||
| #include "core/juce_StandardHeader.h" | |||||
| #endif | |||||
| #ifndef __JUCE_MATHSFUNCTIONS_JUCEHEADER__ | |||||
| #include "core/juce_MathsFunctions.h" | |||||
| #endif | |||||
| #ifndef __JUCE_TARGETPLATFORM_JUCEHEADER__ | |||||
| #include "core/juce_TargetPlatform.h" | |||||
| #endif | |||||
| #ifndef __JUCE_ARRAY_JUCEHEADER__ | #ifndef __JUCE_ARRAY_JUCEHEADER__ | ||||
| #include "containers/juce_Array.h" | #include "containers/juce_Array.h" | ||||
| #endif | #endif | ||||
| @@ -236,14 +236,14 @@ | |||||
| #ifndef __JUCE_THREAD_JUCEHEADER__ | #ifndef __JUCE_THREAD_JUCEHEADER__ | ||||
| #include "threads/juce_Thread.h" | #include "threads/juce_Thread.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_THREADPOOL_JUCEHEADER__ | |||||
| #include "threads/juce_ThreadPool.h" | |||||
| #endif | |||||
| #ifndef __JUCE_TIMESLICETHREAD_JUCEHEADER__ | #ifndef __JUCE_TIMESLICETHREAD_JUCEHEADER__ | ||||
| #include "threads/juce_TimeSliceThread.h" | #include "threads/juce_TimeSliceThread.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_WAITABLEEVENT_JUCEHEADER__ | #ifndef __JUCE_WAITABLEEVENT_JUCEHEADER__ | ||||
| #include "threads/juce_WaitableEvent.h" | #include "threads/juce_WaitableEvent.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_THREADPOOL_JUCEHEADER__ | |||||
| #include "threads/juce_ThreadPool.h" | |||||
| #endif | |||||
| #endif | #endif | ||||
| @@ -73,7 +73,9 @@ class CoreGraphicsContext : public LowLevelGraphicsContext | |||||
| public: | public: | ||||
| CoreGraphicsContext (CGContextRef context_, const float flipHeight_) | CoreGraphicsContext (CGContextRef context_, const float flipHeight_) | ||||
| : context (context_), | : context (context_), | ||||
| flipHeight (flipHeight_) | |||||
| flipHeight (flipHeight_), | |||||
| gradientLookupTable (0), | |||||
| numGradientLookupEntries (0) | |||||
| { | { | ||||
| CGContextRetain (context); | CGContextRetain (context); | ||||
| CGContextSetShouldSmoothFonts (context, true); | CGContextSetShouldSmoothFonts (context, true); | ||||
| @@ -93,6 +95,7 @@ public: | |||||
| CGColorSpaceRelease (rgbColourSpace); | CGColorSpaceRelease (rgbColourSpace); | ||||
| CGColorSpaceRelease (greyColourSpace); | CGColorSpaceRelease (greyColourSpace); | ||||
| delete state; | delete state; | ||||
| delete gradientLookupTable; | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -103,13 +106,13 @@ public: | |||||
| CGContextTranslateCTM (context, x, -y); | CGContextTranslateCTM (context, x, -y); | ||||
| } | } | ||||
| bool reduceClipRegion (int x, int y, int w, int h) | |||||
| bool clipToRectangle (const Rectangle& r) | |||||
| { | { | ||||
| CGContextClipToRect (context, CGRectMake (x, flipHeight - (y + h), w, h)); | |||||
| CGContextClipToRect (context, CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight())); | |||||
| return ! isClipEmpty(); | return ! isClipEmpty(); | ||||
| } | } | ||||
| bool reduceClipRegion (const RectangleList& clipRegion) | |||||
| bool clipToRectangleList (const RectangleList& clipRegion) | |||||
| { | { | ||||
| const int numRects = clipRegion.getNumRectangles(); | const int numRects = clipRegion.getNumRectangles(); | ||||
| CGRect* const rects = new CGRect [numRects]; | CGRect* const rects = new CGRect [numRects]; | ||||
| @@ -125,40 +128,44 @@ public: | |||||
| return ! isClipEmpty(); | return ! isClipEmpty(); | ||||
| } | } | ||||
| void excludeClipRegion (int x, int y, int w, int h) | |||||
| void excludeClipRectangle (const Rectangle& r) | |||||
| { | { | ||||
| RectangleList r (getClipBounds()); | |||||
| r.subtract (Rectangle (x, y, w, h)); | |||||
| reduceClipRegion (r); | |||||
| RectangleList remaining (getClipBounds()); | |||||
| remaining.subtract (r); | |||||
| clipToRectangleList (remaining); | |||||
| } | } | ||||
| void saveState() | |||||
| void clipToPath (const Path& path, const AffineTransform& transform) | |||||
| { | { | ||||
| CGContextSaveGState (context); | |||||
| stateStack.add (new SavedState (*state)); | |||||
| createPath (path, transform); | |||||
| CGContextClip (context); | |||||
| } | } | ||||
| void restoreState() | |||||
| void clipToImageAlpha (const Image& sourceImage, const Rectangle& srcClip, const AffineTransform& transform) | |||||
| { | { | ||||
| CGContextRestoreGState (context); | |||||
| if (! transform.isSingularity()) | |||||
| { | |||||
| Image* singleChannelImage = createAlphaChannelImage (sourceImage); | |||||
| CGImageRef image = createImage (*singleChannelImage, true); | |||||
| SavedState* const top = stateStack.getLast(); | |||||
| flip(); | |||||
| AffineTransform t (AffineTransform::scale (1.0f, -1.0f).translated (0, sourceImage.getHeight()).followedBy (transform)); | |||||
| applyTransform (t); | |||||
| if (top != 0) | |||||
| { | |||||
| delete state; | |||||
| state = top; | |||||
| stateStack.removeLast (1, false); | |||||
| } | |||||
| else | |||||
| { | |||||
| jassertfalse // trying to pop with an empty stack! | |||||
| CGRect r = CGRectMake (0, 0, sourceImage.getWidth(), sourceImage.getHeight()); | |||||
| CGContextClipToMask (context, r, image); | |||||
| applyTransform (t.inverted()); | |||||
| flip(); | |||||
| CGImageRelease (image); | |||||
| deleteAlphaChannelImage (sourceImage, singleChannelImage); | |||||
| } | } | ||||
| } | } | ||||
| bool clipRegionIntersects (int x, int y, int w, int h) | |||||
| bool clipRegionIntersects (const Rectangle& r) | |||||
| { | { | ||||
| return getClipBounds().intersects (Rectangle (x, y, w, h)); | |||||
| return getClipBounds().intersects (r); | |||||
| } | } | ||||
| const Rectangle getClipBounds() const | const Rectangle getClipBounds() const | ||||
| @@ -176,11 +183,35 @@ public: | |||||
| return CGRectIsEmpty (CGContextGetClipBoundingBox (context)); | return CGRectIsEmpty (CGContextGetClipBoundingBox (context)); | ||||
| } | } | ||||
| //============================================================================== | |||||
| void saveState() | |||||
| { | |||||
| CGContextSaveGState (context); | |||||
| stateStack.add (new SavedState (*state)); | |||||
| } | |||||
| void restoreState() | |||||
| { | |||||
| CGContextRestoreGState (context); | |||||
| SavedState* const top = stateStack.getLast(); | |||||
| if (top != 0) | |||||
| { | |||||
| delete state; | |||||
| state = top; | |||||
| stateStack.removeLast (1, false); | |||||
| } | |||||
| else | |||||
| { | |||||
| jassertfalse // trying to pop with an empty stack! | |||||
| } | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| void setColour (const Colour& colour) | void setColour (const Colour& colour) | ||||
| { | { | ||||
| state->colour = colour; | |||||
| deleteAndZero (state->gradient); | |||||
| state->fillType.setColour (colour); | |||||
| CGContextSetRGBFillColor (context, | CGContextSetRGBFillColor (context, | ||||
| colour.getFloatRed(), colour.getFloatGreen(), | colour.getFloatRed(), colour.getFloatGreen(), | ||||
| @@ -190,15 +221,17 @@ public: | |||||
| void setGradient (const ColourGradient& gradient) | void setGradient (const ColourGradient& gradient) | ||||
| { | { | ||||
| if (state->gradient == 0) | |||||
| state->gradient = new ColourGradient (gradient); | |||||
| else | |||||
| *state->gradient = gradient; | |||||
| state->fillType.setGradient (gradient); | |||||
| } | |||||
| void setTiledFill (const Image& image, int x, int y) | |||||
| { | |||||
| state->fillType.setTiledImage (image, x, y); | |||||
| } | } | ||||
| void setOpacity (float opacity) | void setOpacity (float opacity) | ||||
| { | { | ||||
| setColour (state->colour.withAlpha (opacity)); | |||||
| state->fillType.colour = state->fillType.colour.withAlpha (opacity); | |||||
| } | } | ||||
| void setInterpolationQuality (Graphics::ResamplingQuality quality) | void setInterpolationQuality (Graphics::ResamplingQuality quality) | ||||
| @@ -209,38 +242,48 @@ public: | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void fillRect (int x, int y, int w, int h, const bool replaceExistingContents) | |||||
| void fillRect (const Rectangle& r, const bool replaceExistingContents) | |||||
| { | { | ||||
| CGRect cgRect = CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()); | |||||
| if (replaceExistingContents) | if (replaceExistingContents) | ||||
| { | { | ||||
| #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 | #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 | ||||
| CGContextClearRect (context, CGRectMake (x, y, w, h)); | |||||
| CGContextClearRect (context, cgRect); | |||||
| #else | #else | ||||
| #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 | #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 | ||||
| if (CGContextDrawLinearGradient == 0) // (just a way of checking whether we're running in 10.5 or later) | if (CGContextDrawLinearGradient == 0) // (just a way of checking whether we're running in 10.5 or later) | ||||
| CGContextClearRect (context, CGRectMake (x, y, w, h)); | |||||
| CGContextClearRect (context, cgRect); | |||||
| else | else | ||||
| #endif | #endif | ||||
| CGContextSetBlendMode (context, kCGBlendModeCopy); | CGContextSetBlendMode (context, kCGBlendModeCopy); | ||||
| #endif | #endif | ||||
| fillRect (x, y, w, h, false); | |||||
| fillRect (r, false); | |||||
| CGContextSetBlendMode (context, kCGBlendModeNormal); | CGContextSetBlendMode (context, kCGBlendModeNormal); | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| if (state->gradient == 0) | |||||
| if (state->fillType.isColour()) | |||||
| { | { | ||||
| CGContextFillRect (context, CGRectMake (x, flipHeight - (y + h), w, h)); | |||||
| CGContextFillRect (context, cgRect); | |||||
| } | } | ||||
| else | |||||
| else if (state->fillType.isGradient()) | |||||
| { | { | ||||
| CGContextSaveGState (context); | CGContextSaveGState (context); | ||||
| CGContextClipToRect (context, CGRectMake (x, flipHeight - (y + h), w, h)); | |||||
| CGContextClipToRect (context, cgRect); | |||||
| flip(); | flip(); | ||||
| drawGradient(); | drawGradient(); | ||||
| CGContextRestoreGState (context); | CGContextRestoreGState (context); | ||||
| } | } | ||||
| else | |||||
| { | |||||
| CGContextSaveGState (context); | |||||
| CGContextClipToRect (context, cgRect); | |||||
| drawImage (*(state->fillType.image), Rectangle (0, 0, state->fillType.image->getWidth(), state->fillType.image->getHeight()), | |||||
| AffineTransform::translation (state->fillType.imageX, state->fillType.imageY), true); | |||||
| CGContextRestoreGState (context); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -248,7 +291,7 @@ public: | |||||
| { | { | ||||
| CGContextSaveGState (context); | CGContextSaveGState (context); | ||||
| if (state->gradient == 0) | |||||
| if (state->fillType.isColour()) | |||||
| { | { | ||||
| flip(); | flip(); | ||||
| applyTransform (transform); | applyTransform (transform); | ||||
| @@ -259,102 +302,78 @@ public: | |||||
| else | else | ||||
| CGContextEOFillPath (context); | CGContextEOFillPath (context); | ||||
| } | } | ||||
| else | |||||
| else if (state->fillType.isGradient()) | |||||
| { | { | ||||
| createPath (path, transform); | createPath (path, transform); | ||||
| CGContextClip (context); | CGContextClip (context); | ||||
| flip(); | flip(); | ||||
| applyTransform (state->gradient->transform); | |||||
| applyTransform (state->fillType.gradient->transform); | |||||
| drawGradient(); | drawGradient(); | ||||
| } | } | ||||
| else | |||||
| { | |||||
| createPath (path, transform); | |||||
| CGContextClip (context); | |||||
| drawImage (*(state->fillType.image), Rectangle (0, 0, state->fillType.image->getWidth(), state->fillType.image->getHeight()), | |||||
| AffineTransform::translation (state->fillType.imageX, state->fillType.imageY), true); | |||||
| } | |||||
| CGContextRestoreGState (context); | |||||
| } | |||||
| void fillPathWithImage (const Path& path, const AffineTransform& transform, | |||||
| const Image& image, int imageX, int imageY) | |||||
| { | |||||
| CGContextSaveGState (context); | |||||
| createPath (path, transform); | |||||
| CGContextClip (context); | |||||
| blendImage (image, imageX, imageY, image.getWidth(), image.getHeight(), 0, 0); | |||||
| CGContextRestoreGState (context); | |||||
| } | |||||
| void fillAlphaChannel (const Image& alphaImage, int alphaImageX, int alphaImageY) | |||||
| { | |||||
| Image* singleChannelImage = createAlphaChannelImage (alphaImage); | |||||
| CGImageRef image = createImage (*singleChannelImage, true); | |||||
| CGContextSaveGState (context); | |||||
| CGContextSetAlpha (context, 1.0f); | |||||
| CGRect r = CGRectMake (alphaImageX, flipHeight - (alphaImageY + alphaImage.getHeight()), | |||||
| alphaImage.getWidth(), alphaImage.getHeight()); | |||||
| CGContextClipToMask (context, r, image); | |||||
| fillRect (alphaImageX, alphaImageY, alphaImage.getWidth(), alphaImage.getHeight(), false); | |||||
| CGContextRestoreGState (context); | CGContextRestoreGState (context); | ||||
| CGImageRelease (image); | |||||
| deleteAlphaChannelImage (alphaImage, singleChannelImage); | |||||
| } | } | ||||
| void fillAlphaChannelWithImage (const Image& alphaImage, int alphaImageX, int alphaImageY, | |||||
| const Image& fillerImage, int fillerImageX, int fillerImageY) | |||||
| void drawImage (const Image& sourceImage, const Rectangle& srcClip, | |||||
| const AffineTransform& transform, const bool fillEntireClipAsTiles) | |||||
| { | { | ||||
| Image* singleChannelImage = createAlphaChannelImage (alphaImage); | |||||
| CGImageRef image = createImage (*singleChannelImage, true); | |||||
| CGImageRef fullImage = createImage (sourceImage, false); | |||||
| CGImageRef image = CGImageCreateWithImageInRect (fullImage, CGRectMake (srcClip.getX(), sourceImage.getHeight() - srcClip.getBottom(), | |||||
| srcClip.getWidth(), srcClip.getHeight())); | |||||
| CGImageRelease (fullImage); | |||||
| CGContextSaveGState (context); | CGContextSaveGState (context); | ||||
| CGRect r = CGRectMake (alphaImageX, flipHeight - (alphaImageY + alphaImage.getHeight()), | |||||
| alphaImage.getWidth(), alphaImage.getHeight()); | |||||
| CGContextClipToMask (context, r, image); | |||||
| blendImage (fillerImage, fillerImageX, fillerImageY, | |||||
| fillerImage.getWidth(), fillerImage.getHeight(), | |||||
| 0, 0); | |||||
| CGContextSetAlpha (context, state->fillType.colour.getFloatAlpha()); | |||||
| CGContextRestoreGState (context); | |||||
| flip(); | |||||
| applyTransform (AffineTransform::scale (1.0f, -1.0f).translated (0, sourceImage.getHeight()).followedBy (transform)); | |||||
| CGRect imageRect = CGRectMake (0, 0, sourceImage.getWidth(), sourceImage.getHeight()); | |||||
| CGImageRelease (image); | |||||
| deleteAlphaChannelImage (alphaImage, singleChannelImage); | |||||
| } | |||||
| if (fillEntireClipAsTiles) | |||||
| { | |||||
| #if JUCE_IPHONE || (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) | |||||
| CGContextDrawTiledImage (context, imageRect, image); | |||||
| #else | |||||
| #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 | |||||
| if (CGContextDrawTiledImage != 0) | |||||
| CGContextDrawTiledImage (context, imageRect, image); | |||||
| else | |||||
| #endif | |||||
| { | |||||
| // Fallback to manually doing a tiled fill on 10.4 | |||||
| CGRect clip = CGRectIntegral (CGContextGetClipBoundingBox (context)); | |||||
| const int iw = sourceImage.getWidth(); | |||||
| const int ih = sourceImage.getHeight(); | |||||
| //============================================================================== | |||||
| void blendImage (const Image& sourceImage, | |||||
| int destX, int destY, int destW, int destH, int sourceX, int sourceY) | |||||
| { | |||||
| CGImageRef image = createImage (sourceImage, false); | |||||
| int x = 0, y = 0; | |||||
| while (x > clip.origin.x) x -= iw; | |||||
| while (y > clip.origin.y) y -= ih; | |||||
| CGContextSaveGState (context); | |||||
| CGContextClipToRect (context, CGRectMake (destX, flipHeight - (destY + destH), destW, destH)); | |||||
| CGContextSetAlpha (context, state->colour.getFloatAlpha()); | |||||
| CGContextDrawImage (context, CGRectMake (destX - sourceX, | |||||
| flipHeight - ((destY - sourceY) + sourceImage.getHeight()), | |||||
| sourceImage.getWidth(), | |||||
| sourceImage.getHeight()), image); | |||||
| const int right = clip.origin.x + clip.size.width; | |||||
| const int bottom = clip.origin.y + clip.size.height; | |||||
| CGContextRestoreGState (context); | |||||
| CGImageRelease (image); | |||||
| } | |||||
| while (y < bottom) | |||||
| { | |||||
| for (int x2 = x; x2 < right; x2 += iw) | |||||
| CGContextDrawImage (context, CGRectMake (x2, y, iw, ih), image); | |||||
| void blendImageWarping (const Image& sourceImage, | |||||
| int srcClipX, int srcClipY, int srcClipW, int srcClipH, | |||||
| const AffineTransform& transform) | |||||
| { | |||||
| CGImageRef fullImage = createImage (sourceImage, false); | |||||
| CGImageRef image = CGImageCreateWithImageInRect (fullImage, CGRectMake (srcClipX, sourceImage.getHeight() - (srcClipY + srcClipH), | |||||
| srcClipW, srcClipH)); | |||||
| CGImageRelease (fullImage); | |||||
| CGContextSaveGState (context); | |||||
| flip(); | |||||
| applyTransform (AffineTransform::scale (1.0f, -1.0f).translated (0, sourceImage.getHeight()).followedBy (transform)); | |||||
| CGContextSetAlpha (context, state->colour.getFloatAlpha()); | |||||
| CGContextDrawImage (context, CGRectMake (0, 0, sourceImage.getWidth(), | |||||
| sourceImage.getHeight()), image); | |||||
| y += ih; | |||||
| } | |||||
| } | |||||
| #endif | |||||
| } | |||||
| else | |||||
| { | |||||
| CGContextDrawImage (context, imageRect, image); | |||||
| } | |||||
| CGImageRelease (image); | CGImageRelease (image); | ||||
| CGContextRestoreGState (context); | CGContextRestoreGState (context); | ||||
| @@ -366,8 +385,8 @@ public: | |||||
| CGContextSetLineCap (context, kCGLineCapSquare); | CGContextSetLineCap (context, kCGLineCapSquare); | ||||
| CGContextSetLineWidth (context, 1.0f); | CGContextSetLineWidth (context, 1.0f); | ||||
| CGContextSetRGBStrokeColor (context, | CGContextSetRGBStrokeColor (context, | ||||
| state->colour.getFloatRed(), state->colour.getFloatGreen(), | |||||
| state->colour.getFloatBlue(), state->colour.getFloatAlpha()); | |||||
| state->fillType.colour.getFloatRed(), state->fillType.colour.getFloatGreen(), | |||||
| state->fillType.colour.getFloatBlue(), state->fillType.colour.getFloatAlpha()); | |||||
| CGPoint line[] = { { x1 + 0.5f, flipHeight - (y1 + 0.5f) }, | CGPoint line[] = { { x1 + 0.5f, flipHeight - (y1 + 0.5f) }, | ||||
| { x2 + 0.5f, flipHeight - (y2 + 0.5f) } }; | { x2 + 0.5f, flipHeight - (y2 + 0.5f) } }; | ||||
| @@ -407,40 +426,46 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| void drawGlyph (int glyphNumber, float x, float y) | |||||
| const Font getFont() | |||||
| { | { | ||||
| if (state->fontRef != 0 && state->gradient == 0) | |||||
| { | |||||
| CGGlyph g = glyphNumber; | |||||
| CGContextShowGlyphsAtPoint (context, x, flipHeight - roundFloatToInt (y), &g, 1); | |||||
| } | |||||
| else | |||||
| { | |||||
| state->font.renderGlyphIndirectly (*this, glyphNumber, x, y); | |||||
| } | |||||
| return state->font; | |||||
| } | } | ||||
| void drawGlyph (int glyphNumber, const AffineTransform& transform) | void drawGlyph (int glyphNumber, const AffineTransform& transform) | ||||
| { | { | ||||
| if (state->fontRef != 0) | |||||
| if (state->fontRef != 0 && state->fillType.isColour()) | |||||
| { | { | ||||
| CGContextSaveGState (context); | |||||
| flip(); | |||||
| applyTransform (transform); | |||||
| if (transform.isOnlyTranslation()) | |||||
| { | |||||
| CGGlyph g = glyphNumber; | |||||
| CGContextShowGlyphsAtPoint (context, transform.getTranslationX(), | |||||
| flipHeight - roundFloatToInt (transform.getTranslationY()), &g, 1); | |||||
| } | |||||
| else | |||||
| { | |||||
| CGContextSaveGState (context); | |||||
| flip(); | |||||
| applyTransform (transform); | |||||
| CGAffineTransform t = state->fontTransform; | |||||
| t.d = -t.d; | |||||
| CGContextSetTextMatrix (context, t); | |||||
| CGAffineTransform t = state->fontTransform; | |||||
| t.d = -t.d; | |||||
| CGContextSetTextMatrix (context, t); | |||||
| CGGlyph g = glyphNumber; | |||||
| CGContextShowGlyphsAtPoint (context, 0, 0, &g, 1); | |||||
| CGGlyph g = glyphNumber; | |||||
| CGContextShowGlyphsAtPoint (context, 0, 0, &g, 1); | |||||
| CGContextSetTextMatrix (context, state->fontTransform); | |||||
| CGContextRestoreGState (context); | |||||
| CGContextSetTextMatrix (context, state->fontTransform); | |||||
| CGContextRestoreGState (context); | |||||
| } | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| state->font.renderGlyphIndirectly (*this, glyphNumber, transform); | |||||
| Path p; | |||||
| Font& f = state->font; | |||||
| f.getTypeface()->getOutlineForGlyph (glyphNumber, p); | |||||
| fillPath (p, AffineTransform::scale (f.getHeight() * f.getHorizontalScale(), f.getHeight()) | |||||
| .followedBy (transform)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -453,26 +478,21 @@ private: | |||||
| struct SavedState | struct SavedState | ||||
| { | { | ||||
| SavedState() throw() | SavedState() throw() | ||||
| : gradient (0), font (1.0f), fontRef (0), | |||||
| fontTransform (CGAffineTransformIdentity) | |||||
| : font (1.0f), fontRef (0), fontTransform (CGAffineTransformIdentity) | |||||
| { | { | ||||
| } | } | ||||
| SavedState (const SavedState& other) throw() | SavedState (const SavedState& other) throw() | ||||
| : colour (other.colour), | |||||
| gradient (other.gradient != 0 ? new ColourGradient (*other.gradient) : 0), | |||||
| font (other.font), fontRef (other.fontRef), | |||||
| : fillType (other.fillType), font (other.font), fontRef (other.fontRef), | |||||
| fontTransform (other.fontTransform) | fontTransform (other.fontTransform) | ||||
| { | { | ||||
| } | } | ||||
| ~SavedState() throw() | ~SavedState() throw() | ||||
| { | { | ||||
| delete gradient; | |||||
| } | } | ||||
| Colour colour; | |||||
| ColourGradient* gradient; | |||||
| Graphics::FillType fillType; | |||||
| Font font; | Font font; | ||||
| CGFontRef fontRef; | CGFontRef fontRef; | ||||
| CGAffineTransform fontTransform; | CGAffineTransform fontTransform; | ||||
| @@ -480,21 +500,31 @@ private: | |||||
| SavedState* state; | SavedState* state; | ||||
| OwnedArray <SavedState> stateStack; | OwnedArray <SavedState> stateStack; | ||||
| PixelARGB* gradientLookupTable; | |||||
| int numGradientLookupEntries; | |||||
| static void gradientCallback (void* info, const CGFloat* inData, CGFloat* outData) | static void gradientCallback (void* info, const CGFloat* inData, CGFloat* outData) | ||||
| { | { | ||||
| const ColourGradient* const g = (const ColourGradient*) info; | |||||
| const Colour c (g->getColourAtPosition (inData[0])); | |||||
| outData[0] = c.getFloatRed(); | |||||
| outData[1] = c.getFloatGreen(); | |||||
| outData[2] = c.getFloatBlue(); | |||||
| outData[3] = c.getFloatAlpha(); | |||||
| const CoreGraphicsContext* const g = (const CoreGraphicsContext*) info; | |||||
| const int index = roundFloatToInt (g->numGradientLookupEntries * inData[0]); | |||||
| PixelARGB colour (g->gradientLookupTable [jlimit (0, g->numGradientLookupEntries, index)]); | |||||
| colour.unpremultiply(); | |||||
| outData[0] = colour.getRed() / 255.0f; | |||||
| outData[1] = colour.getGreen() / 255.0f; | |||||
| outData[2] = colour.getBlue() / 255.0f; | |||||
| outData[3] = colour.getAlpha() / 255.0f; | |||||
| } | } | ||||
| CGShadingRef createGradient (const ColourGradient* const gradient) const throw() | |||||
| CGShadingRef createGradient (const ColourGradient* const gradient) throw() | |||||
| { | { | ||||
| delete gradientLookupTable; | |||||
| gradientLookupTable = gradient->createLookupTable (numGradientLookupEntries); | |||||
| --numGradientLookupEntries; | |||||
| CGShadingRef result = 0; | CGShadingRef result = 0; | ||||
| CGFunctionRef function = CGFunctionCreate ((void*) gradient, 1, 0, 4, 0, &gradientCallbacks); | |||||
| CGFunctionRef function = CGFunctionCreate ((void*) this, 1, 0, 4, 0, &gradientCallbacks); | |||||
| CGPoint p1 (CGPointMake (gradient->x1, gradient->y1)); | CGPoint p1 (CGPointMake (gradient->x1, gradient->y1)); | ||||
| if (gradient->isRadial) | if (gradient->isRadial) | ||||
| @@ -514,12 +544,12 @@ private: | |||||
| return result; | return result; | ||||
| } | } | ||||
| void drawGradient() const throw() | |||||
| void drawGradient() throw() | |||||
| { | { | ||||
| CGContextSetAlpha (context, 1.0f); | CGContextSetAlpha (context, 1.0f); | ||||
| CGContextSetInterpolationQuality (context, kCGInterpolationDefault); // (This is required for 10.4, where there's a crash if | CGContextSetInterpolationQuality (context, kCGInterpolationDefault); // (This is required for 10.4, where there's a crash if | ||||
| // you draw a gradient with high quality interp enabled). | // you draw a gradient with high quality interp enabled). | ||||
| CGShadingRef shading = createGradient (state->gradient); | |||||
| CGShadingRef shading = createGradient (state->fillType.gradient); | |||||
| CGContextDrawShading (context, shading); | CGContextDrawShading (context, shading); | ||||
| CGShadingRelease (shading); | CGShadingRelease (shading); | ||||
| } | } | ||||
| @@ -409,7 +409,7 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | |||||
| if (e != 0 && ! isEventBlockedByModalComps (e)) | if (e != 0 && ! isEventBlockedByModalComps (e)) | ||||
| [NSApp sendEvent: e]; | [NSApp sendEvent: e]; | ||||
| if (Time::getMillisecondCounter() >= endTime) | if (Time::getMillisecondCounter() >= endTime) | ||||
| break; | break; | ||||
| } | } | ||||
| @@ -1471,7 +1471,7 @@ void NSViewComponentPeer::drawRect (NSRect r) | |||||
| roundFloatToInt (rects[i].size.height))); | roundFloatToInt (rects[i].size.height))); | ||||
| } | } | ||||
| if (context.reduceClipRegion (clip)) | |||||
| if (context.clipToRectangleList (clip)) | |||||
| { | { | ||||
| insideDrawRect = true; | insideDrawRect = true; | ||||
| handlePaint (context); | handlePaint (context); | ||||
| @@ -35,7 +35,7 @@ | |||||
| #include "../../core/juce_StandardHeader.h" | #include "../../core/juce_StandardHeader.h" | ||||
| #define USE_COREGRAPHICS_RENDERING 0 | |||||
| #define USE_COREGRAPHICS_RENDERING 1 | |||||
| #if JUCE_IPHONE | #if JUCE_IPHONE | ||||
| #import <Foundation/Foundation.h> | #import <Foundation/Foundation.h> | ||||
| @@ -1253,7 +1253,7 @@ private: | |||||
| updateCurrentModifiers(); | updateCurrentModifiers(); | ||||
| LowLevelGraphicsSoftwareRenderer context (*offscreenImage); | LowLevelGraphicsSoftwareRenderer context (*offscreenImage); | ||||
| context.reduceClipRegion (contextClip); | |||||
| context.clipToRectangleList (contextClip); | |||||
| context.setOrigin (-x, -y); | context.setOrigin (-x, -y); | ||||
| handlePaint (context); | handlePaint (context); | ||||