From cd885710816fb51699937251165ee6e833cf0bc0 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Thu, 5 Nov 2009 17:59:44 +0000 Subject: [PATCH] Added methods Graphics::setTiledImageFill and Graphics::setGradientFill - these are now the preferred way to specify a fill type, rather than using the Brush classes (which will probably disappear at some point in the future). Also refactored and renamed some DrawablePath methods, which might require a few tweaks to your code if you use this class. --- .../src/demos/PathsAndTransformsDemo.cpp | 9 +- extras/juce demo/src/demos/WidgetsDemo.cpp | 17 +- .../paintelements/jucer_PaintElementImage.h | 5 +- .../src/ui/jucer_SnapGridPainter.cpp | 3 +- juce_amalgamated.cpp | 683 +++++++++--------- juce_amalgamated.h | 328 +++++---- .../code_editor/juce_CodeEditorComponent.cpp | 52 +- .../controls/juce_TableHeaderComponent.cpp | 1 - .../juce_FileSearchPathListComponent.cpp | 4 +- .../lookandfeel/juce_LookAndFeel.cpp | 178 ++--- .../lookandfeel/juce_OldSchoolLookAndFeel.cpp | 5 +- .../components/special/juce_DropShadower.cpp | 6 +- .../special/juce_MidiKeyboardComponent.cpp | 6 +- .../components/special/juce_OpenGLComponent.h | 5 +- src/gui/graphics/colour/juce_ColourGradient.h | 4 +- src/gui/graphics/contexts/juce_Graphics.cpp | 20 +- src/gui/graphics/contexts/juce_Graphics.h | 14 + .../graphics/drawables/juce_DrawablePath.cpp | 287 ++++---- .../graphics/drawables/juce_DrawablePath.h | 54 +- src/gui/graphics/drawables/juce_SVGParser.cpp | 134 ++-- src/gui/graphics/imaging/juce_Image.cpp | 1 - src/native/mac/juce_iphone_Audio.cpp | 2 +- 22 files changed, 877 insertions(+), 941 deletions(-) diff --git a/extras/juce demo/src/demos/PathsAndTransformsDemo.cpp b/extras/juce demo/src/demos/PathsAndTransformsDemo.cpp index 9c48c05df0..8dee944d99 100644 --- a/extras/juce demo/src/demos/PathsAndTransformsDemo.cpp +++ b/extras/juce demo/src/demos/PathsAndTransformsDemo.cpp @@ -303,12 +303,11 @@ private: DrawablePath dp; dp.setPath (shape); - dp.setOutline (4.0f, Colours::blue); + dp.setStrokeThickness (4.0f); + dp.setStrokeColour (Colours::blue); - GradientBrush gb (ColourGradient (Colours::red.withAlpha (0.4f), -100.0f, -100.0f, - Colours::green.withAlpha (0.6f), 100.0f, 100.0f, false)); - - dp.setFillBrush (gb); + dp.setFillGradient (ColourGradient (Colours::red.withAlpha (0.4f), -100.0f, -100.0f, + Colours::green.withAlpha (0.6f), 100.0f, 100.0f, false)); dc->insertDrawable (dp); diff --git a/extras/juce demo/src/demos/WidgetsDemo.cpp b/extras/juce demo/src/demos/WidgetsDemo.cpp index 92278410d2..a3fe1c835c 100644 --- a/extras/juce demo/src/demos/WidgetsDemo.cpp +++ b/extras/juce demo/src/demos/WidgetsDemo.cpp @@ -422,12 +422,14 @@ static Component* createRadioButtonPage() Path p; p.addStar (0.0f, 0.0f, i + 5, 20.0f, 50.0f, -0.2f); normal.setPath (p); - normal.setSolidFill (Colours::lightblue); - normal.setOutline (4.0f, Colours::black); + normal.setFillColour (Colours::lightblue); + normal.setStrokeColour (Colours::black); + normal.setStrokeThickness (4.0f); over.setPath (p); - over.setSolidFill (Colours::blue); - over.setOutline (4.0f, Colours::black); + over.setFillColour (Colours::blue); + over.setStrokeColour (Colours::black); + over.setStrokeThickness (4.0f); DrawableButton* db = new DrawableButton (String (i + 5) + T(" points"), DrawableButton::ImageAboveTextLabel); db->setImages (&normal, &over, 0); @@ -478,13 +480,14 @@ public: Path p; p.addStar (0.0f, 0.0f, 5, 20.0f, 50.0f, 0.2f); normal.setPath (p); - normal.setSolidFill (Colours::red); + normal.setFillColour (Colours::red); p.clear(); p.addStar (0.0f, 0.0f, 7, 30.0f, 50.0f, 0.0f); over.setPath (p); - over.setSolidFill (Colours::pink); - over.setOutline (5.0f, Colours::black); + over.setFillColour (Colours::pink); + over.setStrokeColour (Colours::black); + over.setStrokeThickness (5.0f); DrawableImage down; down.setImage (ImageCache::getFromMemory (BinaryData::juce_png, BinaryData::juce_pngSize), true); diff --git a/extras/the jucer/src/model/paintelements/jucer_PaintElementImage.h b/extras/the jucer/src/model/paintelements/jucer_PaintElementImage.h index 037684e39f..5a1d363a75 100644 --- a/extras/the jucer/src/model/paintelements/jucer_PaintElementImage.h +++ b/extras/the jucer/src/model/paintelements/jucer_PaintElementImage.h @@ -76,12 +76,11 @@ public: if (image != 0) { - g.setColour (Colours::black.withAlpha ((float) opacity)); - image->drawWithin (g, r.getX(), r.getY(), r.getWidth(), r.getHeight(), mode == stretched ? RectanglePlacement::stretchToFit : (mode == proportionalReducingOnly ? (RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize) - : RectanglePlacement::centred)); + : RectanglePlacement::centred), + (float) opacity); } else { diff --git a/extras/the jucer/src/ui/jucer_SnapGridPainter.cpp b/extras/the jucer/src/ui/jucer_SnapGridPainter.cpp index bbbfd3f6c3..c50574d7bd 100644 --- a/extras/the jucer/src/ui/jucer_SnapGridPainter.cpp +++ b/extras/the jucer/src/ui/jucer_SnapGridPainter.cpp @@ -85,8 +85,7 @@ void SnapGridPainter::draw (Graphics& g, PaintRoutine* backgroundGraphics) if (backgroundFill != 0) { - ImageBrush ib (backgroundFill, 0, 0, 1.0f); - g.setBrush (&ib); + g.setTiledImageFill (*backgroundFill, 0, 0, 1.0f); g.fillAll(); } } diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 2dbf719e40..f56f69492b 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -44272,18 +44272,15 @@ public: return true; } - void draw (Graphics& g, const Font& font, + void draw (CodeEditorComponent& owner, Graphics& g, const Font& font, float x, const int y, const int baselineOffset, const int lineHeight, - const Array & coloursForTokenCategories, - const Colour& defaultColour, - const Colour& highlightColour, - const float charWidth) const throw() + const Colour& highlightColour) const throw() { if (highlightColumnStart < highlightColumnEnd) { g.setColour (highlightColour); - g.fillRect (roundFloatToInt (x + highlightColumnStart * charWidth), y, - roundFloatToInt ((highlightColumnEnd - highlightColumnStart) * charWidth), lineHeight); + g.fillRect (roundFloatToInt (x + highlightColumnStart * owner.getCharWidth()), y, + roundFloatToInt ((highlightColumnEnd - highlightColumnStart) * owner.getCharWidth()), lineHeight); } int lastType = INT_MIN; @@ -44295,11 +44292,7 @@ public: if (lastType != token->tokenType) { lastType = token->tokenType; - - if (((unsigned int) lastType) < (unsigned int) coloursForTokenCategories.size()) - g.setColour (coloursForTokenCategories [lastType]); - else - g.setColour (defaultColour); + g.setColour (owner.getColourForTokenType (lastType)); } g.drawSingleLineText (token->text, roundFloatToInt (x), y + baselineOffset); @@ -44518,12 +44511,17 @@ void CodeEditorComponent::paint (Graphics& g) const Colour defaultColour (findColour (CodeEditorComponent::defaultTextColourId)); const Colour highlightColour (findColour (CodeEditorComponent::highlightColourId)); - for (int j = 0; j < lines.size(); ++j) - lines.getUnchecked(j)->draw (g, font, + const Rectangle clip (g.getClipBounds()); + const int firstLineToDraw = jmax (0, clip.getY() / lineHeight); + const int lastLineToDraw = jmin (lines.size(), clip.getBottom() / lineHeight + 1); + + for (int j = firstLineToDraw; j < lastLineToDraw; ++j) + { + lines.getUnchecked(j)->draw (*this, g, font, (float) (gutter - xOffset * charWidth), lineHeight * j, baselineOffset, lineHeight, - coloursForTokenCategories, defaultColour, - highlightColour, charWidth); + highlightColour); + } } void CodeEditorComponent::handleAsyncUpdate() @@ -44534,8 +44532,12 @@ void CodeEditorComponent::handleAsyncUpdate() void CodeEditorComponent::rebuildLineTokens() { cancelPendingUpdate(); + const int numNeeded = linesOnScreen + 1; + int minLineToRepaint = numNeeded; + int maxLineToRepaint = 0; + if (numNeeded != lines.size()) { lines.clear(); @@ -44543,7 +44545,8 @@ void CodeEditorComponent::rebuildLineTokens() for (int i = numNeeded; --i >= 0;) lines.add (new CodeEditorLine()); - repaint(); + minLineToRepaint = 0; + maxLineToRepaint = numNeeded; } jassert (numNeeded == lines.size()); @@ -44555,8 +44558,19 @@ void CodeEditorComponent::rebuildLineTokens() { CodeEditorLine* const line = lines.getUnchecked(i); - if (line->update (document, firstLineOnScreen + i, source, codeTokeniser, spacesPerTab, selectionStart, selectionEnd)) - repaint (0, lineHeight * i, getWidth(), lineHeight); + if (line->update (document, firstLineOnScreen + i, source, codeTokeniser, spacesPerTab, + selectionStart, selectionEnd)) + { + minLineToRepaint = jmin (minLineToRepaint, i); + maxLineToRepaint = jmax (maxLineToRepaint, i); + } + } + + if (minLineToRepaint <= maxLineToRepaint) + { + repaint (gutter, lineHeight * minLineToRepaint - 1, + verticalScrollBar->getX() - gutter, + lineHeight * (1 + maxLineToRepaint - minLineToRepaint) + 2); } } @@ -57534,7 +57548,7 @@ FileSearchPathListComponent::FileSearchPathListComponent() Path arrowPath; arrowPath.addArrow (50.0f, 100.0f, 50.0f, 0.0, 40.0f, 100.0f, 50.0f); DrawablePath arrowImage; - arrowImage.setSolidFill (Colours::black.withAlpha (0.4f)); + arrowImage.setFillColour (Colours::black.withAlpha (0.4f)); arrowImage.setPath (arrowPath); ((DrawableButton*) upButton)->setImages (&arrowImage); @@ -57547,7 +57561,7 @@ FileSearchPathListComponent::FileSearchPathListComponent() Path arrowPath; arrowPath.addArrow (50.0f, 0.0f, 50.0f, 100.0f, 40.0f, 100.0f, 50.0f); DrawablePath arrowImage; - arrowImage.setSolidFill (Colours::black.withAlpha (0.4f)); + arrowImage.setFillColour (Colours::black.withAlpha (0.4f)); arrowImage.setPath (arrowPath); ((DrawableButton*) downButton)->setImages (&arrowImage); @@ -63576,9 +63590,7 @@ void LookAndFeel::drawProgressBar (Graphics& g, ProgressBar& progressBar, true, true, true, true); } - ImageBrush ib (&im, 0, 0, 0.85f); - g.setBrush (&ib); - + g.setTiledImageFill (im, 0, 0, 0.85f); g.fillPath (p); } @@ -63711,12 +63723,8 @@ void LookAndFeel::drawScrollbar (Graphics& g, const Colour thumbColour (scrollbar.findColour (ScrollBar::thumbColourId)); - GradientBrush gb (thumbColour.overlaidWith (Colour (0x44000000)), - gx1, gy1, - thumbColour.overlaidWith (Colour (0x19000000)), - gx2, gy2, false); - - g.setBrush (&gb); + g.setGradientFill (ColourGradient (thumbColour.overlaidWith (Colour (0x44000000)), gx1, gy1, + thumbColour.overlaidWith (Colour (0x19000000)), gx2, gy2, false)); g.fillPath (slotPath); if (isScrollbarVertical) @@ -63730,24 +63738,17 @@ void LookAndFeel::drawScrollbar (Graphics& g, gy2 = (float) y + height; } - GradientBrush gb2 (Colours::transparentBlack, - gx1, gy1, - Colour (0x19000000), - gx2, gy2, false); - - g.setBrush (&gb2); + g.setGradientFill (ColourGradient (Colours::transparentBlack,gx1, gy1, + Colour (0x19000000), gx2, gy2, false)); g.fillPath (slotPath); g.setColour (thumbColour); g.fillPath (thumbPath); - GradientBrush gb3 (Colour (0x10000000), - gx1, gy1, - Colours::transparentBlack, - gx2, gy2, false); + g.setGradientFill (ColourGradient (Colour (0x10000000), gx1, gy1, + Colours::transparentBlack, gx2, gy2, false)); g.saveState(); - g.setBrush (&gb3); if (isScrollbarVertical) g.reduceClipRegion (x + width / 2, y, width, height); @@ -63927,13 +63928,11 @@ void LookAndFeel::drawPopupMenuUpDownArrow (Graphics& g, { const Colour background (findColour (PopupMenu::backgroundColourId)); - GradientBrush gb (background, - 0.0f, height * 0.5f, - background.withAlpha (0.0f), - 0.0f, isScrollUpArrow ? ((float) height) : 0.0f, - false); + g.setGradientFill (ColourGradient (background, 0.0f, height * 0.5f, + background.withAlpha (0.0f), + 0.0f, isScrollUpArrow ? ((float) height) : 0.0f, + false)); - g.setBrush (&gb); g.fillRect (1, 1, width - 2, height - 2); const float hw = width * 0.5f; @@ -64276,9 +64275,8 @@ void LookAndFeel::drawLinearSliderBackground (Graphics& g, const float iy = y + height * 0.5f - sliderRadius * 0.5f; const float ih = sliderRadius; - GradientBrush gb (gradCol1, 0.0f, iy, - gradCol2, 0.0f, iy + ih, false); - g.setBrush (&gb); + g.setGradientFill (ColourGradient (gradCol1, 0.0f, iy, + gradCol2, 0.0f, iy + ih, false)); indent.addRoundedRectangle (x - sliderRadius * 0.5f, iy, width + sliderRadius, ih, @@ -64290,9 +64288,8 @@ void LookAndFeel::drawLinearSliderBackground (Graphics& g, const float ix = x + width * 0.5f - sliderRadius * 0.5f; const float iw = sliderRadius; - GradientBrush gb (gradCol1, ix, 0.0f, - gradCol2, ix + iw, 0.0f, false); - g.setBrush (&gb); + g.setGradientFill (ColourGradient (gradCol1, ix, 0.0f, + gradCol2, ix + iw, 0.0f, false)); indent.addRoundedRectangle (ix, y - sliderRadius * 0.5f, iw, height + sliderRadius, @@ -64689,11 +64686,10 @@ void LookAndFeel::drawDocumentWindowTitleBar (DocumentWindow& window, { const bool isActive = window.isActiveWindow(); - GradientBrush gb (window.getBackgroundColour(), - 0.0f, 0.0f, - window.getBackgroundColour().contrasting (isActive ? 0.15f : 0.05f), - 0.0f, (float) h, false); - g.setBrush (&gb); + g.setGradientFill (ColourGradient (window.getBackgroundColour(), + 0.0f, 0.0f, + window.getBackgroundColour().contrasting (isActive ? 0.15f : 0.05f), + 0.0f, (float) h, false)); g.fillAll(); Font font (h * 0.65f, Font::bold); @@ -64775,10 +64771,8 @@ public: y += diam * 0.05f; diam *= 0.9f; - GradientBrush gb1 (Colour::greyLevel (0.9f).withAlpha (alpha), 0, y + diam, - Colour::greyLevel (0.6f).withAlpha (alpha), 0, y, false); - - g.setBrush (&gb1); + g.setGradientFill (ColourGradient (Colour::greyLevel (0.9f).withAlpha (alpha), 0, y + diam, + Colour::greyLevel (0.6f).withAlpha (alpha), 0, y, false)); g.fillEllipse (x, y, diam, diam); x += 2.0f; @@ -64907,11 +64901,10 @@ void LookAndFeel::drawStretchableLayoutResizerBar (Graphics& g, const float cy = h * 0.5f; const float cr = jmin (w, h) * 0.4f; - GradientBrush gb (Colours::white.withAlpha (alpha), cx + cr * 0.1f, cy + cr, - Colours::black.withAlpha (alpha), cx, cy - cr * 4.0f, - true); + g.setGradientFill (ColourGradient (Colours::white.withAlpha (alpha), cx + cr * 0.1f, cy + cr, + Colours::black.withAlpha (alpha), cx, cy - cr * 4.0f, + true)); - g.setBrush (&gb); g.fillEllipse (cx - cr, cy - cr, cr * 2.0f, cr * 2.0f); } @@ -65229,11 +65222,9 @@ void LookAndFeel::drawTabAreaBehindFrontButton (Graphics& g, shadowRect.setBounds (0, (int) y2, w, h - (int) y2); } - GradientBrush gb (Colours::black.withAlpha (tabBar.isEnabled() ? 0.3f : 0.15f), x1, y1, - Colours::transparentBlack, x2, y2, - false); + g.setGradientFill (ColourGradient (Colours::black.withAlpha (tabBar.isEnabled() ? 0.3f : 0.15f), x1, y1, + Colours::transparentBlack, x2, y2, false)); - g.setBrush (&gb); shadowRect.expand (2, 2); g.fillRect (shadowRect); @@ -65267,7 +65258,7 @@ Button* LookAndFeel::createTabBarExtrasButton() DrawablePath ellipse; ellipse.setPath (p); - ellipse.setSolidFill (Colour (0x99ffffff)); + ellipse.setFillColour (Colour (0x99ffffff)); p.clear(); p.addEllipse (0.0f, 0.0f, 100.0f, 100.0f); @@ -65278,13 +65269,13 @@ Button* LookAndFeel::createTabBarExtrasButton() DrawablePath dp; dp.setPath (p); - dp.setSolidFill (Colour (0x59000000)); + dp.setFillColour (Colour (0x59000000)); DrawableComposite normalImage; normalImage.insertDrawable (ellipse); normalImage.insertDrawable (dp); - dp.setSolidFill (Colour (0xcc000000)); + dp.setFillColour (Colour (0xcc000000)); DrawableComposite overImage; overImage.insertDrawable (ellipse); @@ -65302,11 +65293,9 @@ void LookAndFeel::drawTableHeaderBackground (Graphics& g, TableHeaderComponent& const int w = header.getWidth(); const int h = header.getHeight(); - GradientBrush gb (Colour (0xffe8ebf9), 0.0f, h * 0.5f, - Colour (0xfff6f8f9), 0.0f, h - 1.0f, - false); - - g.setBrush (&gb); + g.setGradientFill (ColourGradient (Colour (0xffe8ebf9), 0.0f, h * 0.5f, + Colour (0xfff6f8f9), 0.0f, h - 1.0f, + false)); g.fillRect (0, h / 2, w, h); g.setColour (Colour (0x33000000)); @@ -65354,13 +65343,11 @@ void LookAndFeel::paintToolbarBackground (Graphics& g, int w, int h, Toolbar& to { const Colour background (toolbar.findColour (Toolbar::backgroundColourId)); - GradientBrush gb (background, 0.0f, 0.0f, - background.darker (0.1f), - toolbar.isVertical() ? w - 1.0f : 0.0f, - toolbar.isVertical() ? 0.0f : h - 1.0f, - false); - - g.setBrush (&gb); + g.setGradientFill (ColourGradient (background, 0.0f, 0.0f, + background.darker (0.1f), + toolbar.isVertical() ? w - 1.0f : 0.0f, + toolbar.isVertical() ? 0.0f : h - 1.0f, + false)); g.fillAll(); } @@ -65529,7 +65516,7 @@ Button* LookAndFeel::createFileBrowserGoUpButton() arrowPath.addArrow (50.0f, 100.0f, 50.0f, 0.0, 40.0f, 100.0f, 50.0f); DrawablePath arrowImage; - arrowImage.setSolidFill (Colours::black.withAlpha (0.4f)); + arrowImage.setFillColour (Colours::black.withAlpha (0.4f)); arrowImage.setPath (arrowPath); goUpButton->setImages (&arrowImage); @@ -65760,8 +65747,7 @@ void LookAndFeel::drawShinyButtonShape (Graphics& g, cg.addColour (0.5, baseColour.overlaidWith (Colour (0x33ffffff))); cg.addColour (0.51, baseColour.overlaidWith (Colour (0x110000ff))); - GradientBrush gb (cg); - g.setBrush (&gb); + g.setGradientFill (cg); g.fillPath (outline); g.setColour (Colour (0x80000000)); @@ -65786,32 +65772,24 @@ void LookAndFeel::drawGlassSphere (Graphics& g, cg.addColour (0.4, Colours::white.overlaidWith (colour)); - GradientBrush gb (cg); - g.setBrush (&gb); + g.setGradientFill (cg); g.fillPath (p); } - { - GradientBrush gb (Colours::white, 0, y + diameter * 0.06f, - Colours::transparentWhite, 0, y + diameter * 0.3f, false); + g.setGradientFill (ColourGradient (Colours::white, 0, y + diameter * 0.06f, + Colours::transparentWhite, 0, y + diameter * 0.3f, false)); + g.fillEllipse (x + diameter * 0.2f, y + diameter * 0.05f, diameter * 0.6f, diameter * 0.4f); - g.setBrush (&gb); - g.fillEllipse (x + diameter * 0.2f, y + diameter * 0.05f, diameter * 0.6f, diameter * 0.4f); - } + ColourGradient cg (Colours::transparentBlack, + x + diameter * 0.5f, y + diameter * 0.5f, + Colours::black.withAlpha (0.5f * outlineThickness * colour.getFloatAlpha()), + x, y + diameter * 0.5f, true); - { - ColourGradient cg (Colours::transparentBlack, - x + diameter * 0.5f, y + diameter * 0.5f, - Colours::black.withAlpha (0.5f * outlineThickness * colour.getFloatAlpha()), - x, y + diameter * 0.5f, true); + cg.addColour (0.7, Colours::transparentBlack); + cg.addColour (0.8, Colours::black.withAlpha (0.1f * outlineThickness)); - cg.addColour (0.7, Colours::transparentBlack); - cg.addColour (0.8, Colours::black.withAlpha (0.1f * outlineThickness)); - - GradientBrush gb (cg); - g.setBrush (&gb); - g.fillPath (p); - } + g.setGradientFill (cg); + g.fillPath (p); g.setColour (Colours::black.withAlpha (0.5f * colour.getFloatAlpha())); g.drawEllipse (x, y, diameter, diameter, outlineThickness); @@ -65842,24 +65820,20 @@ void LookAndFeel::drawGlassPointer (Graphics& g, cg.addColour (0.4, Colours::white.overlaidWith (colour)); - GradientBrush gb (cg); - g.setBrush (&gb); + g.setGradientFill (cg); g.fillPath (p); } - { - ColourGradient cg (Colours::transparentBlack, - x + diameter * 0.5f, y + diameter * 0.5f, - Colours::black.withAlpha (0.5f * outlineThickness * colour.getFloatAlpha()), - x - diameter * 0.2f, y + diameter * 0.5f, true); + ColourGradient cg (Colours::transparentBlack, + x + diameter * 0.5f, y + diameter * 0.5f, + Colours::black.withAlpha (0.5f * outlineThickness * colour.getFloatAlpha()), + x - diameter * 0.2f, y + diameter * 0.5f, true); - cg.addColour (0.5, Colours::transparentBlack); - cg.addColour (0.7, Colours::black.withAlpha (0.07f * outlineThickness)); + cg.addColour (0.5, Colours::transparentBlack); + cg.addColour (0.7, Colours::black.withAlpha (0.07f * outlineThickness)); - GradientBrush gb (cg); - g.setBrush (&gb); - g.fillPath (p); - } + g.setGradientFill (cg); + g.fillPath (p); g.setColour (Colours::black.withAlpha (0.5f * colour.getFloatAlpha())); g.strokePath (p, PathStrokeType (outlineThickness)); @@ -65903,8 +65877,7 @@ void LookAndFeel::drawGlassLozenge (Graphics& g, cg.addColour (0.4, colour); cg.addColour (0.97, colour.withMultipliedAlpha (0.3f)); - GradientBrush gb (cg); - g.setBrush (&gb); + g.setGradientFill (cg); g.fillPath (outline); } @@ -65916,10 +65889,8 @@ void LookAndFeel::drawGlassLozenge (Graphics& g, if (! (flatOnLeft || flatOnTop || flatOnBottom)) { - GradientBrush gb (cg); - g.saveState(); - g.setBrush (&gb); + g.setGradientFill (cg); g.reduceClipRegion (intX, intY, intEdge, intH); g.fillPath (outline); g.restoreState(); @@ -65929,10 +65900,9 @@ void LookAndFeel::drawGlassLozenge (Graphics& g, { cg.x1 = x + width - edgeBlurRadius; cg.x2 = x + width; - GradientBrush gb (cg); g.saveState(); - g.setBrush (&gb); + g.setGradientFill (cg); g.reduceClipRegion (intX + intW - intEdge, intY, 2 + intEdge, intH); g.fillPath (outline); g.restoreState(); @@ -65953,10 +65923,8 @@ void LookAndFeel::drawGlassLozenge (Graphics& g, ! (flatOnLeft || flatOnBottom), ! (flatOnRight || flatOnBottom)); - GradientBrush gb (colour.brighter (10.0f), 0, y + height * 0.06f, - Colours::transparentWhite, 0, y + height * 0.4f, false); - - g.setBrush (&gb); + g.setGradientFill (ColourGradient (colour.brighter (10.0f), 0, y + height * 0.06f, + Colours::transparentWhite, 0, y + height * 0.4f, false)); g.fillPath (highlight); } @@ -66473,7 +66441,7 @@ Button* OldSchoolLookAndFeel::createDocumentWindowButton (int buttonType) DrawableButton* b = new DrawableButton ("minimise", DrawableButton::ImageFitted); DrawablePath dp; dp.setPath (shape); - dp.setSolidFill (Colours::black.withAlpha (0.3f)); + dp.setFillColour (Colours::black.withAlpha (0.3f)); b->setImages (&dp); return b; } @@ -66485,7 +66453,7 @@ Button* OldSchoolLookAndFeel::createDocumentWindowButton (int buttonType) DrawableButton* b = new DrawableButton ("maximise", DrawableButton::ImageFitted); DrawablePath dp; dp.setPath (shape); - dp.setSolidFill (Colours::black.withAlpha (0.3f)); + dp.setFillColour (Colours::black.withAlpha (0.3f)); b->setImages (&dp); return b; } @@ -72570,7 +72538,6 @@ public: Image* const topLeft = shadowImageSections [type * 3]; Image* const bottomRight = shadowImageSections [type * 3 + 1]; Image* const filler = shadowImageSections [type * 3 + 2]; - ImageBrush fillBrush (filler, 0, 0, 1.0f); g.setOpacity (1.0f); @@ -72586,7 +72553,7 @@ public: 0, getHeight() - imH, bottomRight->getWidth(), imH, 0, bottomRight->getHeight() - imH, bottomRight->getWidth(), imH); - g.setBrush (&fillBrush); + g.setTiledImageFill (*filler, 0, 0, 1.0f); g.fillRect (0, topLeft->getHeight(), getWidth(), getHeight() - (topLeft->getHeight() + bottomRight->getHeight())); } else @@ -72601,7 +72568,7 @@ public: getWidth() - imW, 0, imW, bottomRight->getHeight(), bottomRight->getWidth() - imW, 0, imW, bottomRight->getHeight()); - g.setBrush (&fillBrush); + g.setTiledImageFill (*filler, 0, 0, 1.0f); g.fillRect (topLeft->getWidth(), 0, getWidth() - (topLeft->getWidth() + bottomRight->getWidth()), getHeight()); } } @@ -73509,9 +73476,8 @@ void MidiKeyboardComponent::paint (Graphics& g) else y2 = 5.0f; - GradientBrush gb (Colours::black.withAlpha (0.3f), x1, y1, - Colours::transparentBlack, x2, y2, false); - g.setBrush (&gb); + g.setGradientFill (ColourGradient (Colours::black.withAlpha (0.3f), x1, y1, + Colours::transparentBlack, x2, y2, false)); getKeyPos (rangeEnd, x, w); x += w; @@ -79191,6 +79157,23 @@ void Graphics::setBrush (const Brush* const newBrush) throw() state->brush = 0; } +void Graphics::setGradientFill (const ColourGradient& gradient) throw() +{ + saveStateIfPending(); + delete state->brush; + state->brush = new GradientBrush (gradient); +} + +void Graphics::setTiledImageFill (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() : colour (Colours::black), brush (0), @@ -83563,75 +83546,91 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE DrawablePath::DrawablePath() - : fillBrush (new SolidColourBrush (Colours::black)), - strokeBrush (0), + : fillColour (0xff000000), + fillGradient (0), + strokeGradient (0), strokeType (0.0f) { } DrawablePath::~DrawablePath() { - delete fillBrush; - delete strokeBrush; + delete fillGradient; + delete strokeGradient; } -void DrawablePath::setPath (const Path& newPath) +void DrawablePath::setPath (const Path& newPath) throw() { path = newPath; updateOutline(); } -void DrawablePath::setSolidFill (const Colour& newColour) +void DrawablePath::setFillColour (const Colour& newColour) throw() { - delete fillBrush; - fillBrush = new SolidColourBrush (newColour); + deleteAndZero (fillGradient); + fillColour = newColour; } -void DrawablePath::setFillBrush (const Brush& newBrush) +void DrawablePath::setFillGradient (const ColourGradient& gradient) throw() { - delete fillBrush; - fillBrush = newBrush.createCopy(); + delete fillGradient; + fillGradient = new ColourGradient (gradient); } -void DrawablePath::setOutline (const float thickness, const Colour& colour) +void DrawablePath::setStrokeType (const PathStrokeType& newStrokeType) throw() { - strokeType = PathStrokeType (thickness); - delete strokeBrush; - strokeBrush = new SolidColourBrush (colour); + strokeType = newStrokeType; updateOutline(); } -void DrawablePath::setOutline (const PathStrokeType& strokeType_, const Brush& newStrokeBrush) +void DrawablePath::setStrokeThickness (const float newThickness) throw() { - strokeType = strokeType_; - delete strokeBrush; - strokeBrush = newStrokeBrush.createCopy(); - updateOutline(); + setStrokeType (PathStrokeType (newThickness, strokeType.getJointStyle(), strokeType.getEndStyle())); +} + +void DrawablePath::setStrokeColour (const Colour& newStrokeColour) throw() +{ + deleteAndZero (strokeGradient); + strokeColour = newStrokeColour; +} + +void DrawablePath::setStrokeGradient (const ColourGradient& newStrokeGradient) throw() +{ + delete strokeGradient; + strokeGradient = new ColourGradient (newStrokeGradient); } void DrawablePath::render (const Drawable::RenderingContext& context) const { + if (fillGradient != 0) { - Brush* const tempBrush = fillBrush->createCopy(); - tempBrush->applyTransform (context.transform); - tempBrush->multiplyOpacity (context.opacity); - - context.g.setBrush (tempBrush); - context.g.fillPath (path, context.transform); - - delete tempBrush; + ColourGradient cg (*fillGradient); + cg.transform = cg.transform.followedBy (context.transform); + cg.multiplyOpacity (context.opacity); + context.g.setGradientFill (cg); + } + else + { + context.g.setColour (fillColour); } - if (strokeBrush != 0 && strokeType.getStrokeThickness() > 0.0f) + context.g.fillPath (path, context.transform); + + if (strokeType.getStrokeThickness() > 0.0f) { - Brush* const tempBrush = strokeBrush->createCopy(); - tempBrush->applyTransform (context.transform); - tempBrush->multiplyOpacity (context.opacity); + if (strokeGradient != 0) + { + ColourGradient cg (*strokeGradient); + cg.transform = cg.transform.followedBy (context.transform); + cg.multiplyOpacity (context.opacity); + context.g.setGradientFill (cg); + } + else + { + context.g.setColour (strokeColour); + } - context.g.setBrush (tempBrush); context.g.fillPath (outline, context.transform); - - delete tempBrush; } } @@ -83660,187 +83659,148 @@ Drawable* DrawablePath::createCopy() const DrawablePath* const dp = new DrawablePath(); dp->path = path; - dp->setFillBrush (*fillBrush); - - if (strokeBrush != 0) - dp->setOutline (strokeType, *strokeBrush); - + dp->outline = outline; + dp->fillColour = fillColour; + dp->strokeColour = strokeColour; + dp->fillGradient = (fillGradient != 0) ? new ColourGradient (*fillGradient) : 0; + dp->strokeGradient = (strokeGradient != 0) ? new ColourGradient (*strokeGradient) : 0; + dp->strokeType = strokeType; return dp; } -static Brush* readBrushFromBinary (InputStream& input) +static const Colour readColourFromBinary (InputStream& input, ColourGradient*& gradient) { + deleteAndZero (gradient); + switch (input.readByte()) { case 1: - return new SolidColourBrush (Colour ((uint32) input.readInt())); + return Colour ((uint32) input.readInt()); case 2: { - ColourGradient gradient; - gradient.x1 = input.readFloat(); - gradient.y1 = input.readFloat(); - gradient.x2 = input.readFloat(); - gradient.y2 = input.readFloat(); - gradient.isRadial = input.readByte() != 0; + gradient = new ColourGradient(); + gradient->x1 = input.readFloat(); + gradient->y1 = input.readFloat(); + gradient->x2 = input.readFloat(); + gradient->y2 = input.readFloat(); + gradient->isRadial = input.readByte() != 0; const int numColours = input.readCompressedInt(); for (int i = 0; i < numColours; ++i) { double proportion = (double) input.readFloat(); - const Colour colour ((uint32) input.readInt()); - gradient.addColour (proportion, colour); + const Colour col ((uint32) input.readInt()); + gradient->addColour (proportion, col); } - return new GradientBrush (gradient); - } - - case 3: - { - jassertfalse; //xxx TODO - - return new ImageBrush (0, 0, 0, 0); + break; } default: break; } - return 0; + return Colours::black; } -static void writeBrushToBinary (OutputStream& output, const Brush* const brush) +static void writeColourToBinary (OutputStream& output, const Colour& colour, const ColourGradient* const gradient) { - if (brush == 0) - { - output.writeByte (0); - return; - } - - const SolidColourBrush* cb; - const GradientBrush* gb; - const ImageBrush* ib; - - if ((cb = dynamic_cast (brush)) != 0) + if (gradient == 0) { output.writeByte (1); - output.writeInt ((int) cb->getColour().getARGB()); + output.writeInt ((int) colour.getARGB()); } - else if ((gb = dynamic_cast (brush)) != 0) + else { output.writeByte (2); - const ColourGradient& g = gb->getGradient(); - output.writeFloat (g.x1); - output.writeFloat (g.y1); - output.writeFloat (g.x2); - output.writeFloat (g.y2); - output.writeByte (g.isRadial ? 1 : 0); + output.writeFloat (gradient->x1); + output.writeFloat (gradient->y1); + output.writeFloat (gradient->x2); + output.writeFloat (gradient->y2); + output.writeByte (gradient->isRadial ? 1 : 0); - output.writeCompressedInt (g.getNumColours()); + output.writeCompressedInt (gradient->getNumColours()); - for (int i = 0; i < g.getNumColours(); ++i) + for (int i = 0; i < gradient->getNumColours(); ++i) { - output.writeFloat ((float) g.getColourPosition (i)); - output.writeInt ((int) g.getColour (i).getARGB()); + output.writeFloat ((float) gradient->getColourPosition (i)); + output.writeInt ((int) gradient->getColour (i).getARGB()); } } - else if ((ib = dynamic_cast (brush)) != 0) - { - output.writeByte (3); - jassertfalse; //xxx TODO - } } -static Brush* readBrushFromXml (const XmlElement* xml) +static const Colour readColourFromXml (const XmlElement* xml, ColourGradient*& gradient) { - if (xml == 0) - return 0; + deleteAndZero (gradient); - const String type (xml->getStringAttribute (T("type"))); - - if (type.equalsIgnoreCase (T("solid"))) - return new SolidColourBrush (Colour ((uint32) xml->getStringAttribute (T("colour"), T("ff000000")).getHexValue32())); - - if (type.equalsIgnoreCase (T("gradient"))) + if (xml != 0) { - ColourGradient gradient; - gradient.x1 = (float) xml->getDoubleAttribute (T("x1")); - gradient.y1 = (float) xml->getDoubleAttribute (T("y1")); - gradient.x2 = (float) xml->getDoubleAttribute (T("x2")); - gradient.y2 = (float) xml->getDoubleAttribute (T("y2")); - gradient.isRadial = xml->getBoolAttribute (T("radial"), false); + const String type (xml->getStringAttribute (T("type"))); - StringArray colours; - colours.addTokens (xml->getStringAttribute (T("colours")), false); + if (type.equalsIgnoreCase (T("solid"))) + { + return Colour ((uint32) xml->getStringAttribute (T("colour"), T("ff000000")).getHexValue32()); + } + else if (type.equalsIgnoreCase (T("gradient"))) + { + gradient = new ColourGradient(); + gradient->x1 = (float) xml->getDoubleAttribute (T("x1")); + gradient->y1 = (float) xml->getDoubleAttribute (T("y1")); + gradient->x2 = (float) xml->getDoubleAttribute (T("x2")); + gradient->y2 = (float) xml->getDoubleAttribute (T("y2")); + gradient->isRadial = xml->getBoolAttribute (T("radial"), false); - for (int i = 0; i < colours.size() / 2; ++i) - gradient.addColour (colours[i * 2].getDoubleValue(), - Colour ((uint32) colours[i * 2 + 1].getHexValue32())); + StringArray colours; + colours.addTokens (xml->getStringAttribute (T("colours")), false); - return new GradientBrush (gradient); + for (int i = 0; i < colours.size() / 2; ++i) + gradient->addColour (colours[i * 2].getDoubleValue(), + Colour ((uint32) colours[i * 2 + 1].getHexValue32())); + } + else + { + jassertfalse + } } - if (type.equalsIgnoreCase (T("image"))) - { - jassertfalse; //xxx TODO - - return new ImageBrush (0, 0, 0, 0); - } - - return 0; + return Colours::black; } -static XmlElement* writeBrushToXml (const String& tagName, const Brush* brush) +static XmlElement* writeColourToXml (const String& tagName, const Colour& colour, const ColourGradient* const gradient) { - if (brush == 0) - return 0; - XmlElement* const xml = new XmlElement (tagName); - const SolidColourBrush* cb; - const GradientBrush* gb; - const ImageBrush* ib; - - if ((cb = dynamic_cast (brush)) != 0) + if (gradient == 0) { xml->setAttribute (T("type"), T("solid")); - xml->setAttribute (T("colour"), String::toHexString ((int) cb->getColour().getARGB())); + xml->setAttribute (T("colour"), String::toHexString ((int) colour.getARGB())); } - else if ((gb = dynamic_cast (brush)) != 0) + else { xml->setAttribute (T("type"), T("gradient")); - const ColourGradient& g = gb->getGradient(); - xml->setAttribute (T("x1"), g.x1); - xml->setAttribute (T("y1"), g.y1); - xml->setAttribute (T("x2"), g.x2); - xml->setAttribute (T("y2"), g.y2); - xml->setAttribute (T("radial"), g.isRadial); + xml->setAttribute (T("x1"), gradient->x1); + xml->setAttribute (T("y1"), gradient->y1); + xml->setAttribute (T("x2"), gradient->x2); + xml->setAttribute (T("y2"), gradient->y2); + xml->setAttribute (T("radial"), gradient->isRadial); String s; - for (int i = 0; i < g.getNumColours(); ++i) - s << " " << g.getColourPosition (i) << " " << String::toHexString ((int) g.getColour(i).getARGB()); + for (int i = 0; i < gradient->getNumColours(); ++i) + s << " " << gradient->getColourPosition (i) << " " << String::toHexString ((int) gradient->getColour(i).getARGB()); xml->setAttribute (T("colours"), s.trimStart()); } - else if ((ib = dynamic_cast (brush)) != 0) - { - xml->setAttribute (T("type"), T("image")); - - jassertfalse; //xxx TODO - } return xml; } bool DrawablePath::readBinary (InputStream& input) { - delete fillBrush; - fillBrush = readBrushFromBinary (input); - - delete strokeBrush; - strokeBrush = readBrushFromBinary (input); + fillColour = readColourFromBinary (input, fillGradient); + strokeColour = readColourFromBinary (input, strokeGradient); const float strokeThickness = input.readFloat(); const int jointStyle = input.readByte(); @@ -83869,8 +83829,8 @@ bool DrawablePath::readBinary (InputStream& input) bool DrawablePath::writeBinary (OutputStream& output) const { - writeBrushToBinary (output, fillBrush); - writeBrushToBinary (output, strokeBrush); + writeColourToBinary (output, fillColour, fillGradient); + writeColourToBinary (output, strokeColour, strokeGradient); output.writeFloat (strokeType.getStrokeThickness()); output.writeByte (strokeType.getJointStyle() == PathStrokeType::mitered ? 0 @@ -83887,10 +83847,8 @@ bool DrawablePath::writeBinary (OutputStream& output) const bool DrawablePath::readXml (const XmlElement& xml) { - delete fillBrush; - fillBrush = readBrushFromXml (xml.getChildByName (T("fill"))); - delete strokeBrush; - strokeBrush = readBrushFromXml (xml.getChildByName (T("stroke"))); + fillColour = readColourFromXml (xml.getChildByName (T("fill")), fillGradient); + strokeColour = readColourFromXml (xml.getChildByName (T("stroke")), strokeGradient); const String jointStyle (xml.getStringAttribute (T("jointStyle"), String::empty)); const String endStyle (xml.getStringAttribute (T("capStyle"), String::empty)); @@ -83910,8 +83868,8 @@ bool DrawablePath::readXml (const XmlElement& xml) void DrawablePath::writeXml (XmlElement& xml) const { - xml.addChildElement (writeBrushToXml (T("fill"), fillBrush)); - xml.addChildElement (writeBrushToXml (T("stroke"), strokeBrush)); + xml.addChildElement (writeColourToXml (T("fill"), fillColour, fillGradient)); + xml.addChildElement (writeColourToXml (T("stroke"), strokeColour, strokeGradient)); xml.setAttribute (T("strokeWidth"), (double) strokeType.getStrokeThickness()); xml.setAttribute (T("jointStyle"), @@ -84584,7 +84542,7 @@ private: DrawablePath* dp = new DrawablePath(); dp->setName (xml.getStringAttribute (T("id"))); - dp->setSolidFill (Colours::transparentBlack); + dp->setFillColour (Colours::transparentBlack); path.applyTransform (transform); dp->setPath (path); @@ -84601,47 +84559,49 @@ private: } } - Brush* const fillBrush - = getBrushForFill (path, - getStyleAttribute (&xml, T("fill")), - getStyleAttribute (&xml, T("fill-opacity")), - getStyleAttribute (&xml, T("opacity")), - containsClosedSubPath ? Colours::black - : Colours::transparentBlack); + ColourGradient* fillGradient = 0; + const Colour fillColour (getPathFillType (path, + getStyleAttribute (&xml, T("fill")), + getStyleAttribute (&xml, T("fill-opacity")), + getStyleAttribute (&xml, T("opacity")), + containsClosedSubPath ? Colours::black + : Colours::transparentBlack, + fillGradient)); - if (fillBrush != 0) + if (fillGradient != 0) { - if (! fillBrush->isInvisible()) - { - fillBrush->applyTransform (transform); - dp->setFillBrush (*fillBrush); - } - - delete fillBrush; + fillGradient->transform = fillGradient->transform.followedBy (transform); + dp->setFillGradient (*fillGradient); + delete fillGradient; + } + else + { + dp->setFillColour (fillColour); } const String strokeType (getStyleAttribute (&xml, T("stroke"))); if (strokeType.isNotEmpty() && ! strokeType.equalsIgnoreCase (T("none"))) { - Brush* const strokeBrush - = getBrushForFill (path, strokeType, - getStyleAttribute (&xml, T("stroke-opacity")), - getStyleAttribute (&xml, T("opacity")), - Colours::transparentBlack); + ColourGradient* strokeGradient = 0; + const Colour strokeColour (getPathFillType (path, strokeType, + getStyleAttribute (&xml, T("stroke-opacity")), + getStyleAttribute (&xml, T("opacity")), + Colours::transparentBlack, + strokeGradient)); - if (strokeBrush != 0) + if (strokeGradient != 0) { - const PathStrokeType stroke (getStrokeFor (&xml)); - - if (! strokeBrush->isInvisible()) - { - strokeBrush->applyTransform (transform); - dp->setOutline (stroke, *strokeBrush); - } - - delete strokeBrush; + strokeGradient->transform = strokeGradient->transform.followedBy (transform); + dp->setStrokeGradient (*strokeGradient); + delete strokeGradient; } + else + { + dp->setStrokeColour (strokeColour); + } + + dp->setStrokeType (getStrokeFor (&xml)); } return dp; @@ -84679,11 +84639,12 @@ private: } } - Brush* getBrushForFill (const Path& path, - const String& fill, - const String& fillOpacity, - const String& overallOpacity, - const Colour& defaultColour) const + const Colour getPathFillType (const Path& path, + const String& fill, + const String& fillOpacity, + const String& overallOpacity, + const Colour& defaultColour, + ColourGradient*& gradient) const { float opacity = 1.0f; @@ -84706,29 +84667,29 @@ private: { const XmlElement* inheritedFrom = findLinkedElement (fillXml); - ColourGradient cg; + gradient = new ColourGradient(); - addGradientStopsIn (cg, inheritedFrom); - addGradientStopsIn (cg, fillXml); + addGradientStopsIn (*gradient, inheritedFrom); + addGradientStopsIn (*gradient, fillXml); - if (cg.getNumColours() > 0) + if (gradient->getNumColours() > 0) { - cg.addColour (0.0, cg.getColour (0)); - cg.addColour (1.0, cg.getColour (cg.getNumColours() - 1)); + gradient->addColour (0.0, gradient->getColour (0)); + gradient->addColour (1.0, gradient->getColour (gradient->getNumColours() - 1)); } else { - cg.addColour (0.0, Colours::black); - cg.addColour (1.0, Colours::black); + gradient->addColour (0.0, Colours::black); + gradient->addColour (1.0, Colours::black); } if (overallOpacity.isNotEmpty()) - cg.multiplyOpacity (overallOpacity.getFloatValue()); + gradient->multiplyOpacity (overallOpacity.getFloatValue()); - jassert (cg.getNumColours() > 0); + jassert (gradient->getNumColours() > 0); - cg.isRadial = fillXml->hasTagName (T("radialGradient")); - cg.transform = parseTransform (fillXml->getStringAttribute (T("gradientTransform"))); + gradient->isRadial = fillXml->hasTagName (T("radialGradient")); + gradient->transform = parseTransform (fillXml->getStringAttribute (T("gradientTransform"))); float width = viewBoxW; float height = viewBoxH; @@ -84740,42 +84701,44 @@ private: if (! userSpace) path.getBounds (dx, dy, width, height); - if (cg.isRadial) + if (gradient->isRadial) { - cg.x1 = dx + getCoordLength (fillXml->getStringAttribute (T("cx"), T("50%")), width); - cg.y1 = dy + getCoordLength (fillXml->getStringAttribute (T("cy"), T("50%")), height); + gradient->x1 = dx + getCoordLength (fillXml->getStringAttribute (T("cx"), T("50%")), width); + gradient->y1 = dy + getCoordLength (fillXml->getStringAttribute (T("cy"), T("50%")), height); const float radius = getCoordLength (fillXml->getStringAttribute (T("r"), T("50%")), width); - cg.x2 = cg.x1 + radius; - cg.y2 = cg.y1; + gradient->x2 = gradient->x1 + radius; + gradient->y2 = gradient->y1; //xxx (the fx, fy focal point isn't handled properly here..) } else { - cg.x1 = dx + getCoordLength (fillXml->getStringAttribute (T("x1"), T("0%")), width); - cg.y1 = dy + getCoordLength (fillXml->getStringAttribute (T("y1"), T("0%")), height); + gradient->x1 = dx + getCoordLength (fillXml->getStringAttribute (T("x1"), T("0%")), width); + gradient->y1 = dy + getCoordLength (fillXml->getStringAttribute (T("y1"), T("0%")), height); - cg.x2 = dx + getCoordLength (fillXml->getStringAttribute (T("x2"), T("100%")), width); - cg.y2 = dy + getCoordLength (fillXml->getStringAttribute (T("y2"), T("0%")), height); + gradient->x2 = dx + getCoordLength (fillXml->getStringAttribute (T("x2"), T("100%")), width); + gradient->y2 = dy + getCoordLength (fillXml->getStringAttribute (T("y2"), T("0%")), height); - if (cg.x1 == cg.x2 && cg.y1 == cg.y2) - return new SolidColourBrush (cg.getColour (cg.getNumColours() - 1)); + if (gradient->x1 == gradient->x2 && gradient->y1 == gradient->y2) + { + const Colour col (gradient->getColour (gradient->getNumColours() - 1)); + deleteAndZero (gradient); + return col; + } } - return new GradientBrush (cg); + return defaultColour; } } if (fill.equalsIgnoreCase (T("none"))) - return new SolidColourBrush (Colours::transparentBlack); + return Colours::transparentBlack; int i = 0; Colour colour (parseColour (fill, i, defaultColour)); - colour = colour.withMultipliedAlpha (opacity); - - return new SolidColourBrush (colour); + return colour.withMultipliedAlpha (opacity); } const PathStrokeType getStrokeFor (const XmlElement* const xml) const @@ -264876,7 +264839,7 @@ private: AudioChannelLayout layout; layout.mChannelBitmap = 0; layout.mNumberChannelDescriptions = 0; - layout.mChannelLayoutTag = kAudioChannelLayoutTag_StereoHeadphones; + layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input, 0, &layout, sizeof (layout)); AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output, 0, &layout, sizeof (layout)); diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 2e8d898b95..90122c509e 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -19374,6 +19374,134 @@ private: #endif // __JUCE_COLOURS_JUCEHEADER__ /********* End of inlined file: juce_Colours.h *********/ +/********* Start of inlined file: juce_ColourGradient.h *********/ +#ifndef __JUCE_COLOURGRADIENT_JUCEHEADER__ +#define __JUCE_COLOURGRADIENT_JUCEHEADER__ + +/** + Describes the layout and colours that should be used to paint a colour gradient. + + @see Graphics::setGradientFill +*/ +class JUCE_API ColourGradient +{ +public: + + /** Creates a gradient object. + + (x1, y1) is the location to draw with colour1. Likewise (x2, y2) is where + colour2 should be. In between them there's a gradient. + + 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 note 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 + muddy grey colour midway, but Colour::transparentWhite to Colours::white + will be white all the way across. + + @see ColourGradient + */ + ColourGradient (const Colour& colour1, + const float x1, + const float y1, + const Colour& colour2, + const float x2, + const float y2, + const bool isRadial) throw(); + + /** Creates an uninitialised gradient. + + If you use this constructor instead of the other one, be sure to set all the + object's public member variables before using it! + */ + ColourGradient() throw(); + + /** Destructor */ + ~ColourGradient() throw(); + + /** Removes any colours that have been added. + + This will also remove any start and end colours, so the gradient won't work. You'll + need to add more colours with addColour(). + */ + void clearColours() throw(); + + /** Adds a colour at a point along the length of the gradient. + + This allows the gradient to go through a spectrum of colours, instead of just a + start and end colour. + + @param proportionAlongGradient a value between 0 and 1.0, which is the proportion + of the distance along the line between the two points + at which the colour should occur. + @param colour the colour that should be used at this point + */ + void addColour (const double proportionAlongGradient, + const Colour& colour) throw(); + + /** Multiplies the alpha value of all the colours by the given scale factor */ + void multiplyOpacity (const float multiplier) throw(); + + /** Returns the number of colour-stops that have been added. */ + int getNumColours() const throw(); + + /** Returns the position along the length of the gradient of the colour with this index. + + The index is from 0 to getNumColours() - 1. The return value will be between 0.0 and 1.0 + */ + double getColourPosition (const int index) const throw(); + + /** Returns the colour that was added with a given index. + + The index is from 0 to getNumColours() - 1. The return value will be between 0.0 and 1.0 + */ + const Colour getColour (const int index) const throw(); + + /** Returns the an interpolated colour at any position along the gradient. + @param position the position along the gradient, between 0 and 1 + */ + const Colour getColourAtPosition (const float position) const throw(); + + /** Creates a set of interpolated premultiplied ARGB values. + + The caller must delete the array that is returned using juce_free(). + */ + PixelARGB* createLookupTable (int& numEntries) const throw(); + + /** Returns true if all colours are opaque. */ + bool isOpaque() const throw(); + + /** Returns true if all colours are completely transparent. */ + bool isInvisible() const throw(); + + float x1; + float y1; + + float x2; + float y2; + + /** If true, the gradient should be filled circularly, centred around + (x1, y1), with (x2, y2) defining a point on the circumference. + + If false, the gradient is linear between the two points. + */ + bool isRadial; + + /** A transform to apply to the resultant gradient shape */ + AffineTransform transform; + + juce_UseDebuggingNewOperator + +private: + Array colours; +}; + +#endif // __JUCE_COLOURGRADIENT_JUCEHEADER__ +/********* End of inlined file: juce_ColourGradient.h *********/ + /********* Start of inlined file: juce_SolidColourBrush.h *********/ #ifndef __JUCE_SOLIDCOLOURBRUSH_JUCEHEADER__ #define __JUCE_SOLIDCOLOURBRUSH_JUCEHEADER__ @@ -19720,6 +19848,19 @@ public: */ void setBrush (const Brush* const newBrush) throw(); + /** Sets the context to use a gradient for its fill pattern. + */ + void setGradientFill (const ColourGradient& gradient) throw(); + + /** Sets the context to use a tiled image pattern for filling. + Make sure that you don't delete this image while it's still being used by + this context! + */ + void setTiledImageFill (Image& imageToUse, + const int anchorX, + const int anchorY, + const float opacity) throw(); + /** Changes the font to use for subsequent text-drawing functions. Note there's also a setFont (float, int) method to quickly change the size and @@ -38660,134 +38801,6 @@ private: #ifndef __JUCE_GRADIENTBRUSH_JUCEHEADER__ #define __JUCE_GRADIENTBRUSH_JUCEHEADER__ -/********* Start of inlined file: juce_ColourGradient.h *********/ -#ifndef __JUCE_COLOURGRADIENT_JUCEHEADER__ -#define __JUCE_COLOURGRADIENT_JUCEHEADER__ - -/** - Structure used to define a colour gradient for painting areas. - - @see GradientBrush -*/ -class JUCE_API ColourGradient -{ -public: - - /** Creates a gradient object. - - (x1, y1) is the location to draw with colour1. Likewise (x2, y2) is where - colour2 should be. In between them there's a gradient. - - 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 note 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 - muddy grey colour midway, but Colour::transparentWhite to Colours::white - will be white all the way across. - - @see ColourGradient - */ - ColourGradient (const Colour& colour1, - const float x1, - const float y1, - const Colour& colour2, - const float x2, - const float y2, - const bool isRadial) throw(); - - /** Creates an uninitialised gradient. - - If you use this constructor instead of the other one, be sure to set all the - object's public member variables before using it! - */ - ColourGradient() throw(); - - /** Destructor */ - ~ColourGradient() throw(); - - /** Removes any colours that have been added. - - This will also remove any start and end colours, so the gradient won't work. You'll - need to add more colours with addColour(). - */ - void clearColours() throw(); - - /** Adds a colour at a point along the length of the gradient. - - This allows the gradient to go through a spectrum of colours, instead of just a - start and end colour. - - @param proportionAlongGradient a value between 0 and 1.0, which is the proportion - of the distance along the line between the two points - at which the colour should occur. - @param colour the colour that should be used at this point - */ - void addColour (const double proportionAlongGradient, - const Colour& colour) throw(); - - /** Multiplies the alpha value of all the colours by the given scale factor */ - void multiplyOpacity (const float multiplier) throw(); - - /** Returns the number of colour-stops that have been added. */ - int getNumColours() const throw(); - - /** Returns the position along the length of the gradient of the colour with this index. - - The index is from 0 to getNumColours() - 1. The return value will be between 0.0 and 1.0 - */ - double getColourPosition (const int index) const throw(); - - /** Returns the colour that was added with a given index. - - The index is from 0 to getNumColours() - 1. The return value will be between 0.0 and 1.0 - */ - const Colour getColour (const int index) const throw(); - - /** Returns the an interpolated colour at any position along the gradient. - @param position the position along the gradient, between 0 and 1 - */ - const Colour getColourAtPosition (const float position) const throw(); - - /** Creates a set of interpolated premultiplied ARGB values. - - The caller must delete the array that is returned using juce_free(). - */ - PixelARGB* createLookupTable (int& numEntries) const throw(); - - /** Returns true if all colours are opaque. */ - bool isOpaque() const throw(); - - /** Returns true if all colours are completely transparent. */ - bool isInvisible() const throw(); - - float x1; - float y1; - - float x2; - float y2; - - /** If true, the gradient should be filled circularly, centred around - (x1, y1), with (x2, y2) defining a point on the circumference. - - If false, the gradient is linear between the two points. - */ - bool isRadial; - - /** A transform to apply to the resultant gradient shape */ - AffineTransform transform; - - juce_UseDebuggingNewOperator - -private: - Array colours; -}; - -#endif // __JUCE_COLOURGRADIENT_JUCEHEADER__ -/********* End of inlined file: juce_ColourGradient.h *********/ - /** A Brush that fills areas with a colour gradient. @@ -41647,9 +41660,9 @@ public: /** Changes the path that will be drawn. - @see setSolidFill, setOutline + @see setFillColour, setStrokeType */ - void setPath (const Path& newPath); + void setPath (const Path& newPath) throw(); /** Returns the current path. */ const Path& getPath() const throw() { return path; } @@ -41660,43 +41673,38 @@ public: filled (e.g. if you're just drawing an outline), set this colour to be transparent. - @see setPath, setOutline + @see setPath, setOutlineColour, setFillGradient */ - void setSolidFill (const Colour& newColour); + void setFillColour (const Colour& newColour) throw(); - /** Sets a custom brush to use to fill the path. - - @see setSolidFill + /** Sets a gradient to use to fill the path. */ - void setFillBrush (const Brush& newBrush); + void setFillGradient (const ColourGradient& newGradient) throw(); - /** Returns the brush currently being used to fill the shape. */ - Brush* getCurrentBrush() const throw() { return fillBrush; } + /** Sets the colour with which the outline will be drawn. + @see setStrokeGradient + */ + void setStrokeColour (const Colour& newStrokeColour) throw(); + + /** Sets a gradient with with the outline will be drawn. + @see setStrokeColour + */ + void setStrokeGradient (const ColourGradient& newStrokeGradient) throw(); /** Changes the properties of the outline that will be drawn around the path. + If the stroke has 0 thickness, no stroke will be drawn. - If the thickness value is 0, no outline will be drawn. If one is drawn, the - colour passed-in here will be used for it. - - @see setPath, setSolidFill + @see setStrokeThickness, setStrokeColour */ - void setOutline (const float thickness, - const Colour& outlineColour); + void setStrokeType (const PathStrokeType& newStrokeType) throw(); - /** Changes the properties of the outline that will be drawn around the path. - - If the stroke type has 0 thickness, no outline will be drawn. - - @see setPath, setSolidFill + /** Changes the stroke thickness. + This is a shortcut for calling setStrokeType. */ - void setOutline (const PathStrokeType& strokeType, - const Brush& strokeBrush); + void setStrokeThickness (const float newThickness) throw(); /** Returns the current outline style. */ - const PathStrokeType& getOutlineStroke() const throw() { return strokeType; } - - /** Returns the brush currently being used to draw the outline. */ - Brush* getOutlineBrush() const throw() { return strokeBrush; } + const PathStrokeType& getStrokeType() const throw() { return strokeType; } /** @internal */ void render (const Drawable::RenderingContext& context) const; @@ -41719,8 +41727,9 @@ public: private: Path path, outline; - Brush* fillBrush; - Brush* strokeBrush; + Colour fillColour, strokeColour; + ColourGradient* fillGradient; + ColourGradient* strokeGradient; PathStrokeType strokeType; void updateOutline(); @@ -53840,8 +53849,9 @@ class OpenGLComponentWatcher; @see OpenGLComponent::setPixelFormat */ -struct OpenGLPixelFormat +class JUCE_API OpenGLPixelFormat { +public: /** Creates an OpenGLPixelFormat. @@ -53886,7 +53896,7 @@ struct OpenGLPixelFormat An OpenGLComponent will supply its own context for drawing in its window. */ -class OpenGLContext +class JUCE_API OpenGLContext { public: diff --git a/src/gui/components/code_editor/juce_CodeEditorComponent.cpp b/src/gui/components/code_editor/juce_CodeEditorComponent.cpp index 369ee724a4..1bc515b95d 100644 --- a/src/gui/components/code_editor/juce_CodeEditorComponent.cpp +++ b/src/gui/components/code_editor/juce_CodeEditorComponent.cpp @@ -144,18 +144,15 @@ public: return true; } - void draw (Graphics& g, const Font& font, + void draw (CodeEditorComponent& owner, Graphics& g, const Font& font, float x, const int y, const int baselineOffset, const int lineHeight, - const Array & coloursForTokenCategories, - const Colour& defaultColour, - const Colour& highlightColour, - const float charWidth) const throw() + const Colour& highlightColour) const throw() { if (highlightColumnStart < highlightColumnEnd) { g.setColour (highlightColour); - g.fillRect (roundFloatToInt (x + highlightColumnStart * charWidth), y, - roundFloatToInt ((highlightColumnEnd - highlightColumnStart) * charWidth), lineHeight); + g.fillRect (roundFloatToInt (x + highlightColumnStart * owner.getCharWidth()), y, + roundFloatToInt ((highlightColumnEnd - highlightColumnStart) * owner.getCharWidth()), lineHeight); } int lastType = INT_MIN; @@ -167,11 +164,7 @@ public: if (lastType != token->tokenType) { lastType = token->tokenType; - - if (((unsigned int) lastType) < (unsigned int) coloursForTokenCategories.size()) - g.setColour (coloursForTokenCategories [lastType]); - else - g.setColour (defaultColour); + g.setColour (owner.getColourForTokenType (lastType)); } g.drawSingleLineText (token->text, roundFloatToInt (x), y + baselineOffset); @@ -392,12 +385,17 @@ void CodeEditorComponent::paint (Graphics& g) const Colour defaultColour (findColour (CodeEditorComponent::defaultTextColourId)); const Colour highlightColour (findColour (CodeEditorComponent::highlightColourId)); - for (int j = 0; j < lines.size(); ++j) - lines.getUnchecked(j)->draw (g, font, + const Rectangle clip (g.getClipBounds()); + const int firstLineToDraw = jmax (0, clip.getY() / lineHeight); + const int lastLineToDraw = jmin (lines.size(), clip.getBottom() / lineHeight + 1); + + for (int j = firstLineToDraw; j < lastLineToDraw; ++j) + { + lines.getUnchecked(j)->draw (*this, g, font, (float) (gutter - xOffset * charWidth), lineHeight * j, baselineOffset, lineHeight, - coloursForTokenCategories, defaultColour, - highlightColour, charWidth); + highlightColour); + } } void CodeEditorComponent::handleAsyncUpdate() @@ -408,8 +406,12 @@ void CodeEditorComponent::handleAsyncUpdate() void CodeEditorComponent::rebuildLineTokens() { cancelPendingUpdate(); + const int numNeeded = linesOnScreen + 1; + int minLineToRepaint = numNeeded; + int maxLineToRepaint = 0; + if (numNeeded != lines.size()) { lines.clear(); @@ -417,7 +419,8 @@ void CodeEditorComponent::rebuildLineTokens() for (int i = numNeeded; --i >= 0;) lines.add (new CodeEditorLine()); - repaint(); + minLineToRepaint = 0; + maxLineToRepaint = numNeeded; } jassert (numNeeded == lines.size()); @@ -429,8 +432,19 @@ void CodeEditorComponent::rebuildLineTokens() { CodeEditorLine* const line = lines.getUnchecked(i); - if (line->update (document, firstLineOnScreen + i, source, codeTokeniser, spacesPerTab, selectionStart, selectionEnd)) - repaint (0, lineHeight * i, getWidth(), lineHeight); + if (line->update (document, firstLineOnScreen + i, source, codeTokeniser, spacesPerTab, + selectionStart, selectionEnd)) + { + minLineToRepaint = jmin (minLineToRepaint, i); + maxLineToRepaint = jmax (maxLineToRepaint, i); + } + } + + if (minLineToRepaint <= maxLineToRepaint) + { + repaint (gutter, lineHeight * minLineToRepaint - 1, + verticalScrollBar->getX() - gutter, + lineHeight * (1 + maxLineToRepaint - minLineToRepaint) + 2); } } diff --git a/src/gui/components/controls/juce_TableHeaderComponent.cpp b/src/gui/components/controls/juce_TableHeaderComponent.cpp index 706722cdef..c78875e80c 100644 --- a/src/gui/components/controls/juce_TableHeaderComponent.cpp +++ b/src/gui/components/controls/juce_TableHeaderComponent.cpp @@ -29,7 +29,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_TableHeaderComponent.h" #include "../../graphics/imaging/juce_Image.h" -#include "../../graphics/brushes/juce_GradientBrush.h" #include "../../../text/juce_XmlDocument.h" #include "../lookandfeel/juce_LookAndFeel.h" #include "../layout/juce_StretchableObjectResizer.h" diff --git a/src/gui/components/filebrowser/juce_FileSearchPathListComponent.cpp b/src/gui/components/filebrowser/juce_FileSearchPathListComponent.cpp index 99e22869a4..7eddd5042c 100644 --- a/src/gui/components/filebrowser/juce_FileSearchPathListComponent.cpp +++ b/src/gui/components/filebrowser/juce_FileSearchPathListComponent.cpp @@ -62,7 +62,7 @@ FileSearchPathListComponent::FileSearchPathListComponent() Path arrowPath; arrowPath.addArrow (50.0f, 100.0f, 50.0f, 0.0, 40.0f, 100.0f, 50.0f); DrawablePath arrowImage; - arrowImage.setSolidFill (Colours::black.withAlpha (0.4f)); + arrowImage.setFillColour (Colours::black.withAlpha (0.4f)); arrowImage.setPath (arrowPath); ((DrawableButton*) upButton)->setImages (&arrowImage); @@ -75,7 +75,7 @@ FileSearchPathListComponent::FileSearchPathListComponent() Path arrowPath; arrowPath.addArrow (50.0f, 0.0f, 50.0f, 100.0f, 40.0f, 100.0f, 50.0f); DrawablePath arrowImage; - arrowImage.setSolidFill (Colours::black.withAlpha (0.4f)); + arrowImage.setFillColour (Colours::black.withAlpha (0.4f)); arrowImage.setPath (arrowPath); ((DrawableButton*) downButton)->setImages (&arrowImage); diff --git a/src/gui/components/lookandfeel/juce_LookAndFeel.cpp b/src/gui/components/lookandfeel/juce_LookAndFeel.cpp index 0d5348689d..5008382d9b 100644 --- a/src/gui/components/lookandfeel/juce_LookAndFeel.cpp +++ b/src/gui/components/lookandfeel/juce_LookAndFeel.cpp @@ -58,8 +58,6 @@ BEGIN_JUCE_NAMESPACE #include "../properties/juce_PropertyComponent.h" #include "../juce_Desktop.h" #include "../../graphics/imaging/juce_ImageCache.h" -#include "../../graphics/brushes/juce_GradientBrush.h" -#include "../../graphics/brushes/juce_ImageBrush.h" #include "../../graphics/fonts/juce_GlyphArrangement.h" #include "../../graphics/drawables/juce_DrawableComposite.h" #include "../../graphics/drawables/juce_DrawablePath.h" @@ -647,9 +645,7 @@ void LookAndFeel::drawProgressBar (Graphics& g, ProgressBar& progressBar, true, true, true, true); } - ImageBrush ib (&im, 0, 0, 0.85f); - g.setBrush (&ib); - + g.setTiledImageFill (im, 0, 0, 0.85f); g.fillPath (p); } @@ -782,12 +778,8 @@ void LookAndFeel::drawScrollbar (Graphics& g, const Colour thumbColour (scrollbar.findColour (ScrollBar::thumbColourId)); - GradientBrush gb (thumbColour.overlaidWith (Colour (0x44000000)), - gx1, gy1, - thumbColour.overlaidWith (Colour (0x19000000)), - gx2, gy2, false); - - g.setBrush (&gb); + g.setGradientFill (ColourGradient (thumbColour.overlaidWith (Colour (0x44000000)), gx1, gy1, + thumbColour.overlaidWith (Colour (0x19000000)), gx2, gy2, false)); g.fillPath (slotPath); if (isScrollbarVertical) @@ -801,24 +793,17 @@ void LookAndFeel::drawScrollbar (Graphics& g, gy2 = (float) y + height; } - GradientBrush gb2 (Colours::transparentBlack, - gx1, gy1, - Colour (0x19000000), - gx2, gy2, false); - - g.setBrush (&gb2); + g.setGradientFill (ColourGradient (Colours::transparentBlack,gx1, gy1, + Colour (0x19000000), gx2, gy2, false)); g.fillPath (slotPath); g.setColour (thumbColour); g.fillPath (thumbPath); - GradientBrush gb3 (Colour (0x10000000), - gx1, gy1, - Colours::transparentBlack, - gx2, gy2, false); + g.setGradientFill (ColourGradient (Colour (0x10000000), gx1, gy1, + Colours::transparentBlack, gx2, gy2, false)); g.saveState(); - g.setBrush (&gb3); if (isScrollbarVertical) g.reduceClipRegion (x + width / 2, y, width, height); @@ -1003,13 +988,11 @@ void LookAndFeel::drawPopupMenuUpDownArrow (Graphics& g, { const Colour background (findColour (PopupMenu::backgroundColourId)); - GradientBrush gb (background, - 0.0f, height * 0.5f, - background.withAlpha (0.0f), - 0.0f, isScrollUpArrow ? ((float) height) : 0.0f, - false); + g.setGradientFill (ColourGradient (background, 0.0f, height * 0.5f, + background.withAlpha (0.0f), + 0.0f, isScrollUpArrow ? ((float) height) : 0.0f, + false)); - g.setBrush (&gb); g.fillRect (1, 1, width - 2, height - 2); const float hw = width * 0.5f; @@ -1357,9 +1340,8 @@ void LookAndFeel::drawLinearSliderBackground (Graphics& g, const float iy = y + height * 0.5f - sliderRadius * 0.5f; const float ih = sliderRadius; - GradientBrush gb (gradCol1, 0.0f, iy, - gradCol2, 0.0f, iy + ih, false); - g.setBrush (&gb); + g.setGradientFill (ColourGradient (gradCol1, 0.0f, iy, + gradCol2, 0.0f, iy + ih, false)); indent.addRoundedRectangle (x - sliderRadius * 0.5f, iy, width + sliderRadius, ih, @@ -1371,9 +1353,8 @@ void LookAndFeel::drawLinearSliderBackground (Graphics& g, const float ix = x + width * 0.5f - sliderRadius * 0.5f; const float iw = sliderRadius; - GradientBrush gb (gradCol1, ix, 0.0f, - gradCol2, ix + iw, 0.0f, false); - g.setBrush (&gb); + g.setGradientFill (ColourGradient (gradCol1, ix, 0.0f, + gradCol2, ix + iw, 0.0f, false)); indent.addRoundedRectangle (ix, y - sliderRadius * 0.5f, iw, height + sliderRadius, @@ -1776,11 +1757,10 @@ void LookAndFeel::drawDocumentWindowTitleBar (DocumentWindow& window, { const bool isActive = window.isActiveWindow(); - GradientBrush gb (window.getBackgroundColour(), - 0.0f, 0.0f, - window.getBackgroundColour().contrasting (isActive ? 0.15f : 0.05f), - 0.0f, (float) h, false); - g.setBrush (&gb); + g.setGradientFill (ColourGradient (window.getBackgroundColour(), + 0.0f, 0.0f, + window.getBackgroundColour().contrasting (isActive ? 0.15f : 0.05f), + 0.0f, (float) h, false)); g.fillAll(); Font font (h * 0.65f, Font::bold); @@ -1864,10 +1844,8 @@ public: y += diam * 0.05f; diam *= 0.9f; - GradientBrush gb1 (Colour::greyLevel (0.9f).withAlpha (alpha), 0, y + diam, - Colour::greyLevel (0.6f).withAlpha (alpha), 0, y, false); - - g.setBrush (&gb1); + g.setGradientFill (ColourGradient (Colour::greyLevel (0.9f).withAlpha (alpha), 0, y + diam, + Colour::greyLevel (0.6f).withAlpha (alpha), 0, y, false)); g.fillEllipse (x, y, diam, diam); x += 2.0f; @@ -2000,11 +1978,10 @@ void LookAndFeel::drawStretchableLayoutResizerBar (Graphics& g, const float cy = h * 0.5f; const float cr = jmin (w, h) * 0.4f; - GradientBrush gb (Colours::white.withAlpha (alpha), cx + cr * 0.1f, cy + cr, - Colours::black.withAlpha (alpha), cx, cy - cr * 4.0f, - true); + g.setGradientFill (ColourGradient (Colours::white.withAlpha (alpha), cx + cr * 0.1f, cy + cr, + Colours::black.withAlpha (alpha), cx, cy - cr * 4.0f, + true)); - g.setBrush (&gb); g.fillEllipse (cx - cr, cy - cr, cr * 2.0f, cr * 2.0f); } @@ -2324,11 +2301,9 @@ void LookAndFeel::drawTabAreaBehindFrontButton (Graphics& g, shadowRect.setBounds (0, (int) y2, w, h - (int) y2); } - GradientBrush gb (Colours::black.withAlpha (tabBar.isEnabled() ? 0.3f : 0.15f), x1, y1, - Colours::transparentBlack, x2, y2, - false); + g.setGradientFill (ColourGradient (Colours::black.withAlpha (tabBar.isEnabled() ? 0.3f : 0.15f), x1, y1, + Colours::transparentBlack, x2, y2, false)); - g.setBrush (&gb); shadowRect.expand (2, 2); g.fillRect (shadowRect); @@ -2362,7 +2337,7 @@ Button* LookAndFeel::createTabBarExtrasButton() DrawablePath ellipse; ellipse.setPath (p); - ellipse.setSolidFill (Colour (0x99ffffff)); + ellipse.setFillColour (Colour (0x99ffffff)); p.clear(); p.addEllipse (0.0f, 0.0f, 100.0f, 100.0f); @@ -2373,13 +2348,13 @@ Button* LookAndFeel::createTabBarExtrasButton() DrawablePath dp; dp.setPath (p); - dp.setSolidFill (Colour (0x59000000)); + dp.setFillColour (Colour (0x59000000)); DrawableComposite normalImage; normalImage.insertDrawable (ellipse); normalImage.insertDrawable (dp); - dp.setSolidFill (Colour (0xcc000000)); + dp.setFillColour (Colour (0xcc000000)); DrawableComposite overImage; overImage.insertDrawable (ellipse); @@ -2399,11 +2374,9 @@ void LookAndFeel::drawTableHeaderBackground (Graphics& g, TableHeaderComponent& const int w = header.getWidth(); const int h = header.getHeight(); - GradientBrush gb (Colour (0xffe8ebf9), 0.0f, h * 0.5f, - Colour (0xfff6f8f9), 0.0f, h - 1.0f, - false); - - g.setBrush (&gb); + g.setGradientFill (ColourGradient (Colour (0xffe8ebf9), 0.0f, h * 0.5f, + Colour (0xfff6f8f9), 0.0f, h - 1.0f, + false)); g.fillRect (0, h / 2, w, h); g.setColour (Colour (0x33000000)); @@ -2453,13 +2426,11 @@ void LookAndFeel::paintToolbarBackground (Graphics& g, int w, int h, Toolbar& to { const Colour background (toolbar.findColour (Toolbar::backgroundColourId)); - GradientBrush gb (background, 0.0f, 0.0f, - background.darker (0.1f), - toolbar.isVertical() ? w - 1.0f : 0.0f, - toolbar.isVertical() ? 0.0f : h - 1.0f, - false); - - g.setBrush (&gb); + g.setGradientFill (ColourGradient (background, 0.0f, 0.0f, + background.darker (0.1f), + toolbar.isVertical() ? w - 1.0f : 0.0f, + toolbar.isVertical() ? 0.0f : h - 1.0f, + false)); g.fillAll(); } @@ -2630,7 +2601,7 @@ Button* LookAndFeel::createFileBrowserGoUpButton() arrowPath.addArrow (50.0f, 100.0f, 50.0f, 0.0, 40.0f, 100.0f, 50.0f); DrawablePath arrowImage; - arrowImage.setSolidFill (Colours::black.withAlpha (0.4f)); + arrowImage.setFillColour (Colours::black.withAlpha (0.4f)); arrowImage.setPath (arrowPath); goUpButton->setImages (&arrowImage); @@ -2866,8 +2837,7 @@ void LookAndFeel::drawShinyButtonShape (Graphics& g, cg.addColour (0.5, baseColour.overlaidWith (Colour (0x33ffffff))); cg.addColour (0.51, baseColour.overlaidWith (Colour (0x110000ff))); - GradientBrush gb (cg); - g.setBrush (&gb); + g.setGradientFill (cg); g.fillPath (outline); g.setColour (Colour (0x80000000)); @@ -2893,32 +2863,24 @@ void LookAndFeel::drawGlassSphere (Graphics& g, cg.addColour (0.4, Colours::white.overlaidWith (colour)); - GradientBrush gb (cg); - g.setBrush (&gb); + g.setGradientFill (cg); g.fillPath (p); } - { - GradientBrush gb (Colours::white, 0, y + diameter * 0.06f, - Colours::transparentWhite, 0, y + diameter * 0.3f, false); + g.setGradientFill (ColourGradient (Colours::white, 0, y + diameter * 0.06f, + Colours::transparentWhite, 0, y + diameter * 0.3f, false)); + g.fillEllipse (x + diameter * 0.2f, y + diameter * 0.05f, diameter * 0.6f, diameter * 0.4f); - g.setBrush (&gb); - g.fillEllipse (x + diameter * 0.2f, y + diameter * 0.05f, diameter * 0.6f, diameter * 0.4f); - } + ColourGradient cg (Colours::transparentBlack, + x + diameter * 0.5f, y + diameter * 0.5f, + Colours::black.withAlpha (0.5f * outlineThickness * colour.getFloatAlpha()), + x, y + diameter * 0.5f, true); - { - ColourGradient cg (Colours::transparentBlack, - x + diameter * 0.5f, y + diameter * 0.5f, - Colours::black.withAlpha (0.5f * outlineThickness * colour.getFloatAlpha()), - x, y + diameter * 0.5f, true); + cg.addColour (0.7, Colours::transparentBlack); + cg.addColour (0.8, Colours::black.withAlpha (0.1f * outlineThickness)); - cg.addColour (0.7, Colours::transparentBlack); - cg.addColour (0.8, Colours::black.withAlpha (0.1f * outlineThickness)); - - GradientBrush gb (cg); - g.setBrush (&gb); - g.fillPath (p); - } + g.setGradientFill (cg); + g.fillPath (p); g.setColour (Colours::black.withAlpha (0.5f * colour.getFloatAlpha())); g.drawEllipse (x, y, diameter, diameter, outlineThickness); @@ -2950,24 +2912,20 @@ void LookAndFeel::drawGlassPointer (Graphics& g, cg.addColour (0.4, Colours::white.overlaidWith (colour)); - GradientBrush gb (cg); - g.setBrush (&gb); + g.setGradientFill (cg); g.fillPath (p); } - { - ColourGradient cg (Colours::transparentBlack, - x + diameter * 0.5f, y + diameter * 0.5f, - Colours::black.withAlpha (0.5f * outlineThickness * colour.getFloatAlpha()), - x - diameter * 0.2f, y + diameter * 0.5f, true); + ColourGradient cg (Colours::transparentBlack, + x + diameter * 0.5f, y + diameter * 0.5f, + Colours::black.withAlpha (0.5f * outlineThickness * colour.getFloatAlpha()), + x - diameter * 0.2f, y + diameter * 0.5f, true); - cg.addColour (0.5, Colours::transparentBlack); - cg.addColour (0.7, Colours::black.withAlpha (0.07f * outlineThickness)); + cg.addColour (0.5, Colours::transparentBlack); + cg.addColour (0.7, Colours::black.withAlpha (0.07f * outlineThickness)); - GradientBrush gb (cg); - g.setBrush (&gb); - g.fillPath (p); - } + g.setGradientFill (cg); + g.fillPath (p); g.setColour (Colours::black.withAlpha (0.5f * colour.getFloatAlpha())); g.strokePath (p, PathStrokeType (outlineThickness)); @@ -3012,8 +2970,7 @@ void LookAndFeel::drawGlassLozenge (Graphics& g, cg.addColour (0.4, colour); cg.addColour (0.97, colour.withMultipliedAlpha (0.3f)); - GradientBrush gb (cg); - g.setBrush (&gb); + g.setGradientFill (cg); g.fillPath (outline); } @@ -3025,10 +2982,8 @@ void LookAndFeel::drawGlassLozenge (Graphics& g, if (! (flatOnLeft || flatOnTop || flatOnBottom)) { - GradientBrush gb (cg); - g.saveState(); - g.setBrush (&gb); + g.setGradientFill (cg); g.reduceClipRegion (intX, intY, intEdge, intH); g.fillPath (outline); g.restoreState(); @@ -3038,10 +2993,9 @@ void LookAndFeel::drawGlassLozenge (Graphics& g, { cg.x1 = x + width - edgeBlurRadius; cg.x2 = x + width; - GradientBrush gb (cg); g.saveState(); - g.setBrush (&gb); + g.setGradientFill (cg); g.reduceClipRegion (intX + intW - intEdge, intY, 2 + intEdge, intH); g.fillPath (outline); g.restoreState(); @@ -3062,10 +3016,8 @@ void LookAndFeel::drawGlassLozenge (Graphics& g, ! (flatOnLeft || flatOnBottom), ! (flatOnRight || flatOnBottom)); - GradientBrush gb (colour.brighter (10.0f), 0, y + height * 0.06f, - Colours::transparentWhite, 0, y + height * 0.4f, false); - - g.setBrush (&gb); + g.setGradientFill (ColourGradient (colour.brighter (10.0f), 0, y + height * 0.06f, + Colours::transparentWhite, 0, y + height * 0.4f, false)); g.fillPath (highlight); } diff --git a/src/gui/components/lookandfeel/juce_OldSchoolLookAndFeel.cpp b/src/gui/components/lookandfeel/juce_OldSchoolLookAndFeel.cpp index 08a6d39930..18a9786966 100644 --- a/src/gui/components/lookandfeel/juce_OldSchoolLookAndFeel.cpp +++ b/src/gui/components/lookandfeel/juce_OldSchoolLookAndFeel.cpp @@ -41,7 +41,6 @@ BEGIN_JUCE_NAMESPACE #include "../controls/juce_ListBox.h" #include "../filebrowser/juce_FilenameComponent.h" #include "../juce_Desktop.h" -#include "../../graphics/brushes/juce_GradientBrush.h" #include "../../graphics/drawables/juce_DrawableComposite.h" #include "../../graphics/drawables/juce_DrawablePath.h" @@ -558,7 +557,7 @@ Button* OldSchoolLookAndFeel::createDocumentWindowButton (int buttonType) DrawableButton* b = new DrawableButton ("minimise", DrawableButton::ImageFitted); DrawablePath dp; dp.setPath (shape); - dp.setSolidFill (Colours::black.withAlpha (0.3f)); + dp.setFillColour (Colours::black.withAlpha (0.3f)); b->setImages (&dp); return b; } @@ -570,7 +569,7 @@ Button* OldSchoolLookAndFeel::createDocumentWindowButton (int buttonType) DrawableButton* b = new DrawableButton ("maximise", DrawableButton::ImageFitted); DrawablePath dp; dp.setPath (shape); - dp.setSolidFill (Colours::black.withAlpha (0.3f)); + dp.setFillColour (Colours::black.withAlpha (0.3f)); b->setImages (&dp); return b; } diff --git a/src/gui/components/special/juce_DropShadower.cpp b/src/gui/components/special/juce_DropShadower.cpp index f2bd0efe4d..326da80be2 100644 --- a/src/gui/components/special/juce_DropShadower.cpp +++ b/src/gui/components/special/juce_DropShadower.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_DropShadower.h" -#include "../../graphics/brushes/juce_ImageBrush.h" #include "../../graphics/imaging/juce_ImageCache.h" #include "../../graphics/imaging/juce_ImageConvolutionKernel.h" #include "../../graphics/imaging/juce_Image.h" @@ -75,7 +74,6 @@ public: Image* const topLeft = shadowImageSections [type * 3]; Image* const bottomRight = shadowImageSections [type * 3 + 1]; Image* const filler = shadowImageSections [type * 3 + 2]; - ImageBrush fillBrush (filler, 0, 0, 1.0f); g.setOpacity (1.0f); @@ -91,7 +89,7 @@ public: 0, getHeight() - imH, bottomRight->getWidth(), imH, 0, bottomRight->getHeight() - imH, bottomRight->getWidth(), imH); - g.setBrush (&fillBrush); + g.setTiledImageFill (*filler, 0, 0, 1.0f); g.fillRect (0, topLeft->getHeight(), getWidth(), getHeight() - (topLeft->getHeight() + bottomRight->getHeight())); } else @@ -106,7 +104,7 @@ public: getWidth() - imW, 0, imW, bottomRight->getHeight(), bottomRight->getWidth() - imW, 0, imW, bottomRight->getHeight()); - g.setBrush (&fillBrush); + g.setTiledImageFill (*filler, 0, 0, 1.0f); g.fillRect (topLeft->getWidth(), 0, getWidth() - (topLeft->getWidth() + bottomRight->getWidth()), getHeight()); } } diff --git a/src/gui/components/special/juce_MidiKeyboardComponent.cpp b/src/gui/components/special/juce_MidiKeyboardComponent.cpp index 2d420a01a7..3b81141279 100644 --- a/src/gui/components/special/juce_MidiKeyboardComponent.cpp +++ b/src/gui/components/special/juce_MidiKeyboardComponent.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_MidiKeyboardComponent.h" -#include "../../graphics/brushes/juce_GradientBrush.h" //============================================================================== @@ -381,9 +380,8 @@ void MidiKeyboardComponent::paint (Graphics& g) else y2 = 5.0f; - GradientBrush gb (Colours::black.withAlpha (0.3f), x1, y1, - Colours::transparentBlack, x2, y2, false); - g.setBrush (&gb); + g.setGradientFill (ColourGradient (Colours::black.withAlpha (0.3f), x1, y1, + Colours::transparentBlack, x2, y2, false)); getKeyPos (rangeEnd, x, w); x += w; diff --git a/src/gui/components/special/juce_OpenGLComponent.h b/src/gui/components/special/juce_OpenGLComponent.h index e5b142fdb0..c5a0f0e6c7 100644 --- a/src/gui/components/special/juce_OpenGLComponent.h +++ b/src/gui/components/special/juce_OpenGLComponent.h @@ -40,8 +40,9 @@ class OpenGLComponentWatcher; @see OpenGLComponent::setPixelFormat */ -struct OpenGLPixelFormat +class JUCE_API OpenGLPixelFormat { +public: //============================================================================== /** Creates an OpenGLPixelFormat. @@ -90,7 +91,7 @@ struct OpenGLPixelFormat An OpenGLComponent will supply its own context for drawing in its window. */ -class OpenGLContext +class JUCE_API OpenGLContext { public: //============================================================================== diff --git a/src/gui/graphics/colour/juce_ColourGradient.h b/src/gui/graphics/colour/juce_ColourGradient.h index 41d4e67643..d9130a1029 100644 --- a/src/gui/graphics/colour/juce_ColourGradient.h +++ b/src/gui/graphics/colour/juce_ColourGradient.h @@ -33,9 +33,9 @@ //============================================================================== /** - Structure used to define a colour gradient for painting areas. + Describes the layout and colours that should be used to paint a colour gradient. - @see GradientBrush + @see Graphics::setGradientFill */ class JUCE_API ColourGradient { diff --git a/src/gui/graphics/contexts/juce_Graphics.cpp b/src/gui/graphics/contexts/juce_Graphics.cpp index 3df8df459e..05421fe610 100644 --- a/src/gui/graphics/contexts/juce_Graphics.cpp +++ b/src/gui/graphics/contexts/juce_Graphics.cpp @@ -32,7 +32,8 @@ BEGIN_JUCE_NAMESPACE #include "../geometry/juce_PathStrokeType.h" #include "juce_EdgeTable.h" #include "juce_LowLevelGraphicsContext.h" - +#include "../brushes/juce_GradientBrush.h" +#include "../brushes/juce_ImageBrush.h" static const Graphics::ResamplingQuality defaultQuality = Graphics::mediumResamplingQuality; @@ -212,6 +213,23 @@ void Graphics::setBrush (const Brush* const newBrush) throw() state->brush = 0; } +void Graphics::setGradientFill (const ColourGradient& gradient) throw() +{ + saveStateIfPending(); + delete state->brush; + state->brush = new GradientBrush (gradient); +} + +void Graphics::setTiledImageFill (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() : colour (Colours::black), diff --git a/src/gui/graphics/contexts/juce_Graphics.h b/src/gui/graphics/contexts/juce_Graphics.h index 71cee84825..06bdfdda6a 100644 --- a/src/gui/graphics/contexts/juce_Graphics.h +++ b/src/gui/graphics/contexts/juce_Graphics.h @@ -31,6 +31,7 @@ #include "../geometry/juce_PathStrokeType.h" #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; @@ -103,6 +104,19 @@ public: */ void setBrush (const Brush* const newBrush) throw(); + /** Sets the context to use a gradient for its fill pattern. + */ + void setGradientFill (const ColourGradient& gradient) throw(); + + /** Sets the context to use a tiled image pattern for filling. + Make sure that you don't delete this image while it's still being used by + this context! + */ + void setTiledImageFill (Image& imageToUse, + const int anchorX, + const int anchorY, + const float opacity) throw(); + //============================================================================== /** Changes the font to use for subsequent text-drawing functions. diff --git a/src/gui/graphics/drawables/juce_DrawablePath.cpp b/src/gui/graphics/drawables/juce_DrawablePath.cpp index 5826ac3603..beb2bf7628 100644 --- a/src/gui/graphics/drawables/juce_DrawablePath.cpp +++ b/src/gui/graphics/drawables/juce_DrawablePath.cpp @@ -28,86 +28,98 @@ BEGIN_JUCE_NAMESPACE #include "juce_DrawablePath.h" -#include "../brushes/juce_SolidColourBrush.h" -#include "../brushes/juce_GradientBrush.h" -#include "../brushes/juce_ImageBrush.h" #include "../../../io/streams/juce_MemoryOutputStream.h" //============================================================================== DrawablePath::DrawablePath() - : fillBrush (new SolidColourBrush (Colours::black)), - strokeBrush (0), + : fillColour (0xff000000), + fillGradient (0), + strokeGradient (0), strokeType (0.0f) { } DrawablePath::~DrawablePath() { - delete fillBrush; - delete strokeBrush; + delete fillGradient; + delete strokeGradient; } //============================================================================== -void DrawablePath::setPath (const Path& newPath) +void DrawablePath::setPath (const Path& newPath) throw() { path = newPath; updateOutline(); } -void DrawablePath::setSolidFill (const Colour& newColour) +void DrawablePath::setFillColour (const Colour& newColour) throw() { - delete fillBrush; - fillBrush = new SolidColourBrush (newColour); + deleteAndZero (fillGradient); + fillColour = newColour; } -void DrawablePath::setFillBrush (const Brush& newBrush) +void DrawablePath::setFillGradient (const ColourGradient& gradient) throw() { - delete fillBrush; - fillBrush = newBrush.createCopy(); + delete fillGradient; + fillGradient = new ColourGradient (gradient); } -void DrawablePath::setOutline (const float thickness, const Colour& colour) +void DrawablePath::setStrokeType (const PathStrokeType& newStrokeType) throw() { - strokeType = PathStrokeType (thickness); - delete strokeBrush; - strokeBrush = new SolidColourBrush (colour); + strokeType = newStrokeType; updateOutline(); } -void DrawablePath::setOutline (const PathStrokeType& strokeType_, const Brush& newStrokeBrush) +void DrawablePath::setStrokeThickness (const float newThickness) throw() { - strokeType = strokeType_; - delete strokeBrush; - strokeBrush = newStrokeBrush.createCopy(); - updateOutline(); + setStrokeType (PathStrokeType (newThickness, strokeType.getJointStyle(), strokeType.getEndStyle())); } +void DrawablePath::setStrokeColour (const Colour& newStrokeColour) throw() +{ + deleteAndZero (strokeGradient); + strokeColour = newStrokeColour; +} + +void DrawablePath::setStrokeGradient (const ColourGradient& newStrokeGradient) throw() +{ + delete strokeGradient; + strokeGradient = new ColourGradient (newStrokeGradient); +} //============================================================================== void DrawablePath::render (const Drawable::RenderingContext& context) const { + if (fillGradient != 0) { - Brush* const tempBrush = fillBrush->createCopy(); - tempBrush->applyTransform (context.transform); - tempBrush->multiplyOpacity (context.opacity); - - context.g.setBrush (tempBrush); - context.g.fillPath (path, context.transform); - - delete tempBrush; + ColourGradient cg (*fillGradient); + cg.transform = cg.transform.followedBy (context.transform); + cg.multiplyOpacity (context.opacity); + context.g.setGradientFill (cg); + } + else + { + context.g.setColour (fillColour); } - if (strokeBrush != 0 && strokeType.getStrokeThickness() > 0.0f) + context.g.fillPath (path, context.transform); + + if (strokeType.getStrokeThickness() > 0.0f) { - Brush* const tempBrush = strokeBrush->createCopy(); - tempBrush->applyTransform (context.transform); - tempBrush->multiplyOpacity (context.opacity); + if (strokeGradient != 0) + { + ColourGradient cg (*strokeGradient); + cg.transform = cg.transform.followedBy (context.transform); + cg.multiplyOpacity (context.opacity); + context.g.setGradientFill (cg); + } + else + { + context.g.setColour (strokeColour); + } - context.g.setBrush (tempBrush); context.g.fillPath (outline, context.transform); - - delete tempBrush; } } @@ -136,188 +148,149 @@ Drawable* DrawablePath::createCopy() const DrawablePath* const dp = new DrawablePath(); dp->path = path; - dp->setFillBrush (*fillBrush); - - if (strokeBrush != 0) - dp->setOutline (strokeType, *strokeBrush); - + dp->outline = outline; + dp->fillColour = fillColour; + dp->strokeColour = strokeColour; + dp->fillGradient = (fillGradient != 0) ? new ColourGradient (*fillGradient) : 0; + dp->strokeGradient = (strokeGradient != 0) ? new ColourGradient (*strokeGradient) : 0; + dp->strokeType = strokeType; return dp; } //============================================================================== -static Brush* readBrushFromBinary (InputStream& input) +static const Colour readColourFromBinary (InputStream& input, ColourGradient*& gradient) { + deleteAndZero (gradient); + switch (input.readByte()) { case 1: - return new SolidColourBrush (Colour ((uint32) input.readInt())); + return Colour ((uint32) input.readInt()); case 2: { - ColourGradient gradient; - gradient.x1 = input.readFloat(); - gradient.y1 = input.readFloat(); - gradient.x2 = input.readFloat(); - gradient.y2 = input.readFloat(); - gradient.isRadial = input.readByte() != 0; + gradient = new ColourGradient(); + gradient->x1 = input.readFloat(); + gradient->y1 = input.readFloat(); + gradient->x2 = input.readFloat(); + gradient->y2 = input.readFloat(); + gradient->isRadial = input.readByte() != 0; const int numColours = input.readCompressedInt(); for (int i = 0; i < numColours; ++i) { double proportion = (double) input.readFloat(); - const Colour colour ((uint32) input.readInt()); - gradient.addColour (proportion, colour); + const Colour col ((uint32) input.readInt()); + gradient->addColour (proportion, col); } - return new GradientBrush (gradient); - } - - case 3: - { - jassertfalse; //xxx TODO - - return new ImageBrush (0, 0, 0, 0); + break; } default: break; } - return 0; + return Colours::black; } -static void writeBrushToBinary (OutputStream& output, const Brush* const brush) +static void writeColourToBinary (OutputStream& output, const Colour& colour, const ColourGradient* const gradient) { - if (brush == 0) - { - output.writeByte (0); - return; - } - - const SolidColourBrush* cb; - const GradientBrush* gb; - const ImageBrush* ib; - - if ((cb = dynamic_cast (brush)) != 0) + if (gradient == 0) { output.writeByte (1); - output.writeInt ((int) cb->getColour().getARGB()); + output.writeInt ((int) colour.getARGB()); } - else if ((gb = dynamic_cast (brush)) != 0) + else { output.writeByte (2); - const ColourGradient& g = gb->getGradient(); - output.writeFloat (g.x1); - output.writeFloat (g.y1); - output.writeFloat (g.x2); - output.writeFloat (g.y2); - output.writeByte (g.isRadial ? 1 : 0); + output.writeFloat (gradient->x1); + output.writeFloat (gradient->y1); + output.writeFloat (gradient->x2); + output.writeFloat (gradient->y2); + output.writeByte (gradient->isRadial ? 1 : 0); - output.writeCompressedInt (g.getNumColours()); + output.writeCompressedInt (gradient->getNumColours()); - for (int i = 0; i < g.getNumColours(); ++i) + for (int i = 0; i < gradient->getNumColours(); ++i) { - output.writeFloat ((float) g.getColourPosition (i)); - output.writeInt ((int) g.getColour (i).getARGB()); + output.writeFloat ((float) gradient->getColourPosition (i)); + output.writeInt ((int) gradient->getColour (i).getARGB()); } } - else if ((ib = dynamic_cast (brush)) != 0) - { - output.writeByte (3); - jassertfalse; //xxx TODO - } } -static Brush* readBrushFromXml (const XmlElement* xml) +static const Colour readColourFromXml (const XmlElement* xml, ColourGradient*& gradient) { - if (xml == 0) - return 0; + deleteAndZero (gradient); - const String type (xml->getStringAttribute (T("type"))); - - if (type.equalsIgnoreCase (T("solid"))) - return new SolidColourBrush (Colour ((uint32) xml->getStringAttribute (T("colour"), T("ff000000")).getHexValue32())); - - if (type.equalsIgnoreCase (T("gradient"))) + if (xml != 0) { - ColourGradient gradient; - gradient.x1 = (float) xml->getDoubleAttribute (T("x1")); - gradient.y1 = (float) xml->getDoubleAttribute (T("y1")); - gradient.x2 = (float) xml->getDoubleAttribute (T("x2")); - gradient.y2 = (float) xml->getDoubleAttribute (T("y2")); - gradient.isRadial = xml->getBoolAttribute (T("radial"), false); + const String type (xml->getStringAttribute (T("type"))); - StringArray colours; - colours.addTokens (xml->getStringAttribute (T("colours")), false); + if (type.equalsIgnoreCase (T("solid"))) + { + return Colour ((uint32) xml->getStringAttribute (T("colour"), T("ff000000")).getHexValue32()); + } + else if (type.equalsIgnoreCase (T("gradient"))) + { + gradient = new ColourGradient(); + gradient->x1 = (float) xml->getDoubleAttribute (T("x1")); + gradient->y1 = (float) xml->getDoubleAttribute (T("y1")); + gradient->x2 = (float) xml->getDoubleAttribute (T("x2")); + gradient->y2 = (float) xml->getDoubleAttribute (T("y2")); + gradient->isRadial = xml->getBoolAttribute (T("radial"), false); - for (int i = 0; i < colours.size() / 2; ++i) - gradient.addColour (colours[i * 2].getDoubleValue(), - Colour ((uint32) colours[i * 2 + 1].getHexValue32())); + StringArray colours; + colours.addTokens (xml->getStringAttribute (T("colours")), false); - return new GradientBrush (gradient); + for (int i = 0; i < colours.size() / 2; ++i) + gradient->addColour (colours[i * 2].getDoubleValue(), + Colour ((uint32) colours[i * 2 + 1].getHexValue32())); + } + else + { + jassertfalse + } } - if (type.equalsIgnoreCase (T("image"))) - { - jassertfalse; //xxx TODO - - return new ImageBrush (0, 0, 0, 0); - } - - return 0; + return Colours::black; } -static XmlElement* writeBrushToXml (const String& tagName, const Brush* brush) +static XmlElement* writeColourToXml (const String& tagName, const Colour& colour, const ColourGradient* const gradient) { - if (brush == 0) - return 0; - XmlElement* const xml = new XmlElement (tagName); - const SolidColourBrush* cb; - const GradientBrush* gb; - const ImageBrush* ib; - - if ((cb = dynamic_cast (brush)) != 0) + if (gradient == 0) { xml->setAttribute (T("type"), T("solid")); - xml->setAttribute (T("colour"), String::toHexString ((int) cb->getColour().getARGB())); + xml->setAttribute (T("colour"), String::toHexString ((int) colour.getARGB())); } - else if ((gb = dynamic_cast (brush)) != 0) + else { xml->setAttribute (T("type"), T("gradient")); - const ColourGradient& g = gb->getGradient(); - xml->setAttribute (T("x1"), g.x1); - xml->setAttribute (T("y1"), g.y1); - xml->setAttribute (T("x2"), g.x2); - xml->setAttribute (T("y2"), g.y2); - xml->setAttribute (T("radial"), g.isRadial); + xml->setAttribute (T("x1"), gradient->x1); + xml->setAttribute (T("y1"), gradient->y1); + xml->setAttribute (T("x2"), gradient->x2); + xml->setAttribute (T("y2"), gradient->y2); + xml->setAttribute (T("radial"), gradient->isRadial); String s; - for (int i = 0; i < g.getNumColours(); ++i) - s << " " << g.getColourPosition (i) << " " << String::toHexString ((int) g.getColour(i).getARGB()); + for (int i = 0; i < gradient->getNumColours(); ++i) + s << " " << gradient->getColourPosition (i) << " " << String::toHexString ((int) gradient->getColour(i).getARGB()); xml->setAttribute (T("colours"), s.trimStart()); } - else if ((ib = dynamic_cast (brush)) != 0) - { - xml->setAttribute (T("type"), T("image")); - - jassertfalse; //xxx TODO - } return xml; } bool DrawablePath::readBinary (InputStream& input) { - delete fillBrush; - fillBrush = readBrushFromBinary (input); - - delete strokeBrush; - strokeBrush = readBrushFromBinary (input); + fillColour = readColourFromBinary (input, fillGradient); + strokeColour = readColourFromBinary (input, strokeGradient); const float strokeThickness = input.readFloat(); const int jointStyle = input.readByte(); @@ -346,8 +319,8 @@ bool DrawablePath::readBinary (InputStream& input) bool DrawablePath::writeBinary (OutputStream& output) const { - writeBrushToBinary (output, fillBrush); - writeBrushToBinary (output, strokeBrush); + writeColourToBinary (output, fillColour, fillGradient); + writeColourToBinary (output, strokeColour, strokeGradient); output.writeFloat (strokeType.getStrokeThickness()); output.writeByte (strokeType.getJointStyle() == PathStrokeType::mitered ? 0 @@ -364,10 +337,8 @@ bool DrawablePath::writeBinary (OutputStream& output) const bool DrawablePath::readXml (const XmlElement& xml) { - delete fillBrush; - fillBrush = readBrushFromXml (xml.getChildByName (T("fill"))); - delete strokeBrush; - strokeBrush = readBrushFromXml (xml.getChildByName (T("stroke"))); + fillColour = readColourFromXml (xml.getChildByName (T("fill")), fillGradient); + strokeColour = readColourFromXml (xml.getChildByName (T("stroke")), strokeGradient); const String jointStyle (xml.getStringAttribute (T("jointStyle"), String::empty)); const String endStyle (xml.getStringAttribute (T("capStyle"), String::empty)); @@ -387,8 +358,8 @@ bool DrawablePath::readXml (const XmlElement& xml) void DrawablePath::writeXml (XmlElement& xml) const { - xml.addChildElement (writeBrushToXml (T("fill"), fillBrush)); - xml.addChildElement (writeBrushToXml (T("stroke"), strokeBrush)); + xml.addChildElement (writeColourToXml (T("fill"), fillColour, fillGradient)); + xml.addChildElement (writeColourToXml (T("stroke"), strokeColour, strokeGradient)); xml.setAttribute (T("strokeWidth"), (double) strokeType.getStrokeThickness()); xml.setAttribute (T("jointStyle"), diff --git a/src/gui/graphics/drawables/juce_DrawablePath.h b/src/gui/graphics/drawables/juce_DrawablePath.h index 5f8ecee493..aadb454f4c 100644 --- a/src/gui/graphics/drawables/juce_DrawablePath.h +++ b/src/gui/graphics/drawables/juce_DrawablePath.h @@ -50,9 +50,9 @@ public: //============================================================================== /** Changes the path that will be drawn. - @see setSolidFill, setOutline + @see setFillColour, setStrokeType */ - void setPath (const Path& newPath); + void setPath (const Path& newPath) throw(); /** Returns the current path. */ const Path& getPath() const throw() { return path; } @@ -63,43 +63,38 @@ public: filled (e.g. if you're just drawing an outline), set this colour to be transparent. - @see setPath, setOutline + @see setPath, setOutlineColour, setFillGradient */ - void setSolidFill (const Colour& newColour); + void setFillColour (const Colour& newColour) throw(); - /** Sets a custom brush to use to fill the path. - - @see setSolidFill + /** Sets a gradient to use to fill the path. */ - void setFillBrush (const Brush& newBrush); + void setFillGradient (const ColourGradient& newGradient) throw(); - /** Returns the brush currently being used to fill the shape. */ - Brush* getCurrentBrush() const throw() { return fillBrush; } + /** Sets the colour with which the outline will be drawn. + @see setStrokeGradient + */ + void setStrokeColour (const Colour& newStrokeColour) throw(); + + /** Sets a gradient with with the outline will be drawn. + @see setStrokeColour + */ + void setStrokeGradient (const ColourGradient& newStrokeGradient) throw(); /** Changes the properties of the outline that will be drawn around the path. + If the stroke has 0 thickness, no stroke will be drawn. - If the thickness value is 0, no outline will be drawn. If one is drawn, the - colour passed-in here will be used for it. - - @see setPath, setSolidFill + @see setStrokeThickness, setStrokeColour */ - void setOutline (const float thickness, - const Colour& outlineColour); + void setStrokeType (const PathStrokeType& newStrokeType) throw(); - /** Changes the properties of the outline that will be drawn around the path. - - If the stroke type has 0 thickness, no outline will be drawn. - - @see setPath, setSolidFill + /** Changes the stroke thickness. + This is a shortcut for calling setStrokeType. */ - void setOutline (const PathStrokeType& strokeType, - const Brush& strokeBrush); + void setStrokeThickness (const float newThickness) throw(); /** Returns the current outline style. */ - const PathStrokeType& getOutlineStroke() const throw() { return strokeType; } - - /** Returns the brush currently being used to draw the outline. */ - Brush* getOutlineBrush() const throw() { return strokeBrush; } + const PathStrokeType& getStrokeType() const throw() { return strokeType; } //============================================================================== @@ -125,8 +120,9 @@ public: private: Path path, outline; - Brush* fillBrush; - Brush* strokeBrush; + Colour fillColour, strokeColour; + ColourGradient* fillGradient; + ColourGradient* strokeGradient; PathStrokeType strokeType; void updateOutline(); diff --git a/src/gui/graphics/drawables/juce_SVGParser.cpp b/src/gui/graphics/drawables/juce_SVGParser.cpp index b0d5761144..71552478c7 100644 --- a/src/gui/graphics/drawables/juce_SVGParser.cpp +++ b/src/gui/graphics/drawables/juce_SVGParser.cpp @@ -30,7 +30,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_Drawable.h" #include "juce_DrawableComposite.h" #include "juce_DrawablePath.h" -#include "../brushes/juce_GradientBrush.h" //============================================================================== @@ -608,7 +607,7 @@ private: DrawablePath* dp = new DrawablePath(); dp->setName (xml.getStringAttribute (T("id"))); - dp->setSolidFill (Colours::transparentBlack); + dp->setFillColour (Colours::transparentBlack); path.applyTransform (transform); dp->setPath (path); @@ -625,47 +624,49 @@ private: } } - Brush* const fillBrush - = getBrushForFill (path, - getStyleAttribute (&xml, T("fill")), - getStyleAttribute (&xml, T("fill-opacity")), - getStyleAttribute (&xml, T("opacity")), - containsClosedSubPath ? Colours::black - : Colours::transparentBlack); + ColourGradient* fillGradient = 0; + const Colour fillColour (getPathFillType (path, + getStyleAttribute (&xml, T("fill")), + getStyleAttribute (&xml, T("fill-opacity")), + getStyleAttribute (&xml, T("opacity")), + containsClosedSubPath ? Colours::black + : Colours::transparentBlack, + fillGradient)); - if (fillBrush != 0) + if (fillGradient != 0) { - if (! fillBrush->isInvisible()) - { - fillBrush->applyTransform (transform); - dp->setFillBrush (*fillBrush); - } - - delete fillBrush; + fillGradient->transform = fillGradient->transform.followedBy (transform); + dp->setFillGradient (*fillGradient); + delete fillGradient; + } + else + { + dp->setFillColour (fillColour); } const String strokeType (getStyleAttribute (&xml, T("stroke"))); if (strokeType.isNotEmpty() && ! strokeType.equalsIgnoreCase (T("none"))) { - Brush* const strokeBrush - = getBrushForFill (path, strokeType, - getStyleAttribute (&xml, T("stroke-opacity")), - getStyleAttribute (&xml, T("opacity")), - Colours::transparentBlack); + ColourGradient* strokeGradient = 0; + const Colour strokeColour (getPathFillType (path, strokeType, + getStyleAttribute (&xml, T("stroke-opacity")), + getStyleAttribute (&xml, T("opacity")), + Colours::transparentBlack, + strokeGradient)); - if (strokeBrush != 0) + if (strokeGradient != 0) { - const PathStrokeType stroke (getStrokeFor (&xml)); - - if (! strokeBrush->isInvisible()) - { - strokeBrush->applyTransform (transform); - dp->setOutline (stroke, *strokeBrush); - } - - delete strokeBrush; + strokeGradient->transform = strokeGradient->transform.followedBy (transform); + dp->setStrokeGradient (*strokeGradient); + delete strokeGradient; } + else + { + dp->setStrokeColour (strokeColour); + } + + dp->setStrokeType (getStrokeFor (&xml)); } return dp; @@ -703,11 +704,12 @@ private: } } - Brush* getBrushForFill (const Path& path, - const String& fill, - const String& fillOpacity, - const String& overallOpacity, - const Colour& defaultColour) const + const Colour getPathFillType (const Path& path, + const String& fill, + const String& fillOpacity, + const String& overallOpacity, + const Colour& defaultColour, + ColourGradient*& gradient) const { float opacity = 1.0f; @@ -730,29 +732,29 @@ private: { const XmlElement* inheritedFrom = findLinkedElement (fillXml); - ColourGradient cg; + gradient = new ColourGradient(); - addGradientStopsIn (cg, inheritedFrom); - addGradientStopsIn (cg, fillXml); + addGradientStopsIn (*gradient, inheritedFrom); + addGradientStopsIn (*gradient, fillXml); - if (cg.getNumColours() > 0) + if (gradient->getNumColours() > 0) { - cg.addColour (0.0, cg.getColour (0)); - cg.addColour (1.0, cg.getColour (cg.getNumColours() - 1)); + gradient->addColour (0.0, gradient->getColour (0)); + gradient->addColour (1.0, gradient->getColour (gradient->getNumColours() - 1)); } else { - cg.addColour (0.0, Colours::black); - cg.addColour (1.0, Colours::black); + gradient->addColour (0.0, Colours::black); + gradient->addColour (1.0, Colours::black); } if (overallOpacity.isNotEmpty()) - cg.multiplyOpacity (overallOpacity.getFloatValue()); + gradient->multiplyOpacity (overallOpacity.getFloatValue()); - jassert (cg.getNumColours() > 0); + jassert (gradient->getNumColours() > 0); - cg.isRadial = fillXml->hasTagName (T("radialGradient")); - cg.transform = parseTransform (fillXml->getStringAttribute (T("gradientTransform"))); + gradient->isRadial = fillXml->hasTagName (T("radialGradient")); + gradient->transform = parseTransform (fillXml->getStringAttribute (T("gradientTransform"))); float width = viewBoxW; float height = viewBoxH; @@ -764,42 +766,44 @@ private: if (! userSpace) path.getBounds (dx, dy, width, height); - if (cg.isRadial) + if (gradient->isRadial) { - cg.x1 = dx + getCoordLength (fillXml->getStringAttribute (T("cx"), T("50%")), width); - cg.y1 = dy + getCoordLength (fillXml->getStringAttribute (T("cy"), T("50%")), height); + gradient->x1 = dx + getCoordLength (fillXml->getStringAttribute (T("cx"), T("50%")), width); + gradient->y1 = dy + getCoordLength (fillXml->getStringAttribute (T("cy"), T("50%")), height); const float radius = getCoordLength (fillXml->getStringAttribute (T("r"), T("50%")), width); - cg.x2 = cg.x1 + radius; - cg.y2 = cg.y1; + gradient->x2 = gradient->x1 + radius; + gradient->y2 = gradient->y1; //xxx (the fx, fy focal point isn't handled properly here..) } else { - cg.x1 = dx + getCoordLength (fillXml->getStringAttribute (T("x1"), T("0%")), width); - cg.y1 = dy + getCoordLength (fillXml->getStringAttribute (T("y1"), T("0%")), height); + gradient->x1 = dx + getCoordLength (fillXml->getStringAttribute (T("x1"), T("0%")), width); + gradient->y1 = dy + getCoordLength (fillXml->getStringAttribute (T("y1"), T("0%")), height); - cg.x2 = dx + getCoordLength (fillXml->getStringAttribute (T("x2"), T("100%")), width); - cg.y2 = dy + getCoordLength (fillXml->getStringAttribute (T("y2"), T("0%")), height); + gradient->x2 = dx + getCoordLength (fillXml->getStringAttribute (T("x2"), T("100%")), width); + gradient->y2 = dy + getCoordLength (fillXml->getStringAttribute (T("y2"), T("0%")), height); - if (cg.x1 == cg.x2 && cg.y1 == cg.y2) - return new SolidColourBrush (cg.getColour (cg.getNumColours() - 1)); + if (gradient->x1 == gradient->x2 && gradient->y1 == gradient->y2) + { + const Colour col (gradient->getColour (gradient->getNumColours() - 1)); + deleteAndZero (gradient); + return col; + } } - return new GradientBrush (cg); + return defaultColour; } } if (fill.equalsIgnoreCase (T("none"))) - return new SolidColourBrush (Colours::transparentBlack); + return Colours::transparentBlack; int i = 0; Colour colour (parseColour (fill, i, defaultColour)); - colour = colour.withMultipliedAlpha (opacity); - - return new SolidColourBrush (colour); + return colour.withMultipliedAlpha (opacity); } const PathStrokeType getStrokeFor (const XmlElement* const xml) const diff --git a/src/gui/graphics/imaging/juce_Image.cpp b/src/gui/graphics/imaging/juce_Image.cpp index 32aa73df66..1d4a56ca4b 100644 --- a/src/gui/graphics/imaging/juce_Image.cpp +++ b/src/gui/graphics/imaging/juce_Image.cpp @@ -31,7 +31,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_Image.h" #include "../contexts/juce_Graphics.h" #include "../contexts/juce_LowLevelGraphicsSoftwareRenderer.h" -#include "../brushes/juce_GradientBrush.h" #include "../colour/juce_PixelFormats.h" #include "../../../containers/juce_SparseSet.h" diff --git a/src/native/mac/juce_iphone_Audio.cpp b/src/native/mac/juce_iphone_Audio.cpp index 8146a7177e..be1cc64d1c 100644 --- a/src/native/mac/juce_iphone_Audio.cpp +++ b/src/native/mac/juce_iphone_Audio.cpp @@ -478,7 +478,7 @@ private: AudioChannelLayout layout; layout.mChannelBitmap = 0; layout.mNumberChannelDescriptions = 0; - layout.mChannelLayoutTag = kAudioChannelLayoutTag_StereoHeadphones; + layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input, 0, &layout, sizeof (layout)); AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output, 0, &layout, sizeof (layout));