Browse Source

tags/2021-05-28
jules 17 years ago
parent
commit
5572be0248
15 changed files with 8255 additions and 8255 deletions
  1. +3
    -3
      src/juce_appframework/audio/devices/juce_AudioDeviceManager.cpp
  2. +1
    -1
      src/juce_appframework/events/juce_Message.h
  3. +433
    -433
      src/juce_appframework/gui/components/controls/juce_Label.cpp
  4. +2
    -2
      src/juce_appframework/gui/components/controls/juce_Label.h
  5. +1368
    -1368
      src/juce_appframework/gui/components/controls/juce_Slider.cpp
  6. +2647
    -2647
      src/juce_appframework/gui/components/controls/juce_TextEditor.cpp
  7. +707
    -707
      src/juce_appframework/gui/components/controls/juce_TextEditor.h
  8. +1
    -1
      src/juce_appframework/gui/components/filebrowser/juce_FileListComponent.cpp
  9. +25
    -25
      src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp
  10. +442
    -442
      src/juce_appframework/gui/components/properties/juce_PropertyPanel.cpp
  11. +18
    -18
      src/juce_appframework/gui/components/special/juce_AudioDeviceSelectorComponent.cpp
  12. +1
    -1
      src/juce_appframework/gui/components/special/juce_AudioDeviceSelectorComponent.h
  13. +2228
    -2228
      src/juce_appframework/gui/graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp
  14. +378
    -378
      src/juce_appframework/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp
  15. +1
    -1
      src/juce_core/containers/juce_ArrayAllocationBase.h

+ 3
- 3
src/juce_appframework/audio/devices/juce_AudioDeviceManager.cpp View File

@@ -161,7 +161,7 @@ const String AudioDeviceManager::initialise (const int numInputChannelsNeeded,
if (e->getStringAttribute (T("audioDeviceName")).isNotEmpty()) if (e->getStringAttribute (T("audioDeviceName")).isNotEmpty())
{ {
setup.inputDeviceName = setup.outputDeviceName
setup.inputDeviceName = setup.outputDeviceName
= e->getStringAttribute (T("audioDeviceName")); = e->getStringAttribute (T("audioDeviceName"));
} }
else else
@@ -425,7 +425,7 @@ const String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& ne
error = currentAudioDevice->open (inputChannels, error = currentAudioDevice->open (inputChannels,
outputChannels, outputChannels,
currentSetup.sampleRate,
currentSetup.sampleRate,
currentSetup.bufferSize); currentSetup.bufferSize);
if (error.isEmpty()) if (error.isEmpty())
@@ -511,7 +511,7 @@ void AudioDeviceManager::restartLastAudioDevice()
{ {
if (currentAudioDevice == 0) if (currentAudioDevice == 0)
{ {
if (currentSetup.inputDeviceName.isEmpty()
if (currentSetup.inputDeviceName.isEmpty()
&& currentSetup.outputDeviceName.isEmpty()) && currentSetup.outputDeviceName.isEmpty())
{ {
// This method will only reload the last device that was running // This method will only reload the last device that was running


+ 1
- 1
src/juce_appframework/events/juce_Message.h View File

@@ -33,7 +33,7 @@
#define __JUCE_MESSAGE_JUCEHEADER__ #define __JUCE_MESSAGE_JUCEHEADER__
class MessageListener; class MessageListener;
class MessageManager;
//============================================================================== //==============================================================================
/** The base class for objects that can be delivered to a MessageListener. /** The base class for objects that can be delivered to a MessageListener.


+ 433
- 433
src/juce_appframework/gui/components/controls/juce_Label.cpp View File

@@ -1,433 +1,433 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../../../juce_core/basics/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#include "juce_Label.h"
#include "../LookAndFeel/juce_LookAndFeel.h"
//==============================================================================
Label::Label (const String& componentName,
const String& labelText)
: Component (componentName),
text (labelText),
font (15.0f),
justification (Justification::centredLeft),
editor (0),
listeners (2),
ownerComponent (0),
deletionWatcher (0),
horizontalBorderSize (3),
verticalBorderSize (1),
minimumHorizontalScale (0.7f),
editSingleClick (false),
editDoubleClick (false),
lossOfFocusDiscardsChanges (false)
{
setColour (TextEditor::textColourId, Colours::black);
setColour (TextEditor::backgroundColourId, Colours::transparentBlack);
setColour (TextEditor::outlineColourId, Colours::transparentBlack);
}
Label::~Label()
{
if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted())
ownerComponent->removeComponentListener (this);
deleteAndZero (deletionWatcher);
if (editor != 0)
delete editor;
}
//==============================================================================
void Label::setText (const String& newText,
const bool broadcastChangeMessage)
{
hideEditor (true);
if (text != newText)
{
text = newText;
if (broadcastChangeMessage)
triggerAsyncUpdate();
repaint();
if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted())
componentMovedOrResized (*ownerComponent, true, true);
}
}
const String Label::getText (const bool returnActiveEditorContents) const throw()
{
return (returnActiveEditorContents && isBeingEdited())
? editor->getText()
: text;
}
void Label::setFont (const Font& newFont) throw()
{
font = newFont;
repaint();
}
const Font& Label::getFont() const throw()
{
return font;
}
void Label::setEditable (const bool editOnSingleClick,
const bool editOnDoubleClick,
const bool lossOfFocusDiscardsChanges_) throw()
{
editSingleClick = editOnSingleClick;
editDoubleClick = editOnDoubleClick;
lossOfFocusDiscardsChanges = lossOfFocusDiscardsChanges_;
setWantsKeyboardFocus (editOnSingleClick || editOnDoubleClick);
setFocusContainer (editOnSingleClick || editOnDoubleClick);
}
void Label::setJustificationType (const Justification& justification_) throw()
{
justification = justification_;
repaint();
}
void Label::setBorderSize (int h, int v)
{
horizontalBorderSize = h;
verticalBorderSize = v;
repaint();
}
//==============================================================================
void Label::attachToComponent (Component* owner,
const bool onLeft)
{
if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted())
ownerComponent->removeComponentListener (this);
deleteAndZero (deletionWatcher);
ownerComponent = owner;
leftOfOwnerComp = onLeft;
if (ownerComponent != 0)
{
deletionWatcher = new ComponentDeletionWatcher (owner);
setVisible (owner->isVisible());
ownerComponent->addComponentListener (this);
componentParentHierarchyChanged (*ownerComponent);
componentMovedOrResized (*ownerComponent, true, true);
}
}
void Label::componentMovedOrResized (Component& component,
bool /*wasMoved*/,
bool /*wasResized*/)
{
if (leftOfOwnerComp)
{
setSize (jmin (getFont().getStringWidth (text) + 8, component.getX()),
component.getHeight());
setTopRightPosition (component.getX(), component.getY());
}
else
{
setSize (component.getWidth(),
8 + roundFloatToInt (getFont().getHeight()));
setTopLeftPosition (component.getX(), component.getY() - getHeight());
}
}
void Label::componentParentHierarchyChanged (Component& component)
{
if (component.getParentComponent() != 0)
component.getParentComponent()->addChildComponent (this);
}
void Label::componentVisibilityChanged (Component& component)
{
setVisible (component.isVisible());
}
//==============================================================================
void Label::textWasEdited()
{
}
void Label::showEditor()
{
if (editor == 0)
{
addAndMakeVisible (editor = createEditorComponent());
editor->setText (getText());
editor->addListener (this);
editor->grabKeyboardFocus();
editor->setHighlightedRegion (0, text.length());
editor->addListener (this);
resized();
repaint();
enterModalState();
editor->grabKeyboardFocus();
}
}
bool Label::updateFromTextEditorContents()
{
jassert (editor != 0);
const String newText (editor->getText());
if (text != newText)
{
text = newText;
triggerAsyncUpdate();
repaint();
if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted())
componentMovedOrResized (*ownerComponent, true, true);
return true;
}
return false;
}
void Label::hideEditor (const bool discardCurrentEditorContents)
{
if (editor != 0)
{
const bool changed = (! discardCurrentEditorContents)
&& updateFromTextEditorContents();
deleteAndZero (editor);
repaint();
if (changed)
textWasEdited();
exitModalState (0);
}
}
void Label::inputAttemptWhenModal()
{
if (editor != 0)
{
if (lossOfFocusDiscardsChanges)
textEditorEscapeKeyPressed (*editor);
else
textEditorReturnKeyPressed (*editor);
}
}
bool Label::isBeingEdited() const throw()
{
return editor != 0;
}
TextEditor* Label::createEditorComponent()
{
TextEditor* const ed = new TextEditor (getName());
ed->setFont (font);
// copy these colours from our own settings..
const int cols[] = { TextEditor::backgroundColourId,
TextEditor::textColourId,
TextEditor::highlightColourId,
TextEditor::highlightedTextColourId,
TextEditor::caretColourId,
TextEditor::outlineColourId,
TextEditor::focusedOutlineColourId,
TextEditor::shadowColourId };
for (int i = 0; i < numElementsInArray (cols); ++i)
ed->setColour (cols[i], findColour (cols[i]));
return ed;
}
//==============================================================================
void Label::paint (Graphics& g)
{
getLookAndFeel().drawLabel (g, *this);
}
void Label::mouseUp (const MouseEvent& e)
{
if (editSingleClick
&& e.mouseWasClicked()
&& contains (e.x, e.y)
&& ! e.mods.isPopupMenu())
{
showEditor();
}
}
void Label::mouseDoubleClick (const MouseEvent& e)
{
if (editDoubleClick && ! e.mods.isPopupMenu())
showEditor();
}
void Label::resized()
{
if (editor != 0)
editor->setBoundsInset (BorderSize (0));
}
void Label::focusGained (FocusChangeType cause)
{
if (editSingleClick && cause == focusChangedByTabKey)
showEditor();
}
void Label::enablementChanged()
{
repaint();
}
void Label::colourChanged()
{
repaint();
}
//==============================================================================
// We'll use a custom focus traverser here to make sure focus goes from the
// text editor to another component rather than back to the label itself.
class LabelKeyboardFocusTraverser : public KeyboardFocusTraverser
{
public:
LabelKeyboardFocusTraverser() {}
Component* getNextComponent (Component* current)
{
return KeyboardFocusTraverser::getNextComponent (dynamic_cast <TextEditor*> (current) != 0
? current->getParentComponent() : current);
}
Component* getPreviousComponent (Component* current)
{
return KeyboardFocusTraverser::getPreviousComponent (dynamic_cast <TextEditor*> (current) != 0
? current->getParentComponent() : current);
}
};
KeyboardFocusTraverser* Label::createFocusTraverser()
{
return new LabelKeyboardFocusTraverser();
}
//==============================================================================
void Label::addListener (LabelListener* const listener) throw()
{
jassert (listener != 0);
if (listener != 0)
listeners.add (listener);
}
void Label::removeListener (LabelListener* const listener) throw()
{
listeners.removeValue (listener);
}
void Label::handleAsyncUpdate()
{
for (int i = listeners.size(); --i >= 0;)
{
((LabelListener*) listeners.getUnchecked (i))->labelTextChanged (this);
i = jmin (i, listeners.size());
}
}
//==============================================================================
void Label::textEditorTextChanged (TextEditor& ed)
{
if (editor != 0)
{
jassert (&ed == editor);
if (! (hasKeyboardFocus (true) || isCurrentlyBlockedByAnotherModalComponent()))
{
if (lossOfFocusDiscardsChanges)
textEditorEscapeKeyPressed (ed);
else
textEditorReturnKeyPressed (ed);
}
}
}
void Label::textEditorReturnKeyPressed (TextEditor& ed)
{
if (editor != 0)
{
jassert (&ed == editor);
(void) ed;
const bool changed = updateFromTextEditorContents();
hideEditor (true);
if (changed)
textWasEdited();
}
}
void Label::textEditorEscapeKeyPressed (TextEditor& ed)
{
if (editor != 0)
{
jassert (&ed == editor);
(void) ed;
editor->setText (text, false);
hideEditor (true);
}
}
void Label::textEditorFocusLost (TextEditor& ed)
{
textEditorTextChanged (ed);
}
END_JUCE_NAMESPACE
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../../../juce_core/basics/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#include "juce_Label.h"
#include "../LookAndFeel/juce_LookAndFeel.h"
//==============================================================================
Label::Label (const String& componentName,
const String& labelText)
: Component (componentName),
text (labelText),
font (15.0f),
justification (Justification::centredLeft),
editor (0),
listeners (2),
ownerComponent (0),
deletionWatcher (0),
horizontalBorderSize (3),
verticalBorderSize (1),
minimumHorizontalScale (0.7f),
editSingleClick (false),
editDoubleClick (false),
lossOfFocusDiscardsChanges (false)
{
setColour (TextEditor::textColourId, Colours::black);
setColour (TextEditor::backgroundColourId, Colours::transparentBlack);
setColour (TextEditor::outlineColourId, Colours::transparentBlack);
}
Label::~Label()
{
if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted())
ownerComponent->removeComponentListener (this);
deleteAndZero (deletionWatcher);
if (editor != 0)
delete editor;
}
//==============================================================================
void Label::setText (const String& newText,
const bool broadcastChangeMessage)
{
hideEditor (true);
if (text != newText)
{
text = newText;
if (broadcastChangeMessage)
triggerAsyncUpdate();
repaint();
if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted())
componentMovedOrResized (*ownerComponent, true, true);
}
}
const String Label::getText (const bool returnActiveEditorContents) const throw()
{
return (returnActiveEditorContents && isBeingEdited())
? editor->getText()
: text;
}
void Label::setFont (const Font& newFont) throw()
{
font = newFont;
repaint();
}
const Font& Label::getFont() const throw()
{
return font;
}
void Label::setEditable (const bool editOnSingleClick,
const bool editOnDoubleClick,
const bool lossOfFocusDiscardsChanges_) throw()
{
editSingleClick = editOnSingleClick;
editDoubleClick = editOnDoubleClick;
lossOfFocusDiscardsChanges = lossOfFocusDiscardsChanges_;
setWantsKeyboardFocus (editOnSingleClick || editOnDoubleClick);
setFocusContainer (editOnSingleClick || editOnDoubleClick);
}
void Label::setJustificationType (const Justification& justification_) throw()
{
justification = justification_;
repaint();
}
void Label::setBorderSize (int h, int v)
{
horizontalBorderSize = h;
verticalBorderSize = v;
repaint();
}
//==============================================================================
void Label::attachToComponent (Component* owner,
const bool onLeft)
{
if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted())
ownerComponent->removeComponentListener (this);
deleteAndZero (deletionWatcher);
ownerComponent = owner;
leftOfOwnerComp = onLeft;
if (ownerComponent != 0)
{
deletionWatcher = new ComponentDeletionWatcher (owner);
setVisible (owner->isVisible());
ownerComponent->addComponentListener (this);
componentParentHierarchyChanged (*ownerComponent);
componentMovedOrResized (*ownerComponent, true, true);
}
}
void Label::componentMovedOrResized (Component& component,
bool /*wasMoved*/,
bool /*wasResized*/)
{
if (leftOfOwnerComp)
{
setSize (jmin (getFont().getStringWidth (text) + 8, component.getX()),
component.getHeight());
setTopRightPosition (component.getX(), component.getY());
}
else
{
setSize (component.getWidth(),
8 + roundFloatToInt (getFont().getHeight()));
setTopLeftPosition (component.getX(), component.getY() - getHeight());
}
}
void Label::componentParentHierarchyChanged (Component& component)
{
if (component.getParentComponent() != 0)
component.getParentComponent()->addChildComponent (this);
}
void Label::componentVisibilityChanged (Component& component)
{
setVisible (component.isVisible());
}
//==============================================================================
void Label::textWasEdited()
{
}
void Label::showEditor()
{
if (editor == 0)
{
addAndMakeVisible (editor = createEditorComponent());
editor->setText (getText());
editor->addListener (this);
editor->grabKeyboardFocus();
editor->setHighlightedRegion (0, text.length());
editor->addListener (this);
resized();
repaint();
enterModalState();
editor->grabKeyboardFocus();
}
}
bool Label::updateFromTextEditorContents()
{
jassert (editor != 0);
const String newText (editor->getText());
if (text != newText)
{
text = newText;
triggerAsyncUpdate();
repaint();
if (ownerComponent != 0 && ! deletionWatcher->hasBeenDeleted())
componentMovedOrResized (*ownerComponent, true, true);
return true;
}
return false;
}
void Label::hideEditor (const bool discardCurrentEditorContents)
{
if (editor != 0)
{
const bool changed = (! discardCurrentEditorContents)
&& updateFromTextEditorContents();
deleteAndZero (editor);
repaint();
if (changed)
textWasEdited();
exitModalState (0);
}
}
void Label::inputAttemptWhenModal()
{
if (editor != 0)
{
if (lossOfFocusDiscardsChanges)
textEditorEscapeKeyPressed (*editor);
else
textEditorReturnKeyPressed (*editor);
}
}
bool Label::isBeingEdited() const throw()
{
return editor != 0;
}
TextEditor* Label::createEditorComponent()
{
TextEditor* const ed = new TextEditor (getName());
ed->setFont (font);
// copy these colours from our own settings..
const int cols[] = { TextEditor::backgroundColourId,
TextEditor::textColourId,
TextEditor::highlightColourId,
TextEditor::highlightedTextColourId,
TextEditor::caretColourId,
TextEditor::outlineColourId,
TextEditor::focusedOutlineColourId,
TextEditor::shadowColourId };
for (int i = 0; i < numElementsInArray (cols); ++i)
ed->setColour (cols[i], findColour (cols[i]));
return ed;
}
//==============================================================================
void Label::paint (Graphics& g)
{
getLookAndFeel().drawLabel (g, *this);
}
void Label::mouseUp (const MouseEvent& e)
{
if (editSingleClick
&& e.mouseWasClicked()
&& contains (e.x, e.y)
&& ! e.mods.isPopupMenu())
{
showEditor();
}
}
void Label::mouseDoubleClick (const MouseEvent& e)
{
if (editDoubleClick && ! e.mods.isPopupMenu())
showEditor();
}
void Label::resized()
{
if (editor != 0)
editor->setBoundsInset (BorderSize (0));
}
void Label::focusGained (FocusChangeType cause)
{
if (editSingleClick && cause == focusChangedByTabKey)
showEditor();
}
void Label::enablementChanged()
{
repaint();
}
void Label::colourChanged()
{
repaint();
}
//==============================================================================
// We'll use a custom focus traverser here to make sure focus goes from the
// text editor to another component rather than back to the label itself.
class LabelKeyboardFocusTraverser : public KeyboardFocusTraverser
{
public:
LabelKeyboardFocusTraverser() {}
Component* getNextComponent (Component* current)
{
return KeyboardFocusTraverser::getNextComponent (dynamic_cast <TextEditor*> (current) != 0
? current->getParentComponent() : current);
}
Component* getPreviousComponent (Component* current)
{
return KeyboardFocusTraverser::getPreviousComponent (dynamic_cast <TextEditor*> (current) != 0
? current->getParentComponent() : current);
}
};
KeyboardFocusTraverser* Label::createFocusTraverser()
{
return new LabelKeyboardFocusTraverser();
}
//==============================================================================
void Label::addListener (LabelListener* const listener) throw()
{
jassert (listener != 0);
if (listener != 0)
listeners.add (listener);
}
void Label::removeListener (LabelListener* const listener) throw()
{
listeners.removeValue (listener);
}
void Label::handleAsyncUpdate()
{
for (int i = listeners.size(); --i >= 0;)
{
((LabelListener*) listeners.getUnchecked (i))->labelTextChanged (this);
i = jmin (i, listeners.size());
}
}
//==============================================================================
void Label::textEditorTextChanged (TextEditor& ed)
{
if (editor != 0)
{
jassert (&ed == editor);
if (! (hasKeyboardFocus (true) || isCurrentlyBlockedByAnotherModalComponent()))
{
if (lossOfFocusDiscardsChanges)
textEditorEscapeKeyPressed (ed);
else
textEditorReturnKeyPressed (ed);
}
}
}
void Label::textEditorReturnKeyPressed (TextEditor& ed)
{
if (editor != 0)
{
jassert (&ed == editor);
(void) ed;
const bool changed = updateFromTextEditorContents();
hideEditor (true);
if (changed)
textWasEdited();
}
}
void Label::textEditorEscapeKeyPressed (TextEditor& ed)
{
if (editor != 0)
{
jassert (&ed == editor);
(void) ed;
editor->setText (text, false);
hideEditor (true);
}
}
void Label::textEditorFocusLost (TextEditor& ed)
{
textEditorTextChanged (ed);
}
END_JUCE_NAMESPACE

+ 2
- 2
src/juce_appframework/gui/components/controls/juce_Label.h View File

@@ -154,11 +154,11 @@ public:
*/ */
void setBorderSize (int horizontalBorder, int verticalBorder); void setBorderSize (int horizontalBorder, int verticalBorder);
/**
/** Returns the size of the horizontal gap being left around the text.
*/ */
int getHorizontalBorderSize() const throw() { return horizontalBorderSize; } int getHorizontalBorderSize() const throw() { return horizontalBorderSize; }
/**
/** Returns the size of the vertical gap being left around the text.
*/ */
int getVerticalBorderSize() const throw() { return verticalBorderSize; } int getVerticalBorderSize() const throw() { return verticalBorderSize; }


+ 1368
- 1368
src/juce_appframework/gui/components/controls/juce_Slider.cpp
File diff suppressed because it is too large
View File


+ 2647
- 2647
src/juce_appframework/gui/components/controls/juce_TextEditor.cpp
File diff suppressed because it is too large
View File


+ 707
- 707
src/juce_appframework/gui/components/controls/juce_TextEditor.h
File diff suppressed because it is too large
View File


+ 1
- 1
src/juce_appframework/gui/components/filebrowser/juce_FileListComponent.cpp View File

@@ -44,7 +44,7 @@ Image* juce_createIconForFile (const File& file);
//============================================================================== //==============================================================================
FileListComponent::FileListComponent (DirectoryContentsList& listToShow) FileListComponent::FileListComponent (DirectoryContentsList& listToShow)
: ListBox (String::empty, 0), : ListBox (String::empty, 0),
DirectoryContentsDisplayComponent (listToShow)
DirectoryContentsDisplayComponent (listToShow)
{ {
setModel (this); setModel (this);
fileList.addChangeListener (this); fileList.addChangeListener (this);


+ 25
- 25
src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp View File

@@ -1200,31 +1200,31 @@ void LookAndFeel::positionComboBoxText (ComboBox& box, Label& label)
//============================================================================== //==============================================================================
void LookAndFeel::drawLabel (Graphics& g, Label& label) void LookAndFeel::drawLabel (Graphics& g, Label& label)
{ {
g.fillAll (label.findColour (Label::backgroundColourId));
if (! label.isBeingEdited())
{
const float alpha = label.isEnabled() ? 1.0f : 0.5f;
g.setColour (label.findColour (Label::textColourId).withMultipliedAlpha (alpha));
g.setFont (label.getFont());
g.drawFittedText (label.getText(),
label.getHorizontalBorderSize(),
label.getVerticalBorderSize(),
label.getWidth() - 2 * label.getHorizontalBorderSize(),
label.getHeight() - 2 * label.getVerticalBorderSize(),
label.getJustificationType(),
jmax (1, (int) (label.getHeight() / label.getFont().getHeight())),
label.getMinimumHorizontalScale());
g.setColour (label.findColour (Label::outlineColourId).withMultipliedAlpha (alpha));
g.drawRect (0, 0, label.getWidth(), label.getHeight());
}
else if (label.isEnabled())
{
g.setColour (label.findColour (Label::outlineColourId));
g.drawRect (0, 0, label.getWidth(), label.getHeight());
}
g.fillAll (label.findColour (Label::backgroundColourId));
if (! label.isBeingEdited())
{
const float alpha = label.isEnabled() ? 1.0f : 0.5f;
g.setColour (label.findColour (Label::textColourId).withMultipliedAlpha (alpha));
g.setFont (label.getFont());
g.drawFittedText (label.getText(),
label.getHorizontalBorderSize(),
label.getVerticalBorderSize(),
label.getWidth() - 2 * label.getHorizontalBorderSize(),
label.getHeight() - 2 * label.getVerticalBorderSize(),
label.getJustificationType(),
jmax (1, (int) (label.getHeight() / label.getFont().getHeight())),
label.getMinimumHorizontalScale());
g.setColour (label.findColour (Label::outlineColourId).withMultipliedAlpha (alpha));
g.drawRect (0, 0, label.getWidth(), label.getHeight());
}
else if (label.isEnabled())
{
g.setColour (label.findColour (Label::outlineColourId));
g.drawRect (0, 0, label.getWidth(), label.getHeight());
}
} }
//============================================================================== //==============================================================================


+ 442
- 442
src/juce_appframework/gui/components/properties/juce_PropertyPanel.cpp View File

@@ -1,442 +1,442 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../../../juce_core/basics/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#include "juce_PropertyPanel.h"
#include "../lookandfeel/juce_LookAndFeel.h"
#include "../../../../juce_core/text/juce_LocalisedStrings.h"
//==============================================================================
class PropertyHolderComponent : public Component
{
public:
PropertyHolderComponent()
{
}
~PropertyHolderComponent()
{
deleteAllChildren();
}
void paint (Graphics&)
{
}
void updateLayout (const int width);
void refreshAll() const;
};
//==============================================================================
class PropertySectionComponent : public Component
{
public:
PropertySectionComponent (const String& sectionTitle,
const Array <PropertyComponent*>& newProperties,
const bool open)
: Component (sectionTitle),
titleHeight (sectionTitle.isNotEmpty() ? 22 : 0),
isOpen_ (open)
{
for (int i = newProperties.size(); --i >= 0;)
{
addAndMakeVisible (newProperties.getUnchecked(i));
newProperties.getUnchecked(i)->refresh();
}
}
~PropertySectionComponent()
{
deleteAllChildren();
}
void paint (Graphics& g)
{
if (titleHeight > 0)
getLookAndFeel().drawPropertyPanelSectionHeader (g, getName(), isOpen(), getWidth(), titleHeight);
}
void resized()
{
int y = titleHeight;
for (int i = getNumChildComponents(); --i >= 0;)
{
PropertyComponent* const pec = dynamic_cast <PropertyComponent*> (getChildComponent (i));
if (pec != 0)
{
const int prefH = pec->getPreferredHeight();
pec->setBounds (1, y, getWidth() - 2, prefH);
y += prefH;
}
}
}
int getPreferredHeight() const
{
int y = titleHeight;
if (isOpen())
{
for (int i = 0; i < getNumChildComponents(); ++i)
{
PropertyComponent* pec = dynamic_cast <PropertyComponent*> (getChildComponent (i));
if (pec != 0)
y += pec->getPreferredHeight();
}
}
return y;
}
void setOpen (const bool open)
{
if (isOpen_ != open)
{
isOpen_ = open;
for (int i = 0; i < getNumChildComponents(); ++i)
{
PropertyComponent* pec = dynamic_cast <PropertyComponent*> (getChildComponent (i));
if (pec != 0)
pec->setVisible (open);
}
// (unable to use the syntax findParentComponentOfClass <DragAndDropContainer> () because of a VC6 compiler bug)
PropertyPanel* const pp = findParentComponentOfClass ((PropertyPanel*) 0);
if (pp != 0)
pp->resized();
}
}
bool isOpen() const throw()
{
return isOpen_;
}
void refreshAll() const
{
for (int i = 0; i < getNumChildComponents(); ++i)
{
PropertyComponent* pec = dynamic_cast <PropertyComponent*> (getChildComponent (i));
if (pec != 0)
pec->refresh();
}
}
void mouseDown (const MouseEvent&)
{
}
void mouseUp (const MouseEvent& e)
{
if (e.getMouseDownX() < titleHeight
&& e.x < titleHeight
&& e.y < titleHeight
&& e.getNumberOfClicks() != 2)
{
setOpen (! isOpen());
}
}
void mouseDoubleClick (const MouseEvent& e)
{
if (e.y < titleHeight)
setOpen (! isOpen());
}
private:
int titleHeight;
bool isOpen_;
};
void PropertyHolderComponent::updateLayout (const int width)
{
int y = 0;
for (int i = getNumChildComponents(); --i >= 0;)
{
PropertySectionComponent* const section
= dynamic_cast <PropertySectionComponent*> (getChildComponent (i));
if (section != 0)
{
const int prefH = section->getPreferredHeight();
section->setBounds (0, y, width, prefH);
y += prefH;
}
}
setSize (width, y);
repaint();
}
void PropertyHolderComponent::refreshAll() const
{
for (int i = getNumChildComponents(); --i >= 0;)
{
PropertySectionComponent* const section
= dynamic_cast <PropertySectionComponent*> (getChildComponent (i));
if (section != 0)
section->refreshAll();
}
}
//==============================================================================
PropertyPanel::PropertyPanel()
{
messageWhenEmpty = TRANS("(nothing selected)");
addAndMakeVisible (viewport = new Viewport());
viewport->setViewedComponent (propertyHolderComponent = new PropertyHolderComponent());
viewport->setFocusContainer (true);
}
PropertyPanel::~PropertyPanel()
{
clear();
deleteAllChildren();
}
//==============================================================================
void PropertyPanel::paint (Graphics& g)
{
if (propertyHolderComponent->getNumChildComponents() == 0)
{
g.setColour (Colours::black.withAlpha (0.5f));
g.setFont (14.0f);
g.drawText (messageWhenEmpty, 0, 0, getWidth(), 30,
Justification::centred, true);
}
}
void PropertyPanel::resized()
{
viewport->setBounds (0, 0, getWidth(), getHeight());
updatePropHolderLayout();
}
//==============================================================================
void PropertyPanel::clear()
{
if (propertyHolderComponent->getNumChildComponents() > 0)
{
propertyHolderComponent->deleteAllChildren();
repaint();
}
}
void PropertyPanel::addProperties (const Array <PropertyComponent*>& newProperties)
{
if (propertyHolderComponent->getNumChildComponents() == 0)
repaint();
propertyHolderComponent->addAndMakeVisible (new PropertySectionComponent (String::empty,
newProperties,
true), 0);
updatePropHolderLayout();
}
void PropertyPanel::addSection (const String& sectionTitle,
const Array <PropertyComponent*>& newProperties,
const bool shouldBeOpen)
{
jassert (sectionTitle.isNotEmpty());
if (propertyHolderComponent->getNumChildComponents() == 0)
repaint();
propertyHolderComponent->addAndMakeVisible (new PropertySectionComponent (sectionTitle,
newProperties,
shouldBeOpen), 0);
updatePropHolderLayout();
}
void PropertyPanel::updatePropHolderLayout() const
{
const int maxWidth = viewport->getMaximumVisibleWidth();
((PropertyHolderComponent*) propertyHolderComponent)->updateLayout (maxWidth);
const int newMaxWidth = viewport->getMaximumVisibleWidth();
if (maxWidth != newMaxWidth)
{
// need to do this twice because of scrollbars changing the size, etc.
((PropertyHolderComponent*) propertyHolderComponent)->updateLayout (newMaxWidth);
}
}
void PropertyPanel::refreshAll() const
{
((PropertyHolderComponent*) propertyHolderComponent)->refreshAll();
}
//==============================================================================
const StringArray PropertyPanel::getSectionNames() const
{
StringArray s;
for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i)
{
PropertySectionComponent* const section = dynamic_cast <PropertySectionComponent*> (propertyHolderComponent->getChildComponent (i));
if (section != 0 && section->getName().isNotEmpty())
s.add (section->getName());
}
return s;
}
bool PropertyPanel::isSectionOpen (const int sectionIndex) const
{
int index = 0;
for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i)
{
PropertySectionComponent* const section = dynamic_cast <PropertySectionComponent*> (propertyHolderComponent->getChildComponent (i));
if (section != 0 && section->getName().isNotEmpty())
{
if (index == sectionIndex)
return section->isOpen();
++index;
}
}
return false;
}
void PropertyPanel::setSectionOpen (const int sectionIndex, const bool shouldBeOpen)
{
int index = 0;
for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i)
{
PropertySectionComponent* const section = dynamic_cast <PropertySectionComponent*> (propertyHolderComponent->getChildComponent (i));
if (section != 0 && section->getName().isNotEmpty())
{
if (index == sectionIndex)
{
section->setOpen (shouldBeOpen);
break;
}
++index;
}
}
}
void PropertyPanel::setSectionEnabled (const int sectionIndex, const bool shouldBeEnabled)
{
int index = 0;
for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i)
{
PropertySectionComponent* const section = dynamic_cast <PropertySectionComponent*> (propertyHolderComponent->getChildComponent (i));
if (section != 0 && section->getName().isNotEmpty())
{
if (index == sectionIndex)
{
section->setEnabled (shouldBeEnabled);
break;
}
++index;
}
}
}
//==============================================================================
XmlElement* PropertyPanel::getOpennessState() const
{
XmlElement* const xml = new XmlElement (T("PROPERTYPANELSTATE"));
const StringArray sections (getSectionNames());
for (int i = 0; i < sections.size(); ++i)
{
if (sections[i].isNotEmpty())
{
XmlElement* const e = new XmlElement (T("SECTION"));
e->setAttribute (T("name"), sections[i]);
e->setAttribute (T("open"), isSectionOpen (i) ? 1 : 0);
xml->addChildElement (e);
}
}
return xml;
}
void PropertyPanel::restoreOpennessState (const XmlElement& xml)
{
if (xml.hasTagName (T("PROPERTYPANELSTATE")))
{
const StringArray sections (getSectionNames());
forEachXmlChildElementWithTagName (xml, e, T("SECTION"))
{
setSectionOpen (sections.indexOf (e->getStringAttribute (T("name"))),
e->getBoolAttribute (T("open")));
}
}
}
//==============================================================================
void PropertyPanel::setMessageWhenEmpty (const String& newMessage)
{
if (messageWhenEmpty != newMessage)
{
messageWhenEmpty = newMessage;
repaint();
}
}
const String& PropertyPanel::getMessageWhenEmpty() const throw()
{
return messageWhenEmpty;
}
END_JUCE_NAMESPACE
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../../../juce_core/basics/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#include "juce_PropertyPanel.h"
#include "../lookandfeel/juce_LookAndFeel.h"
#include "../../../../juce_core/text/juce_LocalisedStrings.h"
//==============================================================================
class PropertyHolderComponent : public Component
{
public:
PropertyHolderComponent()
{
}
~PropertyHolderComponent()
{
deleteAllChildren();
}
void paint (Graphics&)
{
}
void updateLayout (const int width);
void refreshAll() const;
};
//==============================================================================
class PropertySectionComponent : public Component
{
public:
PropertySectionComponent (const String& sectionTitle,
const Array <PropertyComponent*>& newProperties,
const bool open)
: Component (sectionTitle),
titleHeight (sectionTitle.isNotEmpty() ? 22 : 0),
isOpen_ (open)
{
for (int i = newProperties.size(); --i >= 0;)
{
addAndMakeVisible (newProperties.getUnchecked(i));
newProperties.getUnchecked(i)->refresh();
}
}
~PropertySectionComponent()
{
deleteAllChildren();
}
void paint (Graphics& g)
{
if (titleHeight > 0)
getLookAndFeel().drawPropertyPanelSectionHeader (g, getName(), isOpen(), getWidth(), titleHeight);
}
void resized()
{
int y = titleHeight;
for (int i = getNumChildComponents(); --i >= 0;)
{
PropertyComponent* const pec = dynamic_cast <PropertyComponent*> (getChildComponent (i));
if (pec != 0)
{
const int prefH = pec->getPreferredHeight();
pec->setBounds (1, y, getWidth() - 2, prefH);
y += prefH;
}
}
}
int getPreferredHeight() const
{
int y = titleHeight;
if (isOpen())
{
for (int i = 0; i < getNumChildComponents(); ++i)
{
PropertyComponent* pec = dynamic_cast <PropertyComponent*> (getChildComponent (i));
if (pec != 0)
y += pec->getPreferredHeight();
}
}
return y;
}
void setOpen (const bool open)
{
if (isOpen_ != open)
{
isOpen_ = open;
for (int i = 0; i < getNumChildComponents(); ++i)
{
PropertyComponent* pec = dynamic_cast <PropertyComponent*> (getChildComponent (i));
if (pec != 0)
pec->setVisible (open);
}
// (unable to use the syntax findParentComponentOfClass <DragAndDropContainer> () because of a VC6 compiler bug)
PropertyPanel* const pp = findParentComponentOfClass ((PropertyPanel*) 0);
if (pp != 0)
pp->resized();
}
}
bool isOpen() const throw()
{
return isOpen_;
}
void refreshAll() const
{
for (int i = 0; i < getNumChildComponents(); ++i)
{
PropertyComponent* pec = dynamic_cast <PropertyComponent*> (getChildComponent (i));
if (pec != 0)
pec->refresh();
}
}
void mouseDown (const MouseEvent&)
{
}
void mouseUp (const MouseEvent& e)
{
if (e.getMouseDownX() < titleHeight
&& e.x < titleHeight
&& e.y < titleHeight
&& e.getNumberOfClicks() != 2)
{
setOpen (! isOpen());
}
}
void mouseDoubleClick (const MouseEvent& e)
{
if (e.y < titleHeight)
setOpen (! isOpen());
}
private:
int titleHeight;
bool isOpen_;
};
void PropertyHolderComponent::updateLayout (const int width)
{
int y = 0;
for (int i = getNumChildComponents(); --i >= 0;)
{
PropertySectionComponent* const section
= dynamic_cast <PropertySectionComponent*> (getChildComponent (i));
if (section != 0)
{
const int prefH = section->getPreferredHeight();
section->setBounds (0, y, width, prefH);
y += prefH;
}
}
setSize (width, y);
repaint();
}
void PropertyHolderComponent::refreshAll() const
{
for (int i = getNumChildComponents(); --i >= 0;)
{
PropertySectionComponent* const section
= dynamic_cast <PropertySectionComponent*> (getChildComponent (i));
if (section != 0)
section->refreshAll();
}
}
//==============================================================================
PropertyPanel::PropertyPanel()
{
messageWhenEmpty = TRANS("(nothing selected)");
addAndMakeVisible (viewport = new Viewport());
viewport->setViewedComponent (propertyHolderComponent = new PropertyHolderComponent());
viewport->setFocusContainer (true);
}
PropertyPanel::~PropertyPanel()
{
clear();
deleteAllChildren();
}
//==============================================================================
void PropertyPanel::paint (Graphics& g)
{
if (propertyHolderComponent->getNumChildComponents() == 0)
{
g.setColour (Colours::black.withAlpha (0.5f));
g.setFont (14.0f);
g.drawText (messageWhenEmpty, 0, 0, getWidth(), 30,
Justification::centred, true);
}
}
void PropertyPanel::resized()
{
viewport->setBounds (0, 0, getWidth(), getHeight());
updatePropHolderLayout();
}
//==============================================================================
void PropertyPanel::clear()
{
if (propertyHolderComponent->getNumChildComponents() > 0)
{
propertyHolderComponent->deleteAllChildren();
repaint();
}
}
void PropertyPanel::addProperties (const Array <PropertyComponent*>& newProperties)
{
if (propertyHolderComponent->getNumChildComponents() == 0)
repaint();
propertyHolderComponent->addAndMakeVisible (new PropertySectionComponent (String::empty,
newProperties,
true), 0);
updatePropHolderLayout();
}
void PropertyPanel::addSection (const String& sectionTitle,
const Array <PropertyComponent*>& newProperties,
const bool shouldBeOpen)
{
jassert (sectionTitle.isNotEmpty());
if (propertyHolderComponent->getNumChildComponents() == 0)
repaint();
propertyHolderComponent->addAndMakeVisible (new PropertySectionComponent (sectionTitle,
newProperties,
shouldBeOpen), 0);
updatePropHolderLayout();
}
void PropertyPanel::updatePropHolderLayout() const
{
const int maxWidth = viewport->getMaximumVisibleWidth();
((PropertyHolderComponent*) propertyHolderComponent)->updateLayout (maxWidth);
const int newMaxWidth = viewport->getMaximumVisibleWidth();
if (maxWidth != newMaxWidth)
{
// need to do this twice because of scrollbars changing the size, etc.
((PropertyHolderComponent*) propertyHolderComponent)->updateLayout (newMaxWidth);
}
}
void PropertyPanel::refreshAll() const
{
((PropertyHolderComponent*) propertyHolderComponent)->refreshAll();
}
//==============================================================================
const StringArray PropertyPanel::getSectionNames() const
{
StringArray s;
for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i)
{
PropertySectionComponent* const section = dynamic_cast <PropertySectionComponent*> (propertyHolderComponent->getChildComponent (i));
if (section != 0 && section->getName().isNotEmpty())
s.add (section->getName());
}
return s;
}
bool PropertyPanel::isSectionOpen (const int sectionIndex) const
{
int index = 0;
for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i)
{
PropertySectionComponent* const section = dynamic_cast <PropertySectionComponent*> (propertyHolderComponent->getChildComponent (i));
if (section != 0 && section->getName().isNotEmpty())
{
if (index == sectionIndex)
return section->isOpen();
++index;
}
}
return false;
}
void PropertyPanel::setSectionOpen (const int sectionIndex, const bool shouldBeOpen)
{
int index = 0;
for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i)
{
PropertySectionComponent* const section = dynamic_cast <PropertySectionComponent*> (propertyHolderComponent->getChildComponent (i));
if (section != 0 && section->getName().isNotEmpty())
{
if (index == sectionIndex)
{
section->setOpen (shouldBeOpen);
break;
}
++index;
}
}
}
void PropertyPanel::setSectionEnabled (const int sectionIndex, const bool shouldBeEnabled)
{
int index = 0;
for (int i = 0; i < propertyHolderComponent->getNumChildComponents(); ++i)
{
PropertySectionComponent* const section = dynamic_cast <PropertySectionComponent*> (propertyHolderComponent->getChildComponent (i));
if (section != 0 && section->getName().isNotEmpty())
{
if (index == sectionIndex)
{
section->setEnabled (shouldBeEnabled);
break;
}
++index;
}
}
}
//==============================================================================
XmlElement* PropertyPanel::getOpennessState() const
{
XmlElement* const xml = new XmlElement (T("PROPERTYPANELSTATE"));
const StringArray sections (getSectionNames());
for (int i = 0; i < sections.size(); ++i)
{
if (sections[i].isNotEmpty())
{
XmlElement* const e = new XmlElement (T("SECTION"));
e->setAttribute (T("name"), sections[i]);
e->setAttribute (T("open"), isSectionOpen (i) ? 1 : 0);
xml->addChildElement (e);
}
}
return xml;
}
void PropertyPanel::restoreOpennessState (const XmlElement& xml)
{
if (xml.hasTagName (T("PROPERTYPANELSTATE")))
{
const StringArray sections (getSectionNames());
forEachXmlChildElementWithTagName (xml, e, T("SECTION"))
{
setSectionOpen (sections.indexOf (e->getStringAttribute (T("name"))),
e->getBoolAttribute (T("open")));
}
}
}
//==============================================================================
void PropertyPanel::setMessageWhenEmpty (const String& newMessage)
{
if (messageWhenEmpty != newMessage)
{
messageWhenEmpty = newMessage;
repaint();
}
}
const String& PropertyPanel::getMessageWhenEmpty() const throw()
{
return messageWhenEmpty;
}
END_JUCE_NAMESPACE

+ 18
- 18
src/juce_appframework/gui/components/special/juce_AudioDeviceSelectorComponent.cpp View File

@@ -42,7 +42,7 @@ BEGIN_JUCE_NAMESPACE
//============================================================================== //==============================================================================
class SimpleDeviceManagerInputLevelMeter : public Component,
class SimpleDeviceManagerInputLevelMeter : public Component,
public Timer public Timer
{ {
public: public:
@@ -214,7 +214,7 @@ class AudioDeviceSettingsPanel : public Component,
public ButtonListener public ButtonListener
{ {
public: public:
AudioDeviceSettingsPanel (AudioIODeviceType* type_,
AudioDeviceSettingsPanel (AudioIODeviceType* type_,
AudioIODeviceType::DeviceSetupDetails& setup_, AudioIODeviceType::DeviceSetupDetails& setup_,
const bool hideAdvancedOptionsWithButton) const bool hideAdvancedOptionsWithButton)
: type (type_), : type (type_),
@@ -279,7 +279,7 @@ public:
outputDeviceDropDown->setBounds (lx, y, w, h); outputDeviceDropDown->setBounds (lx, y, w, h);
if (testButton != 0) if (testButton != 0)
testButton->setBounds (proportionOfWidth (0.77f),
testButton->setBounds (proportionOfWidth (0.77f),
outputDeviceDropDown->getY(), outputDeviceDropDown->getY(),
proportionOfWidth (0.18f), proportionOfWidth (0.18f),
h); h);
@@ -290,7 +290,7 @@ public:
{ {
inputDeviceDropDown->setBounds (lx, y, w, h); inputDeviceDropDown->setBounds (lx, y, w, h);
inputLevelMeter->setBounds (proportionOfWidth (0.77f),
inputLevelMeter->setBounds (proportionOfWidth (0.77f),
inputDeviceDropDown->getY(), inputDeviceDropDown->getY(),
proportionOfWidth (0.18f), proportionOfWidth (0.18f),
h); h);
@@ -323,7 +323,7 @@ public:
if (sampleRateDropDown != 0) if (sampleRateDropDown != 0)
{ {
sampleRateDropDown->setVisible (showAdvancedSettingsButton == 0
sampleRateDropDown->setVisible (showAdvancedSettingsButton == 0
|| ! showAdvancedSettingsButton->isVisible()); || ! showAdvancedSettingsButton->isVisible());
sampleRateDropDown->setBounds (lx, y, w, h); sampleRateDropDown->setBounds (lx, y, w, h);
@@ -360,11 +360,11 @@ public:
|| comboBoxThatHasChanged == inputDeviceDropDown) || comboBoxThatHasChanged == inputDeviceDropDown)
{ {
if (outputDeviceDropDown != 0) if (outputDeviceDropDown != 0)
config.outputDeviceName = outputDeviceDropDown->getSelectedId() < 0 ? String::empty
config.outputDeviceName = outputDeviceDropDown->getSelectedId() < 0 ? String::empty
: outputDeviceDropDown->getText(); : outputDeviceDropDown->getText();
if (inputDeviceDropDown != 0) if (inputDeviceDropDown != 0)
config.inputDeviceName = inputDeviceDropDown->getSelectedId() < 0 ? String::empty
config.inputDeviceName = inputDeviceDropDown->getSelectedId() < 0 ? String::empty
: inputDeviceDropDown->getText(); : inputDeviceDropDown->getText();
if (! type->hasSeparateInputsAndOutputs()) if (! type->hasSeparateInputsAndOutputs())
@@ -460,7 +460,7 @@ public:
outputDeviceDropDown->addListener (this); outputDeviceDropDown->addListener (this);
addAndMakeVisible (outputDeviceDropDown); addAndMakeVisible (outputDeviceDropDown);
outputDeviceLabel = new Label (String::empty,
outputDeviceLabel = new Label (String::empty,
type->hasSeparateInputsAndOutputs() ? TRANS ("output:") type->hasSeparateInputsAndOutputs() ? TRANS ("output:")
: TRANS ("device:")); : TRANS ("device:"));
outputDeviceLabel->attachToComponent (outputDeviceDropDown, true); outputDeviceLabel->attachToComponent (outputDeviceDropDown, true);
@@ -486,7 +486,7 @@ public:
inputDeviceLabel = new Label (String::empty, TRANS ("input:")); inputDeviceLabel = new Label (String::empty, TRANS ("input:"));
inputDeviceLabel->attachToComponent (inputDeviceDropDown, true); inputDeviceLabel->attachToComponent (inputDeviceDropDown, true);
addAndMakeVisible (inputLevelMeter
addAndMakeVisible (inputLevelMeter
= new SimpleDeviceManagerInputLevelMeter (setup.manager)); = new SimpleDeviceManagerInputLevelMeter (setup.manager));
} }
@@ -499,13 +499,13 @@ public:
if (currentDevice != 0) if (currentDevice != 0)
{ {
if (setup.maxNumOutputChannels > 0
if (setup.maxNumOutputChannels > 0
&& setup.minNumOutputChannels < setup.manager->getCurrentAudioDevice()->getOutputChannelNames().size()) && setup.minNumOutputChannels < setup.manager->getCurrentAudioDevice()->getOutputChannelNames().size())
{ {
if (outputChanList == 0) if (outputChanList == 0)
{ {
addAndMakeVisible (outputChanList
= new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioOutputType,
addAndMakeVisible (outputChanList
= new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioOutputType,
TRANS ("(no audio output channels found)"))); TRANS ("(no audio output channels found)")));
outputChanLabel = new Label (String::empty, TRANS ("active output channels:")); outputChanLabel = new Label (String::empty, TRANS ("active output channels:"));
outputChanLabel->attachToComponent (outputChanList, true); outputChanLabel->attachToComponent (outputChanList, true);
@@ -525,7 +525,7 @@ public:
if (inputChanList == 0) if (inputChanList == 0)
{ {
addAndMakeVisible (inputChanList addAndMakeVisible (inputChanList
= new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioInputType,
= new ChannelSelectorListBox (setup, ChannelSelectorListBox::audioInputType,
TRANS ("(no audio input channels found)"))); TRANS ("(no audio input channels found)")));
inputChanLabel = new Label (String::empty, TRANS ("active input channels:")); inputChanLabel = new Label (String::empty, TRANS ("active input channels:"));
inputChanLabel->attachToComponent (inputChanList, true); inputChanLabel->attachToComponent (inputChanList, true);
@@ -832,7 +832,7 @@ private:
int getBestHeight (int maxHeight) int getBestHeight (int maxHeight)
{ {
return getRowHeight() * jlimit (2, jmax (2, maxHeight / getRowHeight()),
return getRowHeight() * jlimit (2, jmax (2, maxHeight / getRowHeight()),
getNumRows()) getNumRows())
+ getOutlineThickness() * 2; + getOutlineThickness() * 2;
} }
@@ -974,7 +974,7 @@ AudioDeviceSelectorComponent::AudioDeviceSelectorComponent (AudioDeviceManager&
for (int i = 0; i < deviceManager_.getAvailableDeviceTypes().size(); ++i) for (int i = 0; i < deviceManager_.getAvailableDeviceTypes().size(); ++i)
{ {
deviceTypeDropDown deviceTypeDropDown
->addItem (deviceManager_.getAvailableDeviceTypes().getUnchecked(i)->getTypeName(),
->addItem (deviceManager_.getAvailableDeviceTypes().getUnchecked(i)->getTypeName(),
i + 1); i + 1);
} }
@@ -1100,15 +1100,15 @@ void AudioDeviceSelectorComponent::changeListenerCallback (void*)
deviceTypeDropDown->setText (deviceManager.getCurrentAudioDeviceType(), false); deviceTypeDropDown->setText (deviceManager.getCurrentAudioDeviceType(), false);
} }
if (audioDeviceSettingsComp == 0
if (audioDeviceSettingsComp == 0
|| audioDeviceSettingsCompType != deviceManager.getCurrentAudioDeviceType()) || audioDeviceSettingsCompType != deviceManager.getCurrentAudioDeviceType())
{ {
audioDeviceSettingsCompType = deviceManager.getCurrentAudioDeviceType(); audioDeviceSettingsCompType = deviceManager.getCurrentAudioDeviceType();
deleteAndZero (audioDeviceSettingsComp); deleteAndZero (audioDeviceSettingsComp);
AudioIODeviceType* const type
= deviceManager.getAvailableDeviceTypes() [deviceTypeDropDown == 0
AudioIODeviceType* const type
= deviceManager.getAvailableDeviceTypes() [deviceTypeDropDown == 0
? 0 : deviceTypeDropDown->getSelectedId() - 1]; ? 0 : deviceTypeDropDown->getSelectedId() - 1];
if (type != 0) if (type != 0)


+ 1
- 1
src/juce_appframework/gui/components/special/juce_AudioDeviceSelectorComponent.h View File

@@ -66,7 +66,7 @@ public:
@param maxAudioOutputChannels the maximum number of audio output channels that the application needs @param maxAudioOutputChannels the maximum number of audio output channels that the application needs
@param showMidiInputOptions if true, the component will allow the user to select which midi inputs are enabled @param showMidiInputOptions if true, the component will allow the user to select which midi inputs are enabled
@param showMidiOutputSelector if true, the component will let the user choose a default midi output device @param showMidiOutputSelector if true, the component will let the user choose a default midi output device
@param showChannelsAsStereoPairs if true, channels will be treated as pairs; if false, channels will be
@param showChannelsAsStereoPairs if true, channels will be treated as pairs; if false, channels will be
treated as a set of separate mono channels. treated as a set of separate mono channels.
@param hideAdvancedOptionsWithButton if true, only the minimum amount of UI components @param hideAdvancedOptionsWithButton if true, only the minimum amount of UI components
are shown, with an "advanced" button that shows the rest of them are shown, with an "advanced" button that shows the rest of them


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


+ 378
- 378
src/juce_appframework/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp View File

@@ -1,378 +1,378 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../../../../juce_core/basics/juce_StandardHeader.h"
#if JUCE_MSVC
#pragma warning (push)
#endif
namespace jpeglibNamespace
{
extern "C"
{
#define JPEG_INTERNALS
#undef FAR
#include "jpglib/jpeglib.h"
#include "jpglib/jcapimin.c"
#include "jpglib/jcapistd.c"
#include "jpglib/jccoefct.c"
#include "jpglib/jccolor.c"
#undef FIX
#include "jpglib/jcdctmgr.c"
#undef CONST_BITS
#include "jpglib/jchuff.c"
#undef emit_byte
#include "jpglib/jcinit.c"
#include "jpglib/jcmainct.c"
#include "jpglib/jcmarker.c"
#include "jpglib/jcmaster.c"
#include "jpglib/jcomapi.c"
#include "jpglib/jcparam.c"
#include "jpglib/jcphuff.c"
#include "jpglib/jcprepct.c"
#include "jpglib/jcsample.c"
#include "jpglib/jctrans.c"
#include "jpglib/jdapistd.c"
#include "jpglib/jdapimin.c"
#include "jpglib/jdatasrc.c"
#include "jpglib/jdcoefct.c"
#undef FIX
#include "jpglib/jdcolor.c"
#undef FIX
#include "jpglib/jddctmgr.c"
#undef CONST_BITS
#undef ASSIGN_STATE
#include "jpglib/jdhuff.c"
#include "jpglib/jdinput.c"
#include "jpglib/jdmainct.c"
#include "jpglib/jdmarker.c"
#include "jpglib/jdmaster.c"
#undef FIX
#include "jpglib/jdmerge.c"
#undef ASSIGN_STATE
#include "jpglib/jdphuff.c"
#include "jpglib/jdpostct.c"
#undef FIX
#include "jpglib/jdsample.c"
#include "jpglib/jdtrans.c"
#include "jpglib/jfdctflt.c"
#include "jpglib/jfdctint.c"
#undef CONST_BITS
#undef MULTIPLY
#undef FIX_0_541196100
#include "jpglib/jfdctfst.c"
#undef FIX_0_541196100
#include "jpglib/jidctflt.c"
#undef CONST_BITS
#undef FIX_1_847759065
#undef MULTIPLY
#undef DEQUANTIZE
#undef DESCALE
#include "jpglib/jidctfst.c"
#undef CONST_BITS
#undef FIX_1_847759065
#undef MULTIPLY
#undef DEQUANTIZE
#include "jpglib/jidctint.c"
#include "jpglib/jidctred.c"
#include "jpglib/jmemmgr.c"
#include "jpglib/jmemnobs.c"
#include "jpglib/jquant1.c"
#include "jpglib/jquant2.c"
#include "jpglib/jutils.c"
#include "jpglib/transupp.c"
}
}
#if JUCE_MSVC
#pragma warning (pop)
#endif
BEGIN_JUCE_NAMESPACE
#include "../juce_Image.h"
#include "../../../../../juce_core/io/juce_InputStream.h"
#include "../../../../../juce_core/io/juce_OutputStream.h"
#include "../../colour/juce_PixelFormats.h"
using namespace jpeglibNamespace;
//==============================================================================
struct JPEGDecodingFailure {};
static void fatalErrorHandler (j_common_ptr)
{
throw JPEGDecodingFailure();
}
static void silentErrorCallback1 (j_common_ptr) {}
static void silentErrorCallback2 (j_common_ptr, int) {}
static void silentErrorCallback3 (j_common_ptr, char*) {}
static void setupSilentErrorHandler (struct jpeg_error_mgr& err)
{
zerostruct (err);
err.error_exit = fatalErrorHandler;
err.emit_message = silentErrorCallback2;
err.output_message = silentErrorCallback1;
err.format_message = silentErrorCallback3;
err.reset_error_mgr = silentErrorCallback1;
}
//==============================================================================
static void dummyCallback1 (j_decompress_ptr) throw()
{
}
static void jpegSkip (j_decompress_ptr decompStruct, long num) throw()
{
decompStruct->src->next_input_byte += num;
num = jmin (num, (int) decompStruct->src->bytes_in_buffer);
decompStruct->src->bytes_in_buffer -= num;
}
static boolean jpegFill (j_decompress_ptr) throw()
{
return 0;
}
//==============================================================================
Image* juce_loadJPEGImageFromStream (InputStream& in) throw()
{
MemoryBlock mb;
in.readIntoMemoryBlock (mb);
Image* image = 0;
if (mb.getSize() > 16)
{
struct jpeg_decompress_struct jpegDecompStruct;
struct jpeg_error_mgr jerr;
setupSilentErrorHandler (jerr);
jpegDecompStruct.err = &jerr;
jpeg_create_decompress (&jpegDecompStruct);
jpegDecompStruct.src = (jpeg_source_mgr*)(jpegDecompStruct.mem->alloc_small)
((j_common_ptr)(&jpegDecompStruct), JPOOL_PERMANENT, sizeof (jpeg_source_mgr));
jpegDecompStruct.src->init_source = dummyCallback1;
jpegDecompStruct.src->fill_input_buffer = jpegFill;
jpegDecompStruct.src->skip_input_data = jpegSkip;
jpegDecompStruct.src->resync_to_restart = jpeg_resync_to_restart;
jpegDecompStruct.src->term_source = dummyCallback1;
jpegDecompStruct.src->next_input_byte = (const unsigned char*) mb.getData();
jpegDecompStruct.src->bytes_in_buffer = mb.getSize();
try
{
jpeg_read_header (&jpegDecompStruct, TRUE);
jpeg_calc_output_dimensions (&jpegDecompStruct);
const int width = jpegDecompStruct.output_width;
const int height = jpegDecompStruct.output_height;
jpegDecompStruct.out_color_space = JCS_RGB;
JSAMPARRAY buffer
= (*jpegDecompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegDecompStruct,
JPOOL_IMAGE,
width * 3, 1);
if (jpeg_start_decompress (&jpegDecompStruct))
{
image = new Image (Image::RGB, width, height, false);
for (int y = 0; y < height; ++y)
{
jpeg_read_scanlines (&jpegDecompStruct, buffer, 1);
int stride, pixelStride;
uint8* pixels = image->lockPixelDataReadWrite (0, y, width, 1, stride, pixelStride);
const uint8* src = *buffer;
uint8* dest = pixels;
for (int i = width; --i >= 0;)
{
((PixelRGB*) dest)->setARGB (0, src[0], src[1], src[2]);
dest += pixelStride;
src += 3;
}
image->releasePixelDataReadWrite (pixels);
}
jpeg_finish_decompress (&jpegDecompStruct);
}
jpeg_destroy_decompress (&jpegDecompStruct);
}
catch (...)
{}
in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData());
}
return image;
}
//==============================================================================
static const int bufferSize = 512;
struct JuceJpegDest : public jpeg_destination_mgr
{
OutputStream* output;
char* buffer;
};
static void jpegWriteInit (j_compress_ptr) throw()
{
}
static void jpegWriteTerminate (j_compress_ptr cinfo) throw()
{
JuceJpegDest* const dest = (JuceJpegDest*) cinfo->dest;
const int numToWrite = bufferSize - dest->free_in_buffer;
dest->output->write (dest->buffer, numToWrite);
}
static boolean jpegWriteFlush (j_compress_ptr cinfo) throw()
{
JuceJpegDest* const dest = (JuceJpegDest*) cinfo->dest;
const int numToWrite = bufferSize;
dest->next_output_byte = (JOCTET*) dest->buffer;
dest->free_in_buffer = bufferSize;
return dest->output->write (dest->buffer, numToWrite);
}
//==============================================================================
bool juce_writeJPEGImageToStream (const Image& image,
OutputStream& out,
float quality) throw()
{
if (image.hasAlphaChannel())
{
// this method could fill the background in white and still save the image..
jassertfalse
return true;
}
struct jpeg_compress_struct jpegCompStruct;
struct jpeg_error_mgr jerr;
setupSilentErrorHandler (jerr);
jpegCompStruct.err = &jerr;
jpeg_create_compress (&jpegCompStruct);
JuceJpegDest dest;
jpegCompStruct.dest = &dest;
dest.output = &out;
dest.buffer = (char*) juce_malloc (bufferSize);
dest.next_output_byte = (JOCTET*) dest.buffer;
dest.free_in_buffer = bufferSize;
dest.init_destination = jpegWriteInit;
dest.empty_output_buffer = jpegWriteFlush;
dest.term_destination = jpegWriteTerminate;
jpegCompStruct.image_width = image.getWidth();
jpegCompStruct.image_height = image.getHeight();
jpegCompStruct.input_components = 3;
jpegCompStruct.in_color_space = JCS_RGB;
jpegCompStruct.write_JFIF_header = 1;
jpegCompStruct.X_density = 72;
jpegCompStruct.Y_density = 72;
jpeg_set_defaults (&jpegCompStruct);
jpegCompStruct.dct_method = JDCT_FLOAT;
jpegCompStruct.optimize_coding = 1;
// jpegCompStruct.smoothing_factor = 10;
if (quality < 0.0f)
quality = 0.85f;
jpeg_set_quality (&jpegCompStruct, jlimit (0, 100, roundFloatToInt (quality * 100.0f)), TRUE);
jpeg_start_compress (&jpegCompStruct, TRUE);
const int strideBytes = jpegCompStruct.image_width * jpegCompStruct.input_components;
JSAMPARRAY buffer = (*jpegCompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegCompStruct,
JPOOL_IMAGE,
strideBytes, 1);
while (jpegCompStruct.next_scanline < jpegCompStruct.image_height)
{
int stride, pixelStride;
const uint8* pixels = image.lockPixelDataReadOnly (0, jpegCompStruct.next_scanline, jpegCompStruct.image_width, 1, stride, pixelStride);
const uint8* src = pixels;
uint8* dst = *buffer;
for (int i = jpegCompStruct.image_width; --i >= 0;)
{
*dst++ = ((const PixelRGB*) src)->getRed();
*dst++ = ((const PixelRGB*) src)->getGreen();
*dst++ = ((const PixelRGB*) src)->getBlue();
src += pixelStride;
}
jpeg_write_scanlines (&jpegCompStruct, buffer, 1);
image.releasePixelDataReadOnly (pixels);
}
jpeg_finish_compress (&jpegCompStruct);
jpeg_destroy_compress (&jpegCompStruct);
juce_free (dest.buffer);
out.flush();
return true;
}
END_JUCE_NAMESPACE
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../../../../juce_core/basics/juce_StandardHeader.h"
#if JUCE_MSVC
#pragma warning (push)
#endif
namespace jpeglibNamespace
{
extern "C"
{
#define JPEG_INTERNALS
#undef FAR
#include "jpglib/jpeglib.h"
#include "jpglib/jcapimin.c"
#include "jpglib/jcapistd.c"
#include "jpglib/jccoefct.c"
#include "jpglib/jccolor.c"
#undef FIX
#include "jpglib/jcdctmgr.c"
#undef CONST_BITS
#include "jpglib/jchuff.c"
#undef emit_byte
#include "jpglib/jcinit.c"
#include "jpglib/jcmainct.c"
#include "jpglib/jcmarker.c"
#include "jpglib/jcmaster.c"
#include "jpglib/jcomapi.c"
#include "jpglib/jcparam.c"
#include "jpglib/jcphuff.c"
#include "jpglib/jcprepct.c"
#include "jpglib/jcsample.c"
#include "jpglib/jctrans.c"
#include "jpglib/jdapistd.c"
#include "jpglib/jdapimin.c"
#include "jpglib/jdatasrc.c"
#include "jpglib/jdcoefct.c"
#undef FIX
#include "jpglib/jdcolor.c"
#undef FIX
#include "jpglib/jddctmgr.c"
#undef CONST_BITS
#undef ASSIGN_STATE
#include "jpglib/jdhuff.c"
#include "jpglib/jdinput.c"
#include "jpglib/jdmainct.c"
#include "jpglib/jdmarker.c"
#include "jpglib/jdmaster.c"
#undef FIX
#include "jpglib/jdmerge.c"
#undef ASSIGN_STATE
#include "jpglib/jdphuff.c"
#include "jpglib/jdpostct.c"
#undef FIX
#include "jpglib/jdsample.c"
#include "jpglib/jdtrans.c"
#include "jpglib/jfdctflt.c"
#include "jpglib/jfdctint.c"
#undef CONST_BITS
#undef MULTIPLY
#undef FIX_0_541196100
#include "jpglib/jfdctfst.c"
#undef FIX_0_541196100
#include "jpglib/jidctflt.c"
#undef CONST_BITS
#undef FIX_1_847759065
#undef MULTIPLY
#undef DEQUANTIZE
#undef DESCALE
#include "jpglib/jidctfst.c"
#undef CONST_BITS
#undef FIX_1_847759065
#undef MULTIPLY
#undef DEQUANTIZE
#include "jpglib/jidctint.c"
#include "jpglib/jidctred.c"
#include "jpglib/jmemmgr.c"
#include "jpglib/jmemnobs.c"
#include "jpglib/jquant1.c"
#include "jpglib/jquant2.c"
#include "jpglib/jutils.c"
#include "jpglib/transupp.c"
}
}
#if JUCE_MSVC
#pragma warning (pop)
#endif
BEGIN_JUCE_NAMESPACE
#include "../juce_Image.h"
#include "../../../../../juce_core/io/juce_InputStream.h"
#include "../../../../../juce_core/io/juce_OutputStream.h"
#include "../../colour/juce_PixelFormats.h"
using namespace jpeglibNamespace;
//==============================================================================
struct JPEGDecodingFailure {};
static void fatalErrorHandler (j_common_ptr)
{
throw JPEGDecodingFailure();
}
static void silentErrorCallback1 (j_common_ptr) {}
static void silentErrorCallback2 (j_common_ptr, int) {}
static void silentErrorCallback3 (j_common_ptr, char*) {}
static void setupSilentErrorHandler (struct jpeg_error_mgr& err)
{
zerostruct (err);
err.error_exit = fatalErrorHandler;
err.emit_message = silentErrorCallback2;
err.output_message = silentErrorCallback1;
err.format_message = silentErrorCallback3;
err.reset_error_mgr = silentErrorCallback1;
}
//==============================================================================
static void dummyCallback1 (j_decompress_ptr) throw()
{
}
static void jpegSkip (j_decompress_ptr decompStruct, long num) throw()
{
decompStruct->src->next_input_byte += num;
num = jmin (num, (int) decompStruct->src->bytes_in_buffer);
decompStruct->src->bytes_in_buffer -= num;
}
static boolean jpegFill (j_decompress_ptr) throw()
{
return 0;
}
//==============================================================================
Image* juce_loadJPEGImageFromStream (InputStream& in) throw()
{
MemoryBlock mb;
in.readIntoMemoryBlock (mb);
Image* image = 0;
if (mb.getSize() > 16)
{
struct jpeg_decompress_struct jpegDecompStruct;
struct jpeg_error_mgr jerr;
setupSilentErrorHandler (jerr);
jpegDecompStruct.err = &jerr;
jpeg_create_decompress (&jpegDecompStruct);
jpegDecompStruct.src = (jpeg_source_mgr*)(jpegDecompStruct.mem->alloc_small)
((j_common_ptr)(&jpegDecompStruct), JPOOL_PERMANENT, sizeof (jpeg_source_mgr));
jpegDecompStruct.src->init_source = dummyCallback1;
jpegDecompStruct.src->fill_input_buffer = jpegFill;
jpegDecompStruct.src->skip_input_data = jpegSkip;
jpegDecompStruct.src->resync_to_restart = jpeg_resync_to_restart;
jpegDecompStruct.src->term_source = dummyCallback1;
jpegDecompStruct.src->next_input_byte = (const unsigned char*) mb.getData();
jpegDecompStruct.src->bytes_in_buffer = mb.getSize();
try
{
jpeg_read_header (&jpegDecompStruct, TRUE);
jpeg_calc_output_dimensions (&jpegDecompStruct);
const int width = jpegDecompStruct.output_width;
const int height = jpegDecompStruct.output_height;
jpegDecompStruct.out_color_space = JCS_RGB;
JSAMPARRAY buffer
= (*jpegDecompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegDecompStruct,
JPOOL_IMAGE,
width * 3, 1);
if (jpeg_start_decompress (&jpegDecompStruct))
{
image = new Image (Image::RGB, width, height, false);
for (int y = 0; y < height; ++y)
{
jpeg_read_scanlines (&jpegDecompStruct, buffer, 1);
int stride, pixelStride;
uint8* pixels = image->lockPixelDataReadWrite (0, y, width, 1, stride, pixelStride);
const uint8* src = *buffer;
uint8* dest = pixels;
for (int i = width; --i >= 0;)
{
((PixelRGB*) dest)->setARGB (0, src[0], src[1], src[2]);
dest += pixelStride;
src += 3;
}
image->releasePixelDataReadWrite (pixels);
}
jpeg_finish_decompress (&jpegDecompStruct);
}
jpeg_destroy_decompress (&jpegDecompStruct);
}
catch (...)
{}
in.setPosition (((char*) jpegDecompStruct.src->next_input_byte) - (char*) mb.getData());
}
return image;
}
//==============================================================================
static const int bufferSize = 512;
struct JuceJpegDest : public jpeg_destination_mgr
{
OutputStream* output;
char* buffer;
};
static void jpegWriteInit (j_compress_ptr) throw()
{
}
static void jpegWriteTerminate (j_compress_ptr cinfo) throw()
{
JuceJpegDest* const dest = (JuceJpegDest*) cinfo->dest;
const int numToWrite = bufferSize - dest->free_in_buffer;
dest->output->write (dest->buffer, numToWrite);
}
static boolean jpegWriteFlush (j_compress_ptr cinfo) throw()
{
JuceJpegDest* const dest = (JuceJpegDest*) cinfo->dest;
const int numToWrite = bufferSize;
dest->next_output_byte = (JOCTET*) dest->buffer;
dest->free_in_buffer = bufferSize;
return dest->output->write (dest->buffer, numToWrite);
}
//==============================================================================
bool juce_writeJPEGImageToStream (const Image& image,
OutputStream& out,
float quality) throw()
{
if (image.hasAlphaChannel())
{
// this method could fill the background in white and still save the image..
jassertfalse
return true;
}
struct jpeg_compress_struct jpegCompStruct;
struct jpeg_error_mgr jerr;
setupSilentErrorHandler (jerr);
jpegCompStruct.err = &jerr;
jpeg_create_compress (&jpegCompStruct);
JuceJpegDest dest;
jpegCompStruct.dest = &dest;
dest.output = &out;
dest.buffer = (char*) juce_malloc (bufferSize);
dest.next_output_byte = (JOCTET*) dest.buffer;
dest.free_in_buffer = bufferSize;
dest.init_destination = jpegWriteInit;
dest.empty_output_buffer = jpegWriteFlush;
dest.term_destination = jpegWriteTerminate;
jpegCompStruct.image_width = image.getWidth();
jpegCompStruct.image_height = image.getHeight();
jpegCompStruct.input_components = 3;
jpegCompStruct.in_color_space = JCS_RGB;
jpegCompStruct.write_JFIF_header = 1;
jpegCompStruct.X_density = 72;
jpegCompStruct.Y_density = 72;
jpeg_set_defaults (&jpegCompStruct);
jpegCompStruct.dct_method = JDCT_FLOAT;
jpegCompStruct.optimize_coding = 1;
// jpegCompStruct.smoothing_factor = 10;
if (quality < 0.0f)
quality = 0.85f;
jpeg_set_quality (&jpegCompStruct, jlimit (0, 100, roundFloatToInt (quality * 100.0f)), TRUE);
jpeg_start_compress (&jpegCompStruct, TRUE);
const int strideBytes = jpegCompStruct.image_width * jpegCompStruct.input_components;
JSAMPARRAY buffer = (*jpegCompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegCompStruct,
JPOOL_IMAGE,
strideBytes, 1);
while (jpegCompStruct.next_scanline < jpegCompStruct.image_height)
{
int stride, pixelStride;
const uint8* pixels = image.lockPixelDataReadOnly (0, jpegCompStruct.next_scanline, jpegCompStruct.image_width, 1, stride, pixelStride);
const uint8* src = pixels;
uint8* dst = *buffer;
for (int i = jpegCompStruct.image_width; --i >= 0;)
{
*dst++ = ((const PixelRGB*) src)->getRed();
*dst++ = ((const PixelRGB*) src)->getGreen();
*dst++ = ((const PixelRGB*) src)->getBlue();
src += pixelStride;
}
jpeg_write_scanlines (&jpegCompStruct, buffer, 1);
image.releasePixelDataReadOnly (pixels);
}
jpeg_finish_compress (&jpegCompStruct);
jpeg_destroy_compress (&jpegCompStruct);
juce_free (dest.buffer);
out.flush();
return true;
}
END_JUCE_NAMESPACE

+ 1
- 1
src/juce_core/containers/juce_ArrayAllocationBase.h View File

@@ -104,7 +104,7 @@ protected:
elements = 0; elements = 0;
} }
numAllocated = numElements;
numAllocated = numElements;
} }
} }


Loading…
Cancel
Save