Browse Source

Removed the Brush classes - everything they used to do can still be done by other methods in the Graphics class. Also did more optimising of the graphics contexts, both software and CoreGraphics.

tags/2021-05-28
Julian Storer 16 years ago
parent
commit
f6a088961f
41 changed files with 4256 additions and 6968 deletions
  1. +0
    -36
      build/win32/vc8/JUCE.vcproj
  2. +17
    -20
      extras/juce demo/src/demos/PathsAndTransformsDemo.cpp
  3. +6
    -7
      extras/the jucer/src/model/paintelements/jucer_FillType.cpp
  4. +1
    -1
      extras/the jucer/src/model/paintelements/jucer_FillType.h
  5. +2
    -8
      extras/the jucer/src/model/paintelements/jucer_PaintElementEllipse.h
  6. +3
    -11
      extras/the jucer/src/model/paintelements/jucer_PaintElementPath.cpp
  7. +2
    -8
      extras/the jucer/src/model/paintelements/jucer_PaintElementRectangle.h
  8. +2
    -9
      extras/the jucer/src/model/paintelements/jucer_PaintElementRoundedRectangle.h
  9. +1
    -4
      extras/the jucer/src/model/paintelements/jucer_PaintElementText.h
  10. +1175
    -1943
      juce_amalgamated.cpp
  11. +1912
    -2325
      juce_amalgamated.h
  12. +0
    -70
      src/gui/graphics/brushes/juce_Brush.cpp
  13. +0
    -100
      src/gui/graphics/brushes/juce_Brush.h
  14. +0
    -108
      src/gui/graphics/brushes/juce_GradientBrush.cpp
  15. +0
    -113
      src/gui/graphics/brushes/juce_GradientBrush.h
  16. +0
    -224
      src/gui/graphics/brushes/juce_ImageBrush.cpp
  17. +0
    -104
      src/gui/graphics/brushes/juce_ImageBrush.h
  18. +0
    -123
      src/gui/graphics/brushes/juce_SolidColourBrush.cpp
  19. +0
    -108
      src/gui/graphics/brushes/juce_SolidColourBrush.h
  20. +11
    -5
      src/gui/graphics/colour/juce_Colour.cpp
  21. +80
    -84
      src/gui/graphics/contexts/juce_EdgeTable.cpp
  22. +4
    -2
      src/gui/graphics/contexts/juce_EdgeTable.h
  23. +125
    -337
      src/gui/graphics/contexts/juce_Graphics.cpp
  24. +8
    -33
      src/gui/graphics/contexts/juce_Graphics.h
  25. +14
    -31
      src/gui/graphics/contexts/juce_LowLevelGraphicsContext.h
  26. +4
    -1
      src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp
  27. +559
    -555
      src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp
  28. +15
    -51
      src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h
  29. +0
    -186
      src/gui/graphics/fonts/juce_Font.cpp
  30. +0
    -18
      src/gui/graphics/fonts/juce_Font.h
  31. +1
    -1
      src/gui/graphics/fonts/juce_GlyphArrangement.cpp
  32. +34
    -70
      src/gui/graphics/geometry/juce_Path.cpp
  33. +9
    -15
      src/gui/graphics/geometry/juce_Path.h
  34. +0
    -4
      src/juce_amalgamated_template.cpp
  35. +62
    -74
      src/juce_app_includes.h
  36. +16
    -16
      src/juce_core_includes.h
  37. +189
    -159
      src/native/mac/juce_mac_CoreGraphicsContext.mm
  38. +1
    -1
      src/native/mac/juce_mac_MessageManager.mm
  39. +1
    -1
      src/native/mac/juce_mac_NSViewComponentPeer.mm
  40. +1
    -1
      src/native/mac/juce_mac_NativeIncludes.h
  41. +1
    -1
      src/native/windows/juce_win32_Windowing.cpp

+ 0
- 36
build/win32/vc8/JUCE.vcproj View File

@@ -2168,42 +2168,6 @@
<Filter
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
Name="colour"
>


+ 17
- 20
extras/juce demo/src/demos/PathsAndTransformsDemo.cpp View File

@@ -130,20 +130,18 @@ public:
}
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());
}
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());
}
else if (type == 4 || type == 5)
@@ -179,16 +177,16 @@ public:
}
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)
{
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,
0, 0, image->getWidth(), image->getHeight(),
AffineTransform::translation (-0.5f * image->getWidth(), -0.5f * image->getHeight())
@@ -198,11 +196,10 @@ public:
}
else if (type == 9)
{
ImageBrush ib (image, 100, 100, (float) opacitySlider->getValue());
g.setBrush (&ib);
if (image != 0)
{
g.setTiledImageFill (*image, 100, 100, (float) opacitySlider->getValue());
g.drawImageTransformed (image,
0, 0, image->getWidth(), image->getHeight(),
AffineTransform::translation (-0.5f * image->getWidth(),


+ 6
- 7
extras/the jucer/src/model/paintelements/jucer_FillType.cpp View File

@@ -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)
{
ImageCache::release (image);
image = 0;
return new SolidColourBrush (colour);
g.setColour (colour);
}
else if (mode == imageBrush)
{
@@ -126,7 +125,7 @@ Brush* FillType::createBrush (JucerDocument* const document,
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
{
@@ -136,9 +135,9 @@ Brush* FillType::createBrush (JucerDocument* const document,
Rectangle r1 (gradPos1.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));
}
}


+ 1
- 1
extras/the jucer/src/model/paintelements/jucer_FillType.h View File

@@ -46,7 +46,7 @@ public:
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;


+ 2
- 8
extras/the jucer/src/model/paintelements/jucer_PaintElementEllipse.h View File

@@ -45,23 +45,17 @@ public:
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));
g.fillEllipse ((float) r.getX(), (float) r.getY(), (float) r.getWidth(), (float) r.getHeight());
delete brush;
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(),
getStrokeType().stroke.getStrokeThickness());
delete brush;
}
}


+ 3
- 11
extras/the jucer/src/model/paintelements/jucer_PaintElementPath.cpp View File

@@ -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)
{
Brush* const brush = fillType.createBrush (getDocument(), parentArea);
g.setBrush (brush);
updateStoredPath (layout, parentArea);
path.setUsingNonZeroWinding (nonZeroWinding);
g.fillPath (path);
delete brush;
fillType.setFillType (g, getDocument(), parentArea);
g.fillPath (path);
if (isStrokePresent)
{
Brush* const brush = strokeType.fill.createBrush (getDocument(), parentArea);
g.setBrush (brush);
strokeType.fill.setFillType (g, getDocument(), parentArea);
g.strokePath (path, getStrokeType().stroke);
delete brush;
}
}


+ 2
- 8
extras/the jucer/src/model/paintelements/jucer_PaintElementRectangle.h View File

@@ -60,23 +60,17 @@ public:
Component parentComponent;
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));
g.fillRect (r);
delete brush;
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(),
roundDoubleToInt (getStrokeType().stroke.getStrokeThickness()));
delete brush;
}
}


+ 2
- 9
extras/the jucer/src/model/paintelements/jucer_PaintElementRoundedRectangle.h View File

@@ -47,25 +47,18 @@ public:
//==============================================================================
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;
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);
delete brush;
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,
getStrokeType().stroke.getStrokeThickness());
delete brush;
}
}


+ 1
- 4
extras/the jucer/src/model/paintelements/jucer_PaintElementText.h View File

@@ -57,8 +57,7 @@ public:
//==============================================================================
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);
g.setFont (font);
@@ -67,8 +66,6 @@ public:
g.drawText (replaceStringTranslations (text, owner->getDocument()),
r.getX(), r.getY(), r.getWidth(), r.getHeight(),
justification, true);
delete brush;
}
void getEditableProperties (Array <PropertyComponent*>& properties)


+ 1175
- 1943
juce_amalgamated.cpp
File diff suppressed because it is too large
View File


+ 1912
- 2325
juce_amalgamated.h
File diff suppressed because it is too large
View File


+ 0
- 70
src/gui/graphics/brushes/juce_Brush.cpp View File

@@ -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

+ 0
- 100
src/gui/graphics/brushes/juce_Brush.h View File

@@ -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__

+ 0
- 108
src/gui/graphics/brushes/juce_GradientBrush.cpp View File

@@ -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

+ 0
- 113
src/gui/graphics/brushes/juce_GradientBrush.h View File

@@ -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__

+ 0
- 224
src/gui/graphics/brushes/juce_ImageBrush.cpp View File

@@ -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

+ 0
- 104
src/gui/graphics/brushes/juce_ImageBrush.h View File

@@ -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__

+ 0
- 123
src/gui/graphics/brushes/juce_SolidColourBrush.cpp View File

@@ -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

+ 0
- 108
src/gui/graphics/brushes/juce_SolidColourBrush.h View File

@@ -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__

+ 11
- 5
src/gui/graphics/colour/juce_Colour.cpp View File

@@ -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 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());
}
//==============================================================================


+ 80
- 84
src/gui/graphics/contexts/juce_EdgeTable.cpp View File

@@ -49,7 +49,8 @@ EdgeTable::EdgeTable (const Rectangle& bounds_,
const Path& path, const AffineTransform& transform) throw()
: bounds (bounds_),
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));
int* t = table;
@@ -167,7 +168,8 @@ EdgeTable::EdgeTable (const Rectangle& bounds_,
EdgeTable::EdgeTable (const Rectangle& rectangleToAdd) throw()
: bounds (rectangleToAdd),
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 = 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()
: bounds (Rectangle ((int) floorf (x), roundFloatToInt (y * 256.0f) >> 8, 2 + (int) w, 2 + (int) h)),
maxEdgesPerLine (juce_edgeTableDefaultEdgesPerLine),
lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1)
lineStrideElements ((juce_edgeTableDefaultEdgesPerLine << 1) + 1),
needToCheckEmptinesss (true)
{
jassert (w > 0 && h > 0);
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;
maxEdgesPerLine = other.maxEdgesPerLine;
lineStrideElements = other.lineStrideElements;
needToCheckEmptinesss = other.needToCheckEmptinesss;
const int tableSize = jmax (1, bounds.getHeight()) * lineStrideElements * sizeof (int);
table = (int*) juce_malloc (tableSize);
@@ -358,6 +362,27 @@ void EdgeTable::addEdgePoint (const int x, const int y, const int winding) throw
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()
{
jassert (y >= 0 && y < bounds.getHeight());
@@ -482,6 +507,7 @@ void EdgeTable::clipToRectangle (const Rectangle& r) throw()
if (clipped.isEmpty())
{
needToCheckEmptinesss = false;
bounds.setHeight (0);
}
else
@@ -505,6 +531,8 @@ void EdgeTable::clipToRectangle (const Rectangle& r) throw()
for (int i = top; i < bottom; ++i)
intersectWithEdgeTableLine (i, rectLine);
}
needToCheckEmptinesss = true;
}
}
@@ -523,6 +551,8 @@ void EdgeTable::excludeRectangle (const Rectangle& r) throw()
for (int i = top; i < bottom; ++i)
intersectWithEdgeTableLine (i, rectLine);
needToCheckEmptinesss = true;
}
}
@@ -532,6 +562,7 @@ void EdgeTable::clipToEdgeTable (const EdgeTable& other)
if (clipped.isEmpty())
{
needToCheckEmptinesss = false;
bounds.setHeight (0);
}
else
@@ -555,109 +586,74 @@ void EdgeTable::clipToEdgeTable (const EdgeTable& other)
intersectWithEdgeTableLine (i, otherLine);
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

+ 4
- 2
src/gui/graphics/contexts/juce_EdgeTable.h View File

@@ -78,9 +78,10 @@ public:
void clipToRectangle (const Rectangle& r) throw();
void excludeRectangle (const Rectangle& r) throw();
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; }
void translate (float dx, int dy) throw();
/** Reduces the amount of space the table has allocated.
@@ -192,6 +193,7 @@ private:
int* table;
Rectangle bounds;
int maxEdgesPerLine, lineStrideElements;
bool needToCheckEmptinesss;
void addEdgePoint (const int x, const int y, const int winding) throw();
void remapTableForNumEdges (const int newNumEdgesPerLine) throw();


+ 125
- 337
src/gui/graphics/contexts/juce_Graphics.cpp View File

@@ -31,8 +31,6 @@ BEGIN_JUCE_NAMESPACE
#include "../fonts/juce_GlyphArrangement.h"
#include "../geometry/juce_PathStrokeType.h"
#include "juce_LowLevelGraphicsContext.h"
#include "../brushes/juce_GradientBrush.h"
#include "../brushes/juce_ImageBrush.h"
static const Graphics::ResamplingQuality defaultQuality = Graphics::mediumResamplingQuality;
@@ -65,7 +63,6 @@ LowLevelGraphicsContext::~LowLevelGraphicsContext()
Graphics::Graphics (Image& imageToDrawOnto) throw()
: context (imageToDrawOnto.createLowLevelContext()),
ownsContext (true),
state (new GraphicsState()),
saveStatePending (false)
{
resetToDefaultState();
@@ -74,7 +71,6 @@ Graphics::Graphics (Image& imageToDrawOnto) throw()
Graphics::Graphics (LowLevelGraphicsContext* const internalContext) throw()
: context (internalContext),
ownsContext (false),
state (new GraphicsState()),
saveStatePending (false)
{
resetToDefaultState();
@@ -82,8 +78,6 @@ Graphics::Graphics (LowLevelGraphicsContext* const internalContext) throw()
Graphics::~Graphics() throw()
{
delete state;
if (ownsContext)
delete context;
}
@@ -106,20 +100,20 @@ bool Graphics::reduceClipRegion (const int x, const int y,
const int w, const int h) throw()
{
saveStateIfPending();
return context->reduceClipRegion (x, y, w, h);
return context->clipToRectangle (Rectangle (x, y, w, h));
}
bool Graphics::reduceClipRegion (const RectangleList& clipRegion) throw()
{
saveStateIfPending();
return context->reduceClipRegion (clipRegion);
return context->clipToRectangleList (clipRegion);
}
void Graphics::excludeClipRegion (const int x, const int y,
const int w, const int h) throw()
{
saveStateIfPending();
context->excludeClipRegion (x, y, w, h);
context->excludeClipRectangle (Rectangle (x, y, w, h));
}
bool Graphics::isClipEmpty() const throw()
@@ -141,29 +135,9 @@ void Graphics::saveState() throw()
void Graphics::restoreState() throw()
{
if (saveStatePending)
{
saveStatePending = false;
}
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()
@@ -171,9 +145,7 @@ void Graphics::saveStateIfPending() throw()
if (saveStatePending)
{
saveStatePending = false;
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,
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()
{
saveStateIfPending();
deleteAndZero (state->brush);
context->setColour (newColour);
}
@@ -205,75 +175,26 @@ void Graphics::setOpacity (const float newOpacity) throw()
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()
{
saveStateIfPending();
deleteAndZero (state->brush);
context->setGradient (gradient);
}
void Graphics::setTiledImageFill (Image& imageToUse,
void Graphics::setTiledImageFill (const Image& imageToUse,
const int anchorX,
const int anchorY,
const float opacity) throw()
{
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()
{
saveStateIfPending();
state->font = newFont;
context->setFont (newFont);
}
@@ -281,8 +202,9 @@ void Graphics::setFont (const float newFontHeight,
const int newFontStyleFlags) throw()
{
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())
{
GlyphArrangement arr;
arr.addLineOfText (state->font, text, (float) startX, (float) baselineY);
arr.addLineOfText (context->getFont(), text, (float) startX, (float) baselineY);
arr.draw (*this);
}
}
@@ -305,7 +227,7 @@ void Graphics::drawTextAsPath (const String& text,
if (text.isNotEmpty())
{
GlyphArrangement arr;
arr.addLineOfText (state->font, text, 0.0f, 0.0f);
arr.addLineOfText (context->getFont(), text, 0.0f, 0.0f);
arr.draw (*this, transform);
}
}
@@ -319,7 +241,7 @@ void Graphics::drawMultiLineText (const String& text,
&& startX < context->getClipBounds().getRight())
{
GlyphArrangement arr;
arr.addJustifiedText (state->font, text,
arr.addJustifiedText (context->getFont(), text,
(float) startX, (float) baselineY, (float) maximumLineWidth,
Justification::left);
arr.draw (*this);
@@ -334,11 +256,11 @@ void Graphics::drawText (const String& text,
const Justification& justificationType,
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;
arr.addCurtailedLineOfText (state->font, text,
arr.addCurtailedLineOfText (context->getFont(), text,
0.0f, 0.0f, (float)width,
useEllipsesIfTooBig);
@@ -361,11 +283,11 @@ void Graphics::drawFittedText (const String& text,
{
if (text.isNotEmpty()
&& width > 0 && height > 0
&& context->clipRegionIntersects (x, y, width, height))
&& context->clipRegionIntersects (Rectangle (x, y, width, height)))
{
GlyphArrangement arr;
arr.addFittedText (state->font, text,
arr.addFittedText (context->getFont(), text,
(float) x, (float) y,
(float) width, (float) height,
justification,
@@ -385,18 +307,12 @@ void Graphics::fillRect (int x,
// passing in a silly number can cause maths problems in rendering!
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()
{
fillRect (r.getX(),
r.getY(),
r.getWidth(),
r.getHeight());
context->fillRect (r, false);
}
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()
{
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()
@@ -436,7 +346,7 @@ void Graphics::fillAll (const Colour& colourToUse) const throw()
context->saveState();
context->setColour (colourToUse);
context->fillRect (clip.getX(), clip.getY(), clip.getWidth(), clip.getHeight(), false);
context->fillRect (clip, false);
context->restoreState();
}
}
@@ -447,24 +357,16 @@ void Graphics::fillPath (const Path& path,
const AffineTransform& transform) const throw()
{
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,
const PathStrokeType& strokeType,
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!
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,
@@ -545,13 +436,13 @@ void Graphics::drawBevel (const int x,
: oldOpacity;
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->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->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->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();
@@ -667,7 +558,7 @@ void Graphics::fillCheckerBoard (int x, int y,
if (colour1 == colour2)
{
context->setColour (colour1);
context->fillRect (x, y, width, height, false);
context->fillRect (Rectangle (x, y, width, height), false);
}
else
{
@@ -684,9 +575,7 @@ void Graphics::fillCheckerBoard (int x, int y,
for (int xx = x; xx < right; xx += checkWidth)
{
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);
}
@@ -702,30 +591,17 @@ void Graphics::fillCheckerBoard (int x, int y,
//==============================================================================
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()
{
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,
@@ -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 (sx, sy, sw, sh);
if (imageToDraw == 0 || ! context->clipRegionIntersects (dx, dy, dw, dh))
if (! context->clipRegionIntersects (Rectangle (dx, dy, dw, dh)))
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,
@@ -994,72 +758,96 @@ void Graphics::drawImageTransformed (const Image* const imageToDraw,
const AffineTransform& transform,
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

+ 8
- 33
src/gui/graphics/contexts/juce_Graphics.h View File

@@ -32,7 +32,6 @@
#include "../geometry/juce_Line.h"
#include "../colour/juce_Colours.h"
#include "../colour/juce_ColourGradient.h"
#include "../brushes/juce_SolidColourBrush.h"
#include "juce_RectanglePlacement.h"
class LowLevelGraphicsContext;
class Image;
@@ -79,7 +78,7 @@ public:
If a brush is being used when this method is called, the brush will be deselected,
and any subsequent drawing will be done with a solid colour brush instead.
@see setOpacity, setBrush
@see setOpacity
*/
void setColour (const Colour& newColour) throw();
@@ -94,18 +93,6 @@ public:
*/
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.
*/
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
this context!
*/
void setTiledImageFill (Image& imageToUse,
void setTiledImageFill (const Image& imageToUse,
const int anchorX,
const int anchorY,
const float opacity) throw();
@@ -698,12 +685,13 @@ public:
LowLevelGraphicsContext* getInternalContext() const throw() { return context; }
//==============================================================================
/*class FillType
class FillType
{
public:
FillType() throw();
FillType (const Colour& colour) 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();
const FillType& operator= (const FillType& other) throw();
~FillType() throw();
@@ -714,35 +702,22 @@ public:
void setColour (const Colour& newColour) 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;
ColourGradient* gradient;
Image* image;
const Image* image;
int imageX, imageY;
juce_UseDebuggingNewOperator
};*/
};
private:
//==============================================================================
LowLevelGraphicsContext* const context;
const bool ownsContext;
struct GraphicsState
{
GraphicsState() throw();
GraphicsState (const GraphicsState&) throw();
~GraphicsState() throw();
Brush* brush;
Font font;
};
GraphicsState* state;
OwnedArray <GraphicsState> stateStack;
bool saveStatePending;
void saveStateIfPending() throw();
const Graphics& operator= (const Graphics& other);


+ 14
- 31
src/gui/graphics/contexts/juce_LowLevelGraphicsContext.h View File

@@ -66,57 +66,40 @@ public:
*/
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 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 setGradient (const ColourGradient& gradient) = 0;
virtual void setTiledFill (const Image& image, int x, int y) = 0;
virtual void setOpacity (float opacity) = 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 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 drawVerticalLine (const int x, double top, double bottom) = 0;
virtual void drawHorizontalLine (const int y, double left, double right) = 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;
};


+ 4
- 1
src/gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp View File

@@ -613,7 +613,10 @@ void LowLevelGraphicsPostScriptRenderer::drawGlyph (int glyphNumber, float x, fl
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

+ 559
- 555
src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp
File diff suppressed because it is too large
View File


+ 15
- 51
src/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h View File

@@ -49,45 +49,35 @@ public:
//==============================================================================
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 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;
bool isClipEmpty() const;
void saveState();
void restoreState();
//==============================================================================
void setColour (const Colour& colour);
void setGradient (const ColourGradient& gradient);
void setTiledFill (const Image& image, int x, int y);
void setOpacity (float opacity);
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 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 drawVerticalLine (const int x, double top, double bottom);
@@ -95,6 +85,7 @@ public:
//==============================================================================
void setFont (const Font& newFont);
const Font getFont();
void drawGlyph (int glyphNumber, float x, float y);
void drawGlyph (int glyphNumber, const AffineTransform& transform);
@@ -108,33 +99,6 @@ protected:
LLGCSavedState* currentState;
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);
const LowLevelGraphicsSoftwareRenderer& operator= (const LowLevelGraphicsSoftwareRenderer&);
};


+ 0
- 186
src/gui/graphics/fonts/juce_Font.cpp View File

@@ -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

+ 0
- 18
src/gui/graphics/fonts/juce_Font.h View File

@@ -307,24 +307,6 @@ public:
*/
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.


+ 1
- 1
src/gui/graphics/fonts/juce_GlyphArrangement.cpp View File

@@ -45,7 +45,7 @@ void PositionedGlyph::draw (const Graphics& g) const throw()
if (! isWhitespace())
{
g.getInternalContext()->setFont (font);
g.getInternalContext()->drawGlyph (glyph, x, y);
g.getInternalContext()->drawGlyph (glyph, AffineTransform::translation (x, y));
}
}


+ 34
- 70
src/gui/graphics/geometry/juce_Path.cpp View File

@@ -323,11 +323,40 @@ const Point Path::getCurrentPosition() const
void Path::addRectangle (const float x, const float y,
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,
@@ -1549,70 +1578,5 @@ bool Path::Iterator::next()
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

+ 9
- 15
src/gui/graphics/geometry/juce_Path.h View File

@@ -221,6 +221,15 @@ public:
void addRectangle (const float x, const float y,
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.
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);
//==============================================================================
/** 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


+ 0
- 4
src/juce_amalgamated_template.cpp View File

@@ -284,10 +284,6 @@
#include "gui/components/windows/juce_ThreadWithProgressWindow.cpp"
#include "gui/components/windows/juce_TooltipWindow.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_ColourGradient.cpp"
#include "gui/graphics/colour/juce_Colours.cpp"


+ 62
- 74
src/juce_app_includes.h View File

@@ -185,12 +185,6 @@
#ifndef __JUCE_AIFFAUDIOFORMAT_JUCEHEADER__
#include "audio/audio_file_formats/juce_AiffAudioFormat.h"
#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__
#include "audio/audio_file_formats/juce_AudioFormat.h"
#endif
@@ -215,14 +209,20 @@
#ifndef __JUCE_FLACAUDIOFORMAT_JUCEHEADER__
#include "audio/audio_file_formats/juce_FlacAudioFormat.h"
#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__
#include "audio/audio_file_formats/juce_OggVorbisAudioFormat.h"
#endif
#ifndef __JUCE_QUICKTIMEAUDIOFORMAT_JUCEHEADER__
#include "audio/audio_file_formats/juce_QuickTimeAudioFormat.h"
#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
#ifndef __JUCE_ACTIONBROADCASTER_JUCEHEADER__
#include "events/juce_ActionBroadcaster.h"
@@ -269,21 +269,6 @@
#ifndef __JUCE_TIMER_JUCEHEADER__
#include "events/juce_Timer.h"
#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__
#include "gui/graphics/colour/juce_Colour.h"
#endif
@@ -293,41 +278,44 @@
#ifndef __JUCE_COLOURGRADIENT_JUCEHEADER__
#include "gui/graphics/colour/juce_ColourGradient.h"
#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
#ifndef __JUCE_TEXTLAYOUT_JUCEHEADER__
#include "gui/graphics/fonts/juce_TextLayout.h"
#endif
#ifndef __JUCE_TYPEFACE_JUCEHEADER__
#include "gui/graphics/fonts/juce_Typeface.h"
#ifndef __JUCE_FONT_JUCEHEADER__
#include "gui/graphics/fonts/juce_Font.h"
#endif
#ifndef __JUCE_GLYPHARRANGEMENT_JUCEHEADER__
#include "gui/graphics/fonts/juce_GlyphArrangement.h"
#endif
#ifndef __JUCE_EDGETABLE_JUCEHEADER__
#include "gui/graphics/contexts/juce_EdgeTable.h"
#ifndef __JUCE_GRAPHICS_JUCEHEADER__
#include "gui/graphics/contexts/juce_Graphics.h"
#endif
#ifndef __JUCE_JUSTIFICATION_JUCEHEADER__
#include "gui/graphics/contexts/juce_Justification.h"
#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__
#include "gui/graphics/contexts/juce_LowLevelGraphicsContext.h"
#endif
#ifndef __JUCE_LOWLEVELGRAPHICSSOFTWARERENDERER_JUCEHEADER__
#include "gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h"
#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__
#include "gui/graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h"
#endif
#ifndef __JUCE_AFFINETRANSFORM_JUCEHEADER__
#include "gui/graphics/geometry/juce_AffineTransform.h"
#ifndef __JUCE_PATH_JUCEHEADER__
#include "gui/graphics/geometry/juce_Path.h"
#endif
#ifndef __JUCE_BORDERSIZE_JUCEHEADER__
#include "gui/graphics/geometry/juce_BorderSize.h"
@@ -335,36 +323,36 @@
#ifndef __JUCE_LINE_JUCEHEADER__
#include "gui/graphics/geometry/juce_Line.h"
#endif
#ifndef __JUCE_PATH_JUCEHEADER__
#include "gui/graphics/geometry/juce_Path.h"
#ifndef __JUCE_POINT_JUCEHEADER__
#include "gui/graphics/geometry/juce_Point.h"
#endif
#ifndef __JUCE_PATHITERATOR_JUCEHEADER__
#include "gui/graphics/geometry/juce_PathIterator.h"
#ifndef __JUCE_RECTANGLE_JUCEHEADER__
#include "gui/graphics/geometry/juce_Rectangle.h"
#endif
#ifndef __JUCE_PATHSTROKETYPE_JUCEHEADER__
#include "gui/graphics/geometry/juce_PathStrokeType.h"
#endif
#ifndef __JUCE_POINT_JUCEHEADER__
#include "gui/graphics/geometry/juce_Point.h"
#endif
#ifndef __JUCE_POSITIONEDRECTANGLE_JUCEHEADER__
#include "gui/graphics/geometry/juce_PositionedRectangle.h"
#endif
#ifndef __JUCE_RECTANGLE_JUCEHEADER__
#include "gui/graphics/geometry/juce_Rectangle.h"
#endif
#ifndef __JUCE_RECTANGLELIST_JUCEHEADER__
#include "gui/graphics/geometry/juce_RectangleList.h"
#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__
#include "gui/graphics/imaging/juce_CameraDevice.h"
#endif
#ifndef __JUCE_IMAGE_JUCEHEADER__
#include "gui/graphics/imaging/juce_Image.h"
#endif
#ifndef __JUCE_IMAGECACHE_JUCEHEADER__
#include "gui/graphics/imaging/juce_ImageCache.h"
#endif
#ifndef __JUCE_IMAGE_JUCEHEADER__
#include "gui/graphics/imaging/juce_Image.h"
#endif
#ifndef __JUCE_IMAGEFILEFORMAT_JUCEHEADER__
#include "gui/graphics/imaging/juce_ImageFileFormat.h"
#endif
@@ -380,12 +368,12 @@
#ifndef __JUCE_DRAWABLEIMAGE_JUCEHEADER__
#include "gui/graphics/drawables/juce_DrawableImage.h"
#endif
#ifndef __JUCE_DRAWABLEPATH_JUCEHEADER__
#include "gui/graphics/drawables/juce_DrawablePath.h"
#endif
#ifndef __JUCE_DRAWABLETEXT_JUCEHEADER__
#include "gui/graphics/drawables/juce_DrawableText.h"
#endif
#ifndef __JUCE_DRAWABLEPATH_JUCEHEADER__
#include "gui/graphics/drawables/juce_DrawablePath.h"
#endif
#ifndef __JUCE_COMPONENT_JUCEHEADER__
#include "gui/components/juce_Component.h"
#endif
@@ -458,12 +446,12 @@
#ifndef __JUCE_CODEEDITORCOMPONENT_JUCEHEADER__
#include "gui/components/code_editor/juce_CodeEditorComponent.h"
#endif
#ifndef __JUCE_CODEDOCUMENT_JUCEHEADER__
#include "gui/components/code_editor/juce_CodeDocument.h"
#endif
#ifndef __JUCE_CPLUSPLUSCODETOKENISER_JUCEHEADER__
#include "gui/components/code_editor/juce_CPlusPlusCodeTokeniser.h"
#endif
#ifndef __JUCE_CODEDOCUMENT_JUCEHEADER__
#include "gui/components/code_editor/juce_CodeDocument.h"
#endif
#ifndef __JUCE_CODETOKENISER_JUCEHEADER__
#include "gui/components/code_editor/juce_CodeTokeniser.h"
#endif
@@ -545,12 +533,12 @@
#ifndef __JUCE_TOOLBARITEMPALETTE_JUCEHEADER__
#include "gui/components/controls/juce_ToolbarItemPalette.h"
#endif
#ifndef __JUCE_TOOLBARITEMCOMPONENT_JUCEHEADER__
#include "gui/components/controls/juce_ToolbarItemComponent.h"
#endif
#ifndef __JUCE_TREEVIEW_JUCEHEADER__
#include "gui/components/controls/juce_TreeView.h"
#endif
#ifndef __JUCE_TOOLBARITEMCOMPONENT_JUCEHEADER__
#include "gui/components/controls/juce_ToolbarItemComponent.h"
#endif
#ifndef __JUCE_BOOLEANPROPERTYCOMPONENT_JUCEHEADER__
#include "gui/components/properties/juce_BooleanPropertyComponent.h"
#endif
@@ -560,12 +548,12 @@
#ifndef __JUCE_CHOICEPROPERTYCOMPONENT_JUCEHEADER__
#include "gui/components/properties/juce_ChoicePropertyComponent.h"
#endif
#ifndef __JUCE_PROPERTYCOMPONENT_JUCEHEADER__
#include "gui/components/properties/juce_PropertyComponent.h"
#endif
#ifndef __JUCE_PROPERTYPANEL_JUCEHEADER__
#include "gui/components/properties/juce_PropertyPanel.h"
#endif
#ifndef __JUCE_PROPERTYCOMPONENT_JUCEHEADER__
#include "gui/components/properties/juce_PropertyComponent.h"
#endif
#ifndef __JUCE_SLIDERPROPERTYCOMPONENT_JUCEHEADER__
#include "gui/components/properties/juce_SliderPropertyComponent.h"
#endif
@@ -629,33 +617,33 @@
#ifndef __JUCE_FILECHOOSER_JUCEHEADER__
#include "gui/components/filebrowser/juce_FileChooser.h"
#endif
#ifndef __JUCE_FILECHOOSERDIALOGBOX_JUCEHEADER__
#include "gui/components/filebrowser/juce_FileChooserDialogBox.h"
#endif
#ifndef __JUCE_FILEFILTER_JUCEHEADER__
#include "gui/components/filebrowser/juce_FileFilter.h"
#endif
#ifndef __JUCE_FILECHOOSERDIALOGBOX_JUCEHEADER__
#include "gui/components/filebrowser/juce_FileChooserDialogBox.h"
#endif
#ifndef __JUCE_FILELISTCOMPONENT_JUCEHEADER__
#include "gui/components/filebrowser/juce_FileListComponent.h"
#endif
#ifndef __JUCE_FILEPREVIEWCOMPONENT_JUCEHEADER__
#include "gui/components/filebrowser/juce_FilePreviewComponent.h"
#endif
#ifndef __JUCE_FILESEARCHPATHLISTCOMPONENT_JUCEHEADER__
#include "gui/components/filebrowser/juce_FileSearchPathListComponent.h"
#endif
#ifndef __JUCE_FILETREECOMPONENT_JUCEHEADER__
#include "gui/components/filebrowser/juce_FileTreeComponent.h"
#endif
#ifndef __JUCE_FILESEARCHPATHLISTCOMPONENT_JUCEHEADER__
#include "gui/components/filebrowser/juce_FileSearchPathListComponent.h"
#endif
#ifndef __JUCE_FILENAMECOMPONENT_JUCEHEADER__
#include "gui/components/filebrowser/juce_FilenameComponent.h"
#endif
#ifndef __JUCE_IMAGEPREVIEWCOMPONENT_JUCEHEADER__
#include "gui/components/filebrowser/juce_ImagePreviewComponent.h"
#endif
#ifndef __JUCE_WILDCARDFILEFILTER_JUCEHEADER__
#include "gui/components/filebrowser/juce_WildcardFileFilter.h"
#endif
#ifndef __JUCE_IMAGEPREVIEWCOMPONENT_JUCEHEADER__
#include "gui/components/filebrowser/juce_ImagePreviewComponent.h"
#endif
#ifndef __JUCE_ALERTWINDOW_JUCEHEADER__
#include "gui/components/windows/juce_AlertWindow.h"
#endif
@@ -716,12 +704,12 @@
#ifndef __JUCE_PREFERENCESPANEL_JUCEHEADER__
#include "gui/components/special/juce_PreferencesPanel.h"
#endif
#ifndef __JUCE_SYSTEMTRAYICONCOMPONENT_JUCEHEADER__
#include "gui/components/special/juce_SystemTrayIconComponent.h"
#endif
#ifndef __JUCE_WEBBROWSERCOMPONENT_JUCEHEADER__
#include "gui/components/special/juce_WebBrowserComponent.h"
#endif
#ifndef __JUCE_SYSTEMTRAYICONCOMPONENT_JUCEHEADER__
#include "gui/components/special/juce_SystemTrayIconComponent.h"
#endif
#ifndef __JUCE_QUICKTIMEMOVIECOMPONENT_JUCEHEADER__
#include "gui/components/special/juce_QuickTimeMovieComponent.h"
#endif


+ 16
- 16
src/juce_core_includes.h View File

@@ -41,8 +41,8 @@
#ifndef __JUCE_LOGGER_JUCEHEADER__
#include "core/juce_Logger.h"
#endif
#ifndef __JUCE_MATHSFUNCTIONS_JUCEHEADER__
#include "core/juce_MathsFunctions.h"
#ifndef __JUCE_PLATFORMUTILITIES_JUCEHEADER__
#include "core/juce_PlatformUtilities.h"
#endif
#ifndef __JUCE_MEMORY_JUCEHEADER__
#include "core/juce_Memory.h"
@@ -53,8 +53,8 @@
#ifndef __JUCE_PLATFORMDEFS_JUCEHEADER__
#include "core/juce_PlatformDefs.h"
#endif
#ifndef __JUCE_PLATFORMUTILITIES_JUCEHEADER__
#include "core/juce_PlatformUtilities.h"
#ifndef __JUCE_SINGLETON_JUCEHEADER__
#include "core/juce_Singleton.h"
#endif
#ifndef __JUCE_RANDOM_JUCEHEADER__
#include "core/juce_Random.h"
@@ -62,24 +62,24 @@
#ifndef __JUCE_RELATIVETIME_JUCEHEADER__
#include "core/juce_RelativeTime.h"
#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__
#include "core/juce_SystemStats.h"
#endif
#ifndef __JUCE_TARGETPLATFORM_JUCEHEADER__
#include "core/juce_TargetPlatform.h"
#endif
#ifndef __JUCE_TIME_JUCEHEADER__
#include "core/juce_Time.h"
#endif
#ifndef __JUCE_UUID_JUCEHEADER__
#include "core/juce_Uuid.h"
#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__
#include "containers/juce_Array.h"
#endif
@@ -236,14 +236,14 @@
#ifndef __JUCE_THREAD_JUCEHEADER__
#include "threads/juce_Thread.h"
#endif
#ifndef __JUCE_THREADPOOL_JUCEHEADER__
#include "threads/juce_ThreadPool.h"
#endif
#ifndef __JUCE_TIMESLICETHREAD_JUCEHEADER__
#include "threads/juce_TimeSliceThread.h"
#endif
#ifndef __JUCE_WAITABLEEVENT_JUCEHEADER__
#include "threads/juce_WaitableEvent.h"
#endif
#ifndef __JUCE_THREADPOOL_JUCEHEADER__
#include "threads/juce_ThreadPool.h"
#endif
#endif

+ 189
- 159
src/native/mac/juce_mac_CoreGraphicsContext.mm View File

@@ -73,7 +73,9 @@ class CoreGraphicsContext : public LowLevelGraphicsContext
public:
CoreGraphicsContext (CGContextRef context_, const float flipHeight_)
: context (context_),
flipHeight (flipHeight_)
flipHeight (flipHeight_),
gradientLookupTable (0),
numGradientLookupEntries (0)
{
CGContextRetain (context);
CGContextSetShouldSmoothFonts (context, true);
@@ -93,6 +95,7 @@ public:
CGColorSpaceRelease (rgbColourSpace);
CGColorSpaceRelease (greyColourSpace);
delete state;
delete gradientLookupTable;
}
//==============================================================================
@@ -103,13 +106,13 @@ public:
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();
}
bool reduceClipRegion (const RectangleList& clipRegion)
bool clipToRectangleList (const RectangleList& clipRegion)
{
const int numRects = clipRegion.getNumRectangles();
CGRect* const rects = new CGRect [numRects];
@@ -125,40 +128,44 @@ public:
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
@@ -176,11 +183,35 @@ public:
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)
{
state->colour = colour;
deleteAndZero (state->gradient);
state->fillType.setColour (colour);
CGContextSetRGBFillColor (context,
colour.getFloatRed(), colour.getFloatGreen(),
@@ -190,15 +221,17 @@ public:
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)
{
setColour (state->colour.withAlpha (opacity));
state->fillType.colour = state->fillType.colour.withAlpha (opacity);
}
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 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
CGContextClearRect (context, CGRectMake (x, y, w, h));
CGContextClearRect (context, cgRect);
#else
#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)
CGContextClearRect (context, CGRectMake (x, y, w, h));
CGContextClearRect (context, cgRect);
else
#endif
CGContextSetBlendMode (context, kCGBlendModeCopy);
#endif
fillRect (x, y, w, h, false);
fillRect (r, false);
CGContextSetBlendMode (context, kCGBlendModeNormal);
}
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);
CGContextClipToRect (context, CGRectMake (x, flipHeight - (y + h), w, h));
CGContextClipToRect (context, cgRect);
flip();
drawGradient();
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);
if (state->gradient == 0)
if (state->fillType.isColour())
{
flip();
applyTransform (transform);
@@ -259,102 +302,78 @@ public:
else
CGContextEOFillPath (context);
}
else
else if (state->fillType.isGradient())
{
createPath (path, transform);
CGContextClip (context);
flip();
applyTransform (state->gradient->transform);
applyTransform (state->fillType.gradient->transform);
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);
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);
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);
CGContextRestoreGState (context);
@@ -366,8 +385,8 @@ public:
CGContextSetLineCap (context, kCGLineCapSquare);
CGContextSetLineWidth (context, 1.0f);
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) },
{ 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)
{
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
{
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
{
SavedState() throw()
: gradient (0), font (1.0f), fontRef (0),
fontTransform (CGAffineTransformIdentity)
: font (1.0f), fontRef (0), fontTransform (CGAffineTransformIdentity)
{
}
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)
{
}
~SavedState() throw()
{
delete gradient;
}
Colour colour;
ColourGradient* gradient;
Graphics::FillType fillType;
Font font;
CGFontRef fontRef;
CGAffineTransform fontTransform;
@@ -480,21 +500,31 @@ private:
SavedState* state;
OwnedArray <SavedState> stateStack;
PixelARGB* gradientLookupTable;
int numGradientLookupEntries;
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;
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));
if (gradient->isRadial)
@@ -514,12 +544,12 @@ private:
return result;
}
void drawGradient() const throw()
void drawGradient() throw()
{
CGContextSetAlpha (context, 1.0f);
CGContextSetInterpolationQuality (context, kCGInterpolationDefault); // (This is required for 10.4, where there's a crash if
// you draw a gradient with high quality interp enabled).
CGShadingRef shading = createGradient (state->gradient);
CGShadingRef shading = createGradient (state->fillType.gradient);
CGContextDrawShading (context, shading);
CGShadingRelease (shading);
}


+ 1
- 1
src/native/mac/juce_mac_MessageManager.mm View File

@@ -409,7 +409,7 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor)
if (e != 0 && ! isEventBlockedByModalComps (e))
[NSApp sendEvent: e];
if (Time::getMillisecondCounter() >= endTime)
break;
}


+ 1
- 1
src/native/mac/juce_mac_NSViewComponentPeer.mm View File

@@ -1471,7 +1471,7 @@ void NSViewComponentPeer::drawRect (NSRect r)
roundFloatToInt (rects[i].size.height)));
}
if (context.reduceClipRegion (clip))
if (context.clipToRectangleList (clip))
{
insideDrawRect = true;
handlePaint (context);


+ 1
- 1
src/native/mac/juce_mac_NativeIncludes.h View File

@@ -35,7 +35,7 @@
#include "../../core/juce_StandardHeader.h"
#define USE_COREGRAPHICS_RENDERING 0
#define USE_COREGRAPHICS_RENDERING 1
#if JUCE_IPHONE
#import <Foundation/Foundation.h>


+ 1
- 1
src/native/windows/juce_win32_Windowing.cpp View File

@@ -1253,7 +1253,7 @@ private:
updateCurrentModifiers();
LowLevelGraphicsSoftwareRenderer context (*offscreenImage);
context.reduceClipRegion (contextClip);
context.clipToRectangleList (contextClip);
context.setOrigin (-x, -y);
handlePaint (context);


Loading…
Cancel
Save