mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Support for writing JPG even if the image has an alpha channel. Added assertion to warn if you try to use a fallback font on OSX. Minor fixes and features for PopupMenu, ComboBox.
This commit is contained in:
parent
6b07bfb51b
commit
ce0b4bdb9c
14 changed files with 86 additions and 76 deletions
|
|
@ -112,7 +112,7 @@ namespace CodeHelpers
|
|||
|
||||
for (int i = 0; i < numBytes || numBytes < 0; ++i)
|
||||
{
|
||||
const char c = utf8[i];
|
||||
const unsigned char c = (unsigned char) utf8[i];
|
||||
bool startNewLine = false;
|
||||
|
||||
switch (c)
|
||||
|
|
@ -145,12 +145,12 @@ namespace CodeHelpers
|
|||
if (c >= 32 && c < 127 && ! (lastWasHexEscapeCode // (have to avoid following a hex escape sequence with a valid hex digit)
|
||||
&& CharacterFunctions::getHexDigitValue (c) >= 0))
|
||||
{
|
||||
out << c;
|
||||
out << (char) c;
|
||||
lastWasHexEscapeCode = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
out << (c < 16 ? "\\x0" : "\\x") << String::toHexString ((int) (unsigned int) c);
|
||||
out << (c < 16 ? "\\x0" : "\\x") << String::toHexString ((int) c);
|
||||
lastWasHexEscapeCode = true;
|
||||
}
|
||||
|
||||
|
|
@ -372,7 +372,7 @@ namespace CodeHelpers
|
|||
{
|
||||
String s (expression.getFloatValue());
|
||||
|
||||
if (s.containsChar (T('.')))
|
||||
if (s.containsChar ('.'))
|
||||
return s + "f";
|
||||
|
||||
return s + ".0f";
|
||||
|
|
|
|||
|
|
@ -766,7 +766,7 @@ private:
|
|||
const Identifier property;
|
||||
UndoManager* const undoManager;
|
||||
|
||||
ValueTreePropertyValueSource& operator= (const ValueTreePropertyValueSource&);
|
||||
JUCE_DECLARE_NON_COPYABLE (ValueTreePropertyValueSource);
|
||||
};
|
||||
|
||||
Value ValueTree::getPropertyAsValue (const Identifier& name, UndoManager* const undoManager) const
|
||||
|
|
|
|||
|
|
@ -310,6 +310,10 @@ const String& Font::getFallbackFontName()
|
|||
void Font::setFallbackFontName (const String& name)
|
||||
{
|
||||
FontValues::fallbackFont = name;
|
||||
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
jassertfalse; // Note that use of a fallback font isn't currently implemented in OSX..
|
||||
#endif
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -339,21 +339,13 @@ bool JPEGImageFormat::writeImageToStream (const Image& image, OutputStream& out)
|
|||
using namespace jpeglibNamespace;
|
||||
using namespace JPEGHelpers;
|
||||
|
||||
if (image.hasAlphaChannel())
|
||||
{
|
||||
// this method could fill the background in white and still save the image..
|
||||
jassertfalse;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct jpeg_compress_struct jpegCompStruct;
|
||||
jpeg_create_compress (&jpegCompStruct);
|
||||
|
||||
struct jpeg_error_mgr jerr;
|
||||
setupSilentErrorHandler (jerr);
|
||||
jpegCompStruct.err = &jerr;
|
||||
|
||||
jpeg_create_compress (&jpegCompStruct);
|
||||
|
||||
JuceJpegDest dest;
|
||||
jpegCompStruct.dest = &dest;
|
||||
|
||||
|
|
@ -396,15 +388,29 @@ bool JPEGImageFormat::writeImageToStream (const Image& image, OutputStream& out)
|
|||
|
||||
while (jpegCompStruct.next_scanline < jpegCompStruct.image_height)
|
||||
{
|
||||
const uint8* src = srcData.getLinePointer ((int) jpegCompStruct.next_scanline);
|
||||
uint8* dst = *buffer;
|
||||
|
||||
for (int i = (int) jpegCompStruct.image_width; --i >= 0;)
|
||||
if (srcData.pixelFormat == Image::RGB)
|
||||
{
|
||||
*dst++ = ((const PixelRGB*) src)->getRed();
|
||||
*dst++ = ((const PixelRGB*) src)->getGreen();
|
||||
*dst++ = ((const PixelRGB*) src)->getBlue();
|
||||
src += srcData.pixelStride;
|
||||
const uint8* src = srcData.getLinePointer ((int) jpegCompStruct.next_scanline);
|
||||
|
||||
for (int i = srcData.width; --i >= 0;)
|
||||
{
|
||||
*dst++ = ((const PixelRGB*) src)->getRed();
|
||||
*dst++ = ((const PixelRGB*) src)->getGreen();
|
||||
*dst++ = ((const PixelRGB*) src)->getBlue();
|
||||
src += srcData.pixelStride;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int x = 0; x < srcData.width; ++x)
|
||||
{
|
||||
const Colour pixel (srcData.getPixelColour (x, (int) jpegCompStruct.next_scanline));
|
||||
*dst++ = pixel.getRed();
|
||||
*dst++ = pixel.getGreen();
|
||||
*dst++ = pixel.getBlue();
|
||||
}
|
||||
}
|
||||
|
||||
jpeg_write_scanlines (&jpegCompStruct, buffer, 1);
|
||||
|
|
|
|||
|
|
@ -309,8 +309,8 @@ const Colour Image::BitmapData::getPixelColour (const int x, const int y) const
|
|||
|
||||
switch (pixelFormat)
|
||||
{
|
||||
case Image::ARGB: return Colour (((const PixelARGB*) pixel)->getUnpremultipliedARGB());
|
||||
case Image::RGB: return Colour (((const PixelRGB*) pixel)->getUnpremultipliedARGB());
|
||||
case Image::ARGB: return Colour (((const PixelARGB*) pixel)->getUnpremultipliedARGB());
|
||||
case Image::RGB: return Colour (((const PixelRGB*) pixel)->getUnpremultipliedARGB());
|
||||
case Image::SingleChannel: return Colour (((const PixelAlpha*) pixel)->getUnpremultipliedARGB());
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
|
@ -328,7 +328,7 @@ void Image::BitmapData::setPixelColour (const int x, const int y, const Colour&
|
|||
switch (pixelFormat)
|
||||
{
|
||||
case Image::ARGB: ((PixelARGB*) pixel)->set (col); break;
|
||||
case Image::RGB: ((PixelRGB*) pixel)->set (col); break;
|
||||
case Image::RGB: ((PixelRGB*) pixel)->set (col); break;
|
||||
case Image::SingleChannel: *pixel = col.getAlpha(); break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -520,13 +520,13 @@ void CoreGraphicsContext::drawVerticalLine (const int x, float top, float bottom
|
|||
{
|
||||
if (state->fillType.isColour())
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
|
||||
CGContextFillRect (context, CGRectMake (x, flipHeight - bottom, 1.0f, bottom - top));
|
||||
#else
|
||||
#else
|
||||
// On Leopard, unless both co-ordinates are non-integer, it disables anti-aliasing, so nudge
|
||||
// the x co-ord slightly to trick it..
|
||||
CGContextFillRect (context, CGRectMake (x + 1.0f / 256.0f, flipHeight - bottom, 1.0f + 1.0f / 256.0f, bottom - top));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -538,13 +538,13 @@ void CoreGraphicsContext::drawHorizontalLine (const int y, float left, float rig
|
|||
{
|
||||
if (state->fillType.isColour())
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5
|
||||
CGContextFillRect (context, CGRectMake (left, flipHeight - (y + 1.0f), right - left, 1.0f));
|
||||
#else
|
||||
#else
|
||||
// On Leopard, unless both co-ordinates are non-integer, it disables anti-aliasing, so nudge
|
||||
// the x co-ord slightly to trick it..
|
||||
CGContextFillRect (context, CGRectMake (left, flipHeight - (y + (1.0f + 1.0f / 256.0f)), right - left, 1.0f + 1.0f / 256.0f));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -559,15 +559,15 @@ void CoreGraphicsContext::setFont (const Font& newFont)
|
|||
state->fontRef = 0;
|
||||
state->font = newFont;
|
||||
|
||||
MacTypeface* mf = dynamic_cast <MacTypeface*> (state->font.getTypeface());
|
||||
OSXTypeface* osxTypeface = dynamic_cast <OSXTypeface*> (state->font.getTypeface());
|
||||
|
||||
if (mf != nullptr)
|
||||
if (osxTypeface != nullptr)
|
||||
{
|
||||
state->fontRef = mf->fontRef;
|
||||
state->fontRef = osxTypeface->fontRef;
|
||||
CGContextSetFont (context, state->fontRef);
|
||||
CGContextSetFontSize (context, state->font.getHeight() * mf->fontHeightToCGSizeFactor);
|
||||
CGContextSetFontSize (context, state->font.getHeight() * osxTypeface->fontHeightToCGSizeFactor);
|
||||
|
||||
state->fontTransform = mf->renderingTransform;
|
||||
state->fontTransform = osxTypeface->renderingTransform;
|
||||
state->fontTransform.a *= state->font.getHorizontalScale();
|
||||
CGContextSetTextMatrix (context, state->fontTransform);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,11 +32,10 @@
|
|||
#if JUCE_CORETEXT_AVAILABLE
|
||||
|
||||
//==============================================================================
|
||||
class MacTypeface : public Typeface
|
||||
class OSXTypeface : public Typeface
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
MacTypeface (const Font& font)
|
||||
OSXTypeface (const Font& font)
|
||||
: Typeface (font.getTypefaceName()),
|
||||
fontRef (nullptr),
|
||||
fontHeightToCGSizeFactor (1.0f),
|
||||
|
|
@ -46,7 +45,6 @@ public:
|
|||
ascent (0.0f),
|
||||
unitsToHeightScaleFactor (0.0f)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
CFStringRef cfName = font.getTypefaceName().toCFString();
|
||||
ctFontRef = CTFontCreateWithName (cfName, 1024, nullptr);
|
||||
CFRelease (cfName);
|
||||
|
|
@ -112,7 +110,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
~MacTypeface()
|
||||
~OSXTypeface()
|
||||
{
|
||||
if (attributedStringAtts != nullptr)
|
||||
CFRelease (attributedStringAtts);
|
||||
|
|
@ -256,7 +254,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MacTypeface);
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSXTypeface);
|
||||
};
|
||||
|
||||
#else
|
||||
|
|
@ -282,11 +280,10 @@ private:
|
|||
#endif
|
||||
|
||||
//==============================================================================
|
||||
class MacTypeface : public Typeface
|
||||
class OSXTypeface : public Typeface
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
MacTypeface (const Font& font)
|
||||
OSXTypeface (const Font& font)
|
||||
: Typeface (font.getTypefaceName())
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
|
|
@ -415,7 +412,7 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
~MacTypeface()
|
||||
~OSXTypeface()
|
||||
{
|
||||
#if ! JUCE_IOS
|
||||
[nsFont release];
|
||||
|
|
@ -425,15 +422,8 @@ public:
|
|||
CGFontRelease (fontRef);
|
||||
}
|
||||
|
||||
float getAscent() const
|
||||
{
|
||||
return ascent;
|
||||
}
|
||||
|
||||
float getDescent() const
|
||||
{
|
||||
return 1.0f - ascent;
|
||||
}
|
||||
float getAscent() const { return ascent; }
|
||||
float getDescent() const { return 1.0f - ascent; }
|
||||
|
||||
float getStringWidth (const String& text)
|
||||
{
|
||||
|
|
@ -569,7 +559,7 @@ public:
|
|||
switch ([bez elementAtIndex: i associatedPoints: p])
|
||||
{
|
||||
case NSMoveToBezierPathElement: path.startNewSubPath ((float) p[0].x, (float) -p[0].y); break;
|
||||
case NSLineToBezierPathElement: path.lineTo ((float) p[0].x, (float) -p[0].y); break;
|
||||
case NSLineToBezierPathElement: path.lineTo ((float) p[0].x, (float) -p[0].y); break;
|
||||
case NSCurveToBezierPathElement: path.cubicTo ((float) p[0].x, (float) -p[0].y,
|
||||
(float) p[1].x, (float) -p[1].y,
|
||||
(float) p[2].x, (float) -p[2].y); break;
|
||||
|
|
@ -725,7 +715,7 @@ private:
|
|||
ScopedPointer <CharToGlyphMapper> charToGlyphMapper;
|
||||
#endif
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MacTypeface);
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSXTypeface);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -733,7 +723,7 @@ private:
|
|||
//==============================================================================
|
||||
Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font)
|
||||
{
|
||||
return new MacTypeface (font);
|
||||
return new OSXTypeface (font);
|
||||
}
|
||||
|
||||
StringArray Font::findAllTypefaceNames()
|
||||
|
|
|
|||
|
|
@ -574,7 +574,7 @@ public:
|
|||
{
|
||||
// xxx The font shouldn't be managed by the graphics context.
|
||||
// The correct way to handle font lifetimes is to use a subclass of Typeface - see
|
||||
// MacTypeface and WindowsTypeface classes. D2D support could probably just be added to the
|
||||
// OSXTypeface and WindowsTypeface classes. D2D support could probably just be added to the
|
||||
// WindowsTypeface class.
|
||||
|
||||
if (currentFontFace == 0)
|
||||
|
|
|
|||
|
|
@ -74,20 +74,17 @@ public:
|
|||
//==============================================================================
|
||||
/** Creates a FileBrowserComponent.
|
||||
|
||||
@param flags A combination of flags from the FileChooserFlags enumeration,
|
||||
used to specify the component's behaviour. The flags must contain
|
||||
either openMode or saveMode, and canSelectFiles and/or
|
||||
canSelectDirectories.
|
||||
@param initialFileOrDirectory The file or directory that should be selected when
|
||||
the component begins. If this is File::nonexistent,
|
||||
a default directory will be chosen.
|
||||
@param fileFilter an optional filter to use to determine which files
|
||||
are shown. If this is 0 then all files are displayed. Note
|
||||
that a pointer is kept internally to this object, so
|
||||
make sure that it is not deleted before the browser object
|
||||
is deleted.
|
||||
@param previewComp an optional preview component that will be used to
|
||||
show previews of files that the user selects
|
||||
@param flags A combination of flags from the FileChooserFlags enumeration, used to
|
||||
specify the component's behaviour. The flags must contain either openMode
|
||||
or saveMode, and canSelectFiles and/or canSelectDirectories.
|
||||
@param initialFileOrDirectory The file or directory that should be selected when the component begins.
|
||||
If this is File::nonexistent, a default directory will be chosen.
|
||||
@param fileFilter an optional filter to use to determine which files are shown.
|
||||
If this is nullptr then all files are displayed. Note that a pointer
|
||||
is kept internally to this object, so make sure that it is not deleted
|
||||
before the FileBrowserComponent object is deleted.
|
||||
@param previewComp an optional preview component that will be used to show previews of
|
||||
files that the user selects
|
||||
*/
|
||||
FileBrowserComponent (int flags,
|
||||
const File& initialFileOrDirectory,
|
||||
|
|
|
|||
|
|
@ -1687,6 +1687,9 @@ bool PopupMenu::MenuItemIterator::next()
|
|||
const Item* const item = menu.items.getUnchecked (index);
|
||||
++index;
|
||||
|
||||
if (item->isSeparator && index >= menu.items.size()) // (avoid showing a separator at the end)
|
||||
return false;
|
||||
|
||||
itemName = item->customComp != nullptr ? item->customComp->getName() : item->text;
|
||||
subMenu = item->subMenu;
|
||||
itemId = item->itemId;
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ void ComboBox::setJustificationType (const Justification& justification)
|
|||
label->setJustificationType (justification);
|
||||
}
|
||||
|
||||
const Justification ComboBox::getJustificationType() const noexcept
|
||||
Justification ComboBox::getJustificationType() const noexcept
|
||||
{
|
||||
return label->getJustificationType();
|
||||
}
|
||||
|
|
@ -121,6 +121,12 @@ void ComboBox::addItem (const String& newItemText, const int newItemId)
|
|||
}
|
||||
}
|
||||
|
||||
void ComboBox::addItemList (const StringArray& items, const int firstItemIdOffset)
|
||||
{
|
||||
for (int i = 0; i < items.size(); ++i)
|
||||
addItem (items[i], i + firstItemIdOffset);
|
||||
}
|
||||
|
||||
void ComboBox::addSeparator()
|
||||
{
|
||||
separatorPending = (items.size() > 0);
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ public:
|
|||
/** Returns the current justification for the text box.
|
||||
@see setJustificationType
|
||||
*/
|
||||
const Justification getJustificationType() const noexcept;
|
||||
Justification getJustificationType() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Adds an item to be shown in the drop-down list.
|
||||
|
|
@ -104,6 +104,11 @@ public:
|
|||
*/
|
||||
void addItem (const String& newItemText, int newItemId);
|
||||
|
||||
/** Adds an array of items to the drop-down list.
|
||||
The item ID of each item will be its index in the StringArray + firstItemIdOffset.
|
||||
*/
|
||||
void addItemList (const StringArray& items, int firstItemIdOffset);
|
||||
|
||||
/** Adds a separator line to the drop-down list.
|
||||
|
||||
This is like adding a separator to a popup menu. See PopupMenu::addSeparator().
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ public:
|
|||
void setJustificationType (const Justification& justification);
|
||||
|
||||
/** Returns the type of justification, as set in setJustificationType(). */
|
||||
const Justification getJustificationType() const noexcept { return justification; }
|
||||
Justification getJustificationType() const noexcept { return justification; }
|
||||
|
||||
/** Changes the gap that is left between the edge of the component and the text.
|
||||
By default there's a small gap left at the sides of the component to allow for
|
||||
|
|
|
|||
|
|
@ -225,8 +225,7 @@ void AlertWindow::addComboBox (const String& name,
|
|||
comboBoxes.add (cb);
|
||||
allComps.add (cb);
|
||||
|
||||
for (int i = 0; i < items.size(); ++i)
|
||||
cb->addItem (items[i], i + 1);
|
||||
cb->addItemList (items, 1);
|
||||
|
||||
addAndMakeVisible (cb);
|
||||
cb->setSelectedItemIndex (0);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue