| @@ -30953,34 +30953,29 @@ void KnownPluginList::scanAndAddDragAndDroppedFiles (const StringArray& files, | |||
| { | |||
| for (int i = 0; i < files.size(); ++i) | |||
| { | |||
| bool loaded = false; | |||
| for (int j = 0; j < AudioPluginFormatManager::getInstance()->getNumFormats(); ++j) | |||
| { | |||
| AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (j); | |||
| if (scanAndAddFile (files[i], true, typesFound, *format)) | |||
| loaded = true; | |||
| return; | |||
| } | |||
| if (! loaded) | |||
| const File f (files[i]); | |||
| if (f.isDirectory()) | |||
| { | |||
| const File f (files[i]); | |||
| StringArray s; | |||
| if (f.isDirectory()) | |||
| { | |||
| StringArray s; | |||
| { | |||
| Array<File> subFiles; | |||
| f.findChildFiles (subFiles, File::findFilesAndDirectories, false); | |||
| Array<File> subFiles; | |||
| f.findChildFiles (subFiles, File::findFilesAndDirectories, false); | |||
| for (int j = 0; j < subFiles.size(); ++j) | |||
| s.add (subFiles.getReference(j).getFullPathName()); | |||
| } | |||
| scanAndAddDragAndDroppedFiles (s, typesFound); | |||
| for (int j = 0; j < subFiles.size(); ++j) | |||
| s.add (subFiles.getReference(j).getFullPathName()); | |||
| } | |||
| scanAndAddDragAndDroppedFiles (s, typesFound); | |||
| } | |||
| } | |||
| } | |||
| @@ -42334,7 +42329,8 @@ const Colour Component::findColour (const int colourId, const bool inheritFromPa | |||
| if (v != nullptr) | |||
| return Colour ((int) *v); | |||
| if (inheritFromParent && parentComponent != nullptr) | |||
| if (inheritFromParent && parentComponent != nullptr | |||
| && (lookAndFeel == nullptr || ! lookAndFeel->isColourSpecified (colourId))) | |||
| return parentComponent->findColour (colourId, true); | |||
| return getLookAndFeel().findColour (colourId); | |||
| @@ -64008,7 +64004,7 @@ void ResizableCornerComponent::mouseDrag (const MouseEvent& e) | |||
| void ResizableCornerComponent::mouseUp (const MouseEvent&) | |||
| { | |||
| if (constrainer != nullptr) | |||
| constrainer->resizeStart(); | |||
| constrainer->resizeEnd(); | |||
| } | |||
| bool ResizableCornerComponent::hitTest (int x, int y) | |||
| @@ -130661,7 +130657,7 @@ FlacAudioFormat::~FlacAudioFormat() | |||
| const Array <int> FlacAudioFormat::getPossibleSampleRates() | |||
| { | |||
| const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 0 }; | |||
| const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000, 0 }; | |||
| return Array <int> (rates); | |||
| } | |||
| @@ -130707,6 +130703,12 @@ AudioFormatWriter* FlacAudioFormat::createWriterFor (OutputStream* out, | |||
| return nullptr; | |||
| } | |||
| const StringArray FlacAudioFormat::getQualityOptions() | |||
| { | |||
| const char* options[] = { "0 (Fastest)", "1", "2", "3", "4", "5 (Default)","6", "7", "8 (Highest quality)", 0 }; | |||
| return StringArray (options); | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| #endif | |||
| @@ -262869,23 +262871,12 @@ private: | |||
| bool hasSerif, monospaced; | |||
| }; | |||
| class FreeTypeInterface : public DeletedAtShutdown | |||
| class LinuxFontFileIterator | |||
| { | |||
| public: | |||
| FreeTypeInterface() | |||
| : ftLib (0), | |||
| lastFace (0), | |||
| lastBold (false), | |||
| lastItalic (false) | |||
| LinuxFontFileIterator() | |||
| : index (0) | |||
| { | |||
| if (FT_Init_FreeType (&ftLib) != 0) | |||
| { | |||
| ftLib = 0; | |||
| DBG ("Failed to initialize FreeType"); | |||
| } | |||
| StringArray fontDirs; | |||
| fontDirs.addTokens (CharPointer_UTF8 (getenv ("JUCE_FONT_PATH")), ";,", String::empty); | |||
| fontDirs.removeEmptyStrings (true); | |||
| @@ -262905,96 +262896,124 @@ public: | |||
| if (fontDirs.size() == 0) | |||
| fontDirs.add ("/usr/X11R6/lib/X11/fonts"); | |||
| for (int i = 0; i < fontDirs.size(); ++i) | |||
| enumerateFaces (fontDirs[i]); | |||
| fontDirs.removeEmptyStrings (true); | |||
| } | |||
| ~FreeTypeInterface() | |||
| bool next() | |||
| { | |||
| if (lastFace != 0) | |||
| FT_Done_Face (lastFace); | |||
| if (iter != nullptr) | |||
| { | |||
| while (iter->next()) | |||
| if (getFile().hasFileExtension ("ttf;pfb;pcf")) | |||
| return true; | |||
| } | |||
| if (ftLib != 0) | |||
| FT_Done_FreeType (ftLib); | |||
| if (index >= fontDirs.size()) | |||
| return false; | |||
| clearSingletonInstance(); | |||
| iter = new DirectoryIterator (fontDirs [index++], true); | |||
| return next(); | |||
| } | |||
| FreeTypeFontFace* findOrCreate (const String& familyName, const bool create = false) | |||
| { | |||
| for (int i = 0; i < faces.size(); i++) | |||
| if (faces[i]->getFamilyName() == familyName) | |||
| return faces[i]; | |||
| if (! create) | |||
| return nullptr; | |||
| File getFile() const { jassert (iter != nullptr); return iter->getFile(); } | |||
| FreeTypeFontFace* newFace = new FreeTypeFontFace (familyName); | |||
| faces.add (newFace); | |||
| private: | |||
| StringArray fontDirs; | |||
| int index; | |||
| ScopedPointer<DirectoryIterator> iter; | |||
| }; | |||
| return newFace; | |||
| } | |||
| class FreeTypeInterface : public DeletedAtShutdown | |||
| { | |||
| public: | |||
| // Enumerate all font faces available in a given directory | |||
| void enumerateFaces (const String& path) | |||
| FreeTypeInterface() | |||
| : ftLib (0), | |||
| lastFace (0), | |||
| lastBold (false), | |||
| lastItalic (false) | |||
| { | |||
| File dirPath (path); | |||
| if (path.isEmpty() || ! dirPath.isDirectory()) | |||
| return; | |||
| if (FT_Init_FreeType (&ftLib) != 0) | |||
| { | |||
| ftLib = 0; | |||
| DBG ("Failed to initialize FreeType"); | |||
| } | |||
| DirectoryIterator di (dirPath, true); | |||
| LinuxFontFileIterator fontFileIterator; | |||
| while (di.next()) | |||
| while (fontFileIterator.next()) | |||
| { | |||
| File possible (di.getFile()); | |||
| FT_Face face; | |||
| int faceIndex = 0; | |||
| int numFaces = 0; | |||
| if (possible.hasFileExtension ("ttf") | |||
| || possible.hasFileExtension ("pfb") | |||
| || possible.hasFileExtension ("pcf")) | |||
| do | |||
| { | |||
| FT_Face face; | |||
| int faceIndex = 0; | |||
| int numFaces = 0; | |||
| do | |||
| if (FT_New_Face (ftLib, fontFileIterator.getFile().getFullPathName().toUTF8(), | |||
| faceIndex, &face) == 0) | |||
| { | |||
| if (FT_New_Face (ftLib, possible.getFullPathName().toUTF8(), | |||
| faceIndex, &face) == 0) | |||
| if (faceIndex == 0) | |||
| numFaces = face->num_faces; | |||
| if ((face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) | |||
| { | |||
| if (faceIndex == 0) | |||
| numFaces = face->num_faces; | |||
| FreeTypeFontFace* const newFace = findOrCreate (face->family_name, true); | |||
| int style = (int) FreeTypeFontFace::Plain; | |||
| if ((face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) | |||
| { | |||
| FreeTypeFontFace* const newFace = findOrCreate (face->family_name, true); | |||
| int style = (int) FreeTypeFontFace::Plain; | |||
| if ((face->style_flags & FT_STYLE_FLAG_BOLD) != 0) | |||
| style |= (int) FreeTypeFontFace::Bold; | |||
| if ((face->style_flags & FT_STYLE_FLAG_BOLD) != 0) | |||
| style |= (int) FreeTypeFontFace::Bold; | |||
| if ((face->style_flags & FT_STYLE_FLAG_ITALIC) != 0) | |||
| style |= (int) FreeTypeFontFace::Italic; | |||
| if ((face->style_flags & FT_STYLE_FLAG_ITALIC) != 0) | |||
| style |= (int) FreeTypeFontFace::Italic; | |||
| newFace->setFileName (fontFileIterator.getFile().getFullPathName(), | |||
| faceIndex, (FreeTypeFontFace::FontStyle) style); | |||
| newFace->setMonospaced ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0); | |||
| newFace->setFileName (possible.getFullPathName(), faceIndex, (FreeTypeFontFace::FontStyle) style); | |||
| newFace->setMonospaced ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0); | |||
| // Surely there must be a better way to do this? | |||
| const String name (face->family_name); | |||
| newFace->setSerif (! (name.containsIgnoreCase ("Sans") | |||
| || name.containsIgnoreCase ("Verdana") | |||
| || name.containsIgnoreCase ("Arial"))); | |||
| // Surely there must be a better way to do this? | |||
| const String name (face->family_name); | |||
| newFace->setSerif (! (name.containsIgnoreCase ("Sans") | |||
| || name.containsIgnoreCase ("Verdana") | |||
| || name.containsIgnoreCase ("Arial"))); | |||
| } | |||
| FT_Done_Face (face); | |||
| //DBG (fontFileIterator.getFile().getFullPathName() << " - " << name); | |||
| } | |||
| ++faceIndex; | |||
| FT_Done_Face (face); | |||
| } | |||
| while (faceIndex < numFaces); | |||
| ++faceIndex; | |||
| } | |||
| while (faceIndex < numFaces); | |||
| } | |||
| } | |||
| ~FreeTypeInterface() | |||
| { | |||
| if (lastFace != 0) | |||
| FT_Done_Face (lastFace); | |||
| if (ftLib != 0) | |||
| FT_Done_FreeType (ftLib); | |||
| clearSingletonInstance(); | |||
| } | |||
| FreeTypeFontFace* findOrCreate (const String& familyName, const bool create = false) | |||
| { | |||
| for (int i = 0; i < faces.size(); i++) | |||
| if (faces[i]->getFamilyName() == familyName) | |||
| return faces[i]; | |||
| if (! create) | |||
| return nullptr; | |||
| FreeTypeFontFace* newFace = new FreeTypeFontFace (familyName); | |||
| faces.add (newFace); | |||
| return newFace; | |||
| } | |||
| // Create a FreeType face object for a given font | |||
| FT_Face createFT_Face (const String& fontName, const bool bold, const bool italic) | |||
| { | |||
| @@ -263252,11 +263271,11 @@ public: | |||
| if (face == 0) | |||
| { | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| String msg ("Failed to create typeface: "); | |||
| msg << font.getTypefaceName() << " " << (font.isBold() ? 'B' : ' ') << (font.isItalic() ? 'I' : ' '); | |||
| DBG (msg); | |||
| #endif | |||
| #endif | |||
| } | |||
| else | |||
| { | |||
| @@ -263287,15 +263306,12 @@ const StringArray Font::findAllTypefaceNames() | |||
| return s; | |||
| } | |||
| namespace | |||
| namespace LinuxFontHelpers | |||
| { | |||
| const String pickBestFont (const StringArray& names, | |||
| const char* const choicesString) | |||
| const char* const* choicesString) | |||
| { | |||
| StringArray choices; | |||
| choices.addTokens (String (choicesString), ",", String::empty); | |||
| choices.trim(); | |||
| choices.removeEmptyStrings(); | |||
| const StringArray choices (choicesString); | |||
| int i, j; | |||
| for (j = 0; j < choices.size(); ++j) | |||
| @@ -263315,36 +263331,39 @@ namespace | |||
| return names[0]; | |||
| } | |||
| const String linux_getDefaultSansSerifFontName() | |||
| const String getDefaultSansSerifFontName() | |||
| { | |||
| StringArray allFonts; | |||
| FreeTypeInterface::getInstance()->getSansSerifNames (allFonts); | |||
| return pickBestFont (allFonts, "Verdana, Bitstream Vera Sans, Luxi Sans, Sans"); | |||
| const char* targets[] = { "Verdana", "Bitstream Vera Sans", "Luxi Sans", "Sans", 0 }; | |||
| return pickBestFont (allFonts, targets); | |||
| } | |||
| const String linux_getDefaultSerifFontName() | |||
| const String getDefaultSerifFontName() | |||
| { | |||
| StringArray allFonts; | |||
| FreeTypeInterface::getInstance()->getSerifNames (allFonts); | |||
| return pickBestFont (allFonts, "Bitstream Vera Serif, Times, Nimbus Roman, Serif"); | |||
| const char* targets[] = { "Bitstream Vera Serif", "Times", "Nimbus Roman", "Serif", 0 }; | |||
| return pickBestFont (allFonts, targets); | |||
| } | |||
| const String linux_getDefaultMonospacedFontName() | |||
| const String getDefaultMonospacedFontName() | |||
| { | |||
| StringArray allFonts; | |||
| FreeTypeInterface::getInstance()->getMonospacedNames (allFonts); | |||
| return pickBestFont (allFonts, "Bitstream Vera Sans Mono, Courier, Sans Mono, Mono"); | |||
| const char* targets[] = { "Bitstream Vera Sans Mono", "Courier", "Sans Mono", "Mono", 0 }; | |||
| return pickBestFont (allFonts, targets); | |||
| } | |||
| } | |||
| void Font::getPlatformDefaultFontNames (String& defaultSans, String& defaultSerif, String& defaultFixed, String& /*defaultFallback*/) | |||
| { | |||
| defaultSans = linux_getDefaultSansSerifFontName(); | |||
| defaultSerif = linux_getDefaultSerifFontName(); | |||
| defaultFixed = linux_getDefaultMonospacedFontName(); | |||
| defaultSans = LinuxFontHelpers::getDefaultSansSerifFontName(); | |||
| defaultSerif = LinuxFontHelpers::getDefaultSerifFontName(); | |||
| defaultFixed = LinuxFontHelpers::getDefaultMonospacedFontName(); | |||
| } | |||
| #endif | |||
| @@ -279769,11 +279788,10 @@ bool NSViewComponentPeer::contains (const Point<int>& position, bool trueIfInACh | |||
| && isPositiveAndBelow (position.getY(), component->getHeight()))) | |||
| return false; | |||
| NSPoint p; | |||
| p.x = (float) position.getX(); | |||
| p.y = (float) position.getY(); | |||
| NSRect frameRect = [view frame]; | |||
| NSView* v = [view hitTest: p]; | |||
| NSView* v = [view hitTest: NSMakePoint (frameRect.origin.x + position.getX(), | |||
| frameRect.origin.y + frameRect.size.height - position.getY())]; | |||
| if (trueIfInAChildWindow) | |||
| return v != nil; | |||
| @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 90 | |||
| #define JUCE_BUILDNUMBER 91 | |||
| /** Current Juce version number. | |||
| @@ -37649,6 +37649,7 @@ public: | |||
| bool canDoStereo(); | |||
| bool canDoMono(); | |||
| bool isCompressed(); | |||
| const StringArray getQualityOptions(); | |||
| AudioFormatReader* createReaderFor (InputStream* sourceStream, | |||
| bool deleteStreamIfOpeningFails); | |||
| @@ -37659,7 +37660,6 @@ public: | |||
| int bitsPerSample, | |||
| const StringPairArray& metadataValues, | |||
| int qualityOptionIndex); | |||
| private: | |||
| JUCE_LEAK_DETECTOR (FlacAudioFormat); | |||
| }; | |||
| @@ -58916,229 +58916,6 @@ private: | |||
| #ifndef __JUCE_TEXTEDITORKEYMAPPER_JUCEHEADER__ | |||
| #define __JUCE_TEXTEDITORKEYMAPPER_JUCEHEADER__ | |||
| /*** Start of inlined file: juce_Keypress.h ***/ | |||
| #ifndef __JUCE_KEYPRESS_JUCEHEADER__ | |||
| #define __JUCE_KEYPRESS_JUCEHEADER__ | |||
| /** | |||
| Represents a key press, including any modifier keys that are needed. | |||
| E.g. a KeyPress might represent CTRL+C, SHIFT+ALT+H, Spacebar, Escape, etc. | |||
| @see Component, KeyListener, Button::addShortcut, KeyPressMappingManager | |||
| */ | |||
| class JUCE_API KeyPress | |||
| { | |||
| public: | |||
| /** Creates an (invalid) KeyPress. | |||
| @see isValid | |||
| */ | |||
| KeyPress() noexcept; | |||
| /** Creates a KeyPress for a key and some modifiers. | |||
| e.g. | |||
| CTRL+C would be: KeyPress ('c', ModifierKeys::ctrlModifier) | |||
| SHIFT+Escape would be: KeyPress (KeyPress::escapeKey, ModifierKeys::shiftModifier) | |||
| @param keyCode a code that represents the key - this value must be | |||
| one of special constants listed in this class, or an | |||
| 8-bit character code such as a letter (case is ignored), | |||
| digit or a simple key like "," or ".". Note that this | |||
| isn't the same as the textCharacter parameter, so for example | |||
| a keyCode of 'a' and a shift-key modifier should have a | |||
| textCharacter value of 'A'. | |||
| @param modifiers the modifiers to associate with the keystroke | |||
| @param textCharacter the character that would be printed if someone typed | |||
| this keypress into a text editor. This value may be | |||
| null if the keypress is a non-printing character | |||
| @see getKeyCode, isKeyCode, getModifiers | |||
| */ | |||
| KeyPress (int keyCode, | |||
| const ModifierKeys& modifiers, | |||
| juce_wchar textCharacter) noexcept; | |||
| /** Creates a keypress with a keyCode but no modifiers or text character. | |||
| */ | |||
| KeyPress (int keyCode) noexcept; | |||
| /** Creates a copy of another KeyPress. */ | |||
| KeyPress (const KeyPress& other) noexcept; | |||
| /** Copies this KeyPress from another one. */ | |||
| KeyPress& operator= (const KeyPress& other) noexcept; | |||
| /** Compares two KeyPress objects. */ | |||
| bool operator== (const KeyPress& other) const noexcept; | |||
| /** Compares two KeyPress objects. */ | |||
| bool operator!= (const KeyPress& other) const noexcept; | |||
| /** Returns true if this is a valid KeyPress. | |||
| A null keypress can be created by the default constructor, in case it's | |||
| needed. | |||
| */ | |||
| bool isValid() const noexcept { return keyCode != 0; } | |||
| /** Returns the key code itself. | |||
| This will either be one of the special constants defined in this class, | |||
| or an 8-bit character code. | |||
| */ | |||
| int getKeyCode() const noexcept { return keyCode; } | |||
| /** Returns the key modifiers. | |||
| @see ModifierKeys | |||
| */ | |||
| const ModifierKeys getModifiers() const noexcept { return mods; } | |||
| /** Returns the character that is associated with this keypress. | |||
| This is the character that you'd expect to see printed if you press this | |||
| keypress in a text editor or similar component. | |||
| */ | |||
| juce_wchar getTextCharacter() const noexcept { return textCharacter; } | |||
| /** Checks whether the KeyPress's key is the same as the one provided, without checking | |||
| the modifiers. | |||
| The values for key codes can either be one of the special constants defined in | |||
| this class, or an 8-bit character code. | |||
| @see getKeyCode | |||
| */ | |||
| bool isKeyCode (int keyCodeToCompare) const noexcept { return keyCode == keyCodeToCompare; } | |||
| /** Converts a textual key description to a KeyPress. | |||
| This attempts to decode a textual version of a keypress, e.g. "CTRL + C" or "SPACE". | |||
| This isn't designed to cope with any kind of input, but should be given the | |||
| strings that are created by the getTextDescription() method. | |||
| If the string can't be parsed, the object returned will be invalid. | |||
| @see getTextDescription | |||
| */ | |||
| static const KeyPress createFromDescription (const String& textVersion); | |||
| /** Creates a textual description of the key combination. | |||
| e.g. "CTRL + C" or "DELETE". | |||
| To store a keypress in a file, use this method, along with createFromDescription() | |||
| to retrieve it later. | |||
| */ | |||
| const String getTextDescription() const; | |||
| /** Creates a textual description of the key combination, using unicode icon symbols if possible. | |||
| On OSX, this uses the Apple symbols for command, option, shift, etc, instead of the textual | |||
| modifier key descriptions that are returned by getTextDescription() | |||
| */ | |||
| const String getTextDescriptionWithIcons() const; | |||
| /** Checks whether the user is currently holding down the keys that make up this | |||
| KeyPress. | |||
| Note that this will return false if any extra modifier keys are | |||
| down - e.g. if the keypress is CTRL+X and the user is actually holding CTRL+ALT+x | |||
| then it will be false. | |||
| */ | |||
| bool isCurrentlyDown() const; | |||
| /** Checks whether a particular key is held down, irrespective of modifiers. | |||
| The values for key codes can either be one of the special constants defined in | |||
| this class, or an 8-bit character code. | |||
| */ | |||
| static bool isKeyCurrentlyDown (int keyCode); | |||
| // Key codes | |||
| // | |||
| // Note that the actual values of these are platform-specific and may change | |||
| // without warning, so don't store them anywhere as constants. For persisting/retrieving | |||
| // KeyPress objects, use getTextDescription() and createFromDescription() instead. | |||
| // | |||
| static const int spaceKey; /**< key-code for the space bar */ | |||
| static const int escapeKey; /**< key-code for the escape key */ | |||
| static const int returnKey; /**< key-code for the return key*/ | |||
| static const int tabKey; /**< key-code for the tab key*/ | |||
| static const int deleteKey; /**< key-code for the delete key (not backspace) */ | |||
| static const int backspaceKey; /**< key-code for the backspace key */ | |||
| static const int insertKey; /**< key-code for the insert key */ | |||
| static const int upKey; /**< key-code for the cursor-up key */ | |||
| static const int downKey; /**< key-code for the cursor-down key */ | |||
| static const int leftKey; /**< key-code for the cursor-left key */ | |||
| static const int rightKey; /**< key-code for the cursor-right key */ | |||
| static const int pageUpKey; /**< key-code for the page-up key */ | |||
| static const int pageDownKey; /**< key-code for the page-down key */ | |||
| static const int homeKey; /**< key-code for the home key */ | |||
| static const int endKey; /**< key-code for the end key */ | |||
| static const int F1Key; /**< key-code for the F1 key */ | |||
| static const int F2Key; /**< key-code for the F2 key */ | |||
| static const int F3Key; /**< key-code for the F3 key */ | |||
| static const int F4Key; /**< key-code for the F4 key */ | |||
| static const int F5Key; /**< key-code for the F5 key */ | |||
| static const int F6Key; /**< key-code for the F6 key */ | |||
| static const int F7Key; /**< key-code for the F7 key */ | |||
| static const int F8Key; /**< key-code for the F8 key */ | |||
| static const int F9Key; /**< key-code for the F9 key */ | |||
| static const int F10Key; /**< key-code for the F10 key */ | |||
| static const int F11Key; /**< key-code for the F11 key */ | |||
| static const int F12Key; /**< key-code for the F12 key */ | |||
| static const int F13Key; /**< key-code for the F13 key */ | |||
| static const int F14Key; /**< key-code for the F14 key */ | |||
| static const int F15Key; /**< key-code for the F15 key */ | |||
| static const int F16Key; /**< key-code for the F16 key */ | |||
| static const int numberPad0; /**< key-code for the 0 on the numeric keypad. */ | |||
| static const int numberPad1; /**< key-code for the 1 on the numeric keypad. */ | |||
| static const int numberPad2; /**< key-code for the 2 on the numeric keypad. */ | |||
| static const int numberPad3; /**< key-code for the 3 on the numeric keypad. */ | |||
| static const int numberPad4; /**< key-code for the 4 on the numeric keypad. */ | |||
| static const int numberPad5; /**< key-code for the 5 on the numeric keypad. */ | |||
| static const int numberPad6; /**< key-code for the 6 on the numeric keypad. */ | |||
| static const int numberPad7; /**< key-code for the 7 on the numeric keypad. */ | |||
| static const int numberPad8; /**< key-code for the 8 on the numeric keypad. */ | |||
| static const int numberPad9; /**< key-code for the 9 on the numeric keypad. */ | |||
| static const int numberPadAdd; /**< key-code for the add sign on the numeric keypad. */ | |||
| static const int numberPadSubtract; /**< key-code for the subtract sign on the numeric keypad. */ | |||
| static const int numberPadMultiply; /**< key-code for the multiply sign on the numeric keypad. */ | |||
| static const int numberPadDivide; /**< key-code for the divide sign on the numeric keypad. */ | |||
| static const int numberPadSeparator; /**< key-code for the comma on the numeric keypad. */ | |||
| static const int numberPadDecimalPoint; /**< key-code for the decimal point sign on the numeric keypad. */ | |||
| static const int numberPadEquals; /**< key-code for the equals key on the numeric keypad. */ | |||
| static const int numberPadDelete; /**< key-code for the delete key on the numeric keypad. */ | |||
| static const int playKey; /**< key-code for a multimedia 'play' key, (not all keyboards will have one) */ | |||
| static const int stopKey; /**< key-code for a multimedia 'stop' key, (not all keyboards will have one) */ | |||
| static const int fastForwardKey; /**< key-code for a multimedia 'fast-forward' key, (not all keyboards will have one) */ | |||
| static const int rewindKey; /**< key-code for a multimedia 'rewind' key, (not all keyboards will have one) */ | |||
| private: | |||
| int keyCode; | |||
| ModifierKeys mods; | |||
| juce_wchar textCharacter; | |||
| JUCE_LEAK_DETECTOR (KeyPress); | |||
| }; | |||
| #endif // __JUCE_KEYPRESS_JUCEHEADER__ | |||
| /*** End of inlined file: juce_Keypress.h ***/ | |||
| /** This class is used to invoke a range of text-editor navigation methods on | |||
| an object, based upon a keypress event. | |||
| @@ -488,7 +488,7 @@ FlacAudioFormat::~FlacAudioFormat() | |||
| const Array <int> FlacAudioFormat::getPossibleSampleRates() | |||
| { | |||
| const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 0 }; | |||
| const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000, 0 }; | |||
| return Array <int> (rates); | |||
| } | |||
| @@ -534,6 +534,12 @@ AudioFormatWriter* FlacAudioFormat::createWriterFor (OutputStream* out, | |||
| return nullptr; | |||
| } | |||
| const StringArray FlacAudioFormat::getQualityOptions() | |||
| { | |||
| const char* options[] = { "0 (Fastest)", "1", "2", "3", "4", "5 (Default)","6", "7", "8 (Highest quality)", 0 }; | |||
| return StringArray (options); | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| #endif | |||
| @@ -54,6 +54,7 @@ public: | |||
| bool canDoStereo(); | |||
| bool canDoMono(); | |||
| bool isCompressed(); | |||
| const StringArray getQualityOptions(); | |||
| //============================================================================== | |||
| AudioFormatReader* createReaderFor (InputStream* sourceStream, | |||
| @@ -65,7 +66,6 @@ public: | |||
| int bitsPerSample, | |||
| const StringPairArray& metadataValues, | |||
| int qualityOptionIndex); | |||
| private: | |||
| JUCE_LEAK_DETECTOR (FlacAudioFormat); | |||
| }; | |||
| @@ -179,34 +179,29 @@ void KnownPluginList::scanAndAddDragAndDroppedFiles (const StringArray& files, | |||
| { | |||
| for (int i = 0; i < files.size(); ++i) | |||
| { | |||
| bool loaded = false; | |||
| for (int j = 0; j < AudioPluginFormatManager::getInstance()->getNumFormats(); ++j) | |||
| { | |||
| AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (j); | |||
| if (scanAndAddFile (files[i], true, typesFound, *format)) | |||
| loaded = true; | |||
| return; | |||
| } | |||
| if (! loaded) | |||
| const File f (files[i]); | |||
| if (f.isDirectory()) | |||
| { | |||
| const File f (files[i]); | |||
| StringArray s; | |||
| if (f.isDirectory()) | |||
| { | |||
| StringArray s; | |||
| { | |||
| Array<File> subFiles; | |||
| f.findChildFiles (subFiles, File::findFilesAndDirectories, false); | |||
| Array<File> subFiles; | |||
| f.findChildFiles (subFiles, File::findFilesAndDirectories, false); | |||
| for (int j = 0; j < subFiles.size(); ++j) | |||
| s.add (subFiles.getReference(j).getFullPathName()); | |||
| } | |||
| scanAndAddDragAndDroppedFiles (s, typesFound); | |||
| for (int j = 0; j < subFiles.size(); ++j) | |||
| s.add (subFiles.getReference(j).getFullPathName()); | |||
| } | |||
| scanAndAddDragAndDroppedFiles (s, typesFound); | |||
| } | |||
| } | |||
| } | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 90 | |||
| #define JUCE_BUILDNUMBER 91 | |||
| /** Current Juce version number. | |||
| @@ -2043,7 +2043,8 @@ const Colour Component::findColour (const int colourId, const bool inheritFromPa | |||
| if (v != nullptr) | |||
| return Colour ((int) *v); | |||
| if (inheritFromParent && parentComponent != nullptr) | |||
| if (inheritFromParent && parentComponent != nullptr | |||
| && (lookAndFeel == nullptr || ! lookAndFeel->isColourSpecified (colourId))) | |||
| return parentComponent->findColour (colourId, true); | |||
| return getLookAndFeel().findColour (colourId); | |||
| @@ -26,7 +26,8 @@ | |||
| #ifndef __JUCE_TEXTEDITORKEYMAPPER_JUCEHEADER__ | |||
| #define __JUCE_TEXTEDITORKEYMAPPER_JUCEHEADER__ | |||
| #include "juce_Keypress.h" | |||
| #include "juce_KeyPress.h" | |||
| //============================================================================== | |||
| /** This class is used to invoke a range of text-editor navigation methods on | |||
| @@ -99,7 +99,7 @@ void ResizableCornerComponent::mouseDrag (const MouseEvent& e) | |||
| void ResizableCornerComponent::mouseUp (const MouseEvent&) | |||
| { | |||
| if (constrainer != nullptr) | |||
| constrainer->resizeStart(); | |||
| constrainer->resizeEnd(); | |||
| } | |||
| bool ResizableCornerComponent::hitTest (int x, int y) | |||
| @@ -85,6 +85,60 @@ private: | |||
| bool hasSerif, monospaced; | |||
| }; | |||
| //============================================================================== | |||
| class LinuxFontFileIterator | |||
| { | |||
| public: | |||
| LinuxFontFileIterator() | |||
| : index (0) | |||
| { | |||
| fontDirs.addTokens (CharPointer_UTF8 (getenv ("JUCE_FONT_PATH")), ";,", String::empty); | |||
| fontDirs.removeEmptyStrings (true); | |||
| if (fontDirs.size() == 0) | |||
| { | |||
| const ScopedPointer<XmlElement> fontsInfo (XmlDocument::parse (File ("/etc/fonts/fonts.conf"))); | |||
| if (fontsInfo != nullptr) | |||
| { | |||
| forEachXmlChildElementWithTagName (*fontsInfo, e, "dir") | |||
| { | |||
| fontDirs.add (e->getAllSubText().trim()); | |||
| } | |||
| } | |||
| } | |||
| if (fontDirs.size() == 0) | |||
| fontDirs.add ("/usr/X11R6/lib/X11/fonts"); | |||
| fontDirs.removeEmptyStrings (true); | |||
| } | |||
| bool next() | |||
| { | |||
| if (iter != nullptr) | |||
| { | |||
| while (iter->next()) | |||
| if (getFile().hasFileExtension ("ttf;pfb;pcf")) | |||
| return true; | |||
| } | |||
| if (index >= fontDirs.size()) | |||
| return false; | |||
| iter = new DirectoryIterator (fontDirs [index++], true); | |||
| return next(); | |||
| } | |||
| File getFile() const { jassert (iter != nullptr); return iter->getFile(); } | |||
| private: | |||
| StringArray fontDirs; | |||
| int index; | |||
| ScopedPointer<DirectoryIterator> iter; | |||
| }; | |||
| //============================================================================== | |||
| class FreeTypeInterface : public DeletedAtShutdown | |||
| { | |||
| @@ -102,28 +156,53 @@ public: | |||
| DBG ("Failed to initialize FreeType"); | |||
| } | |||
| StringArray fontDirs; | |||
| fontDirs.addTokens (CharPointer_UTF8 (getenv ("JUCE_FONT_PATH")), ";,", String::empty); | |||
| fontDirs.removeEmptyStrings (true); | |||
| LinuxFontFileIterator fontFileIterator; | |||
| if (fontDirs.size() == 0) | |||
| while (fontFileIterator.next()) | |||
| { | |||
| const ScopedPointer<XmlElement> fontsInfo (XmlDocument::parse (File ("/etc/fonts/fonts.conf"))); | |||
| FT_Face face; | |||
| int faceIndex = 0; | |||
| int numFaces = 0; | |||
| if (fontsInfo != nullptr) | |||
| do | |||
| { | |||
| forEachXmlChildElementWithTagName (*fontsInfo, e, "dir") | |||
| if (FT_New_Face (ftLib, fontFileIterator.getFile().getFullPathName().toUTF8(), | |||
| faceIndex, &face) == 0) | |||
| { | |||
| fontDirs.add (e->getAllSubText().trim()); | |||
| if (faceIndex == 0) | |||
| numFaces = face->num_faces; | |||
| if ((face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) | |||
| { | |||
| FreeTypeFontFace* const newFace = findOrCreate (face->family_name, true); | |||
| int style = (int) FreeTypeFontFace::Plain; | |||
| if ((face->style_flags & FT_STYLE_FLAG_BOLD) != 0) | |||
| style |= (int) FreeTypeFontFace::Bold; | |||
| if ((face->style_flags & FT_STYLE_FLAG_ITALIC) != 0) | |||
| style |= (int) FreeTypeFontFace::Italic; | |||
| newFace->setFileName (fontFileIterator.getFile().getFullPathName(), | |||
| faceIndex, (FreeTypeFontFace::FontStyle) style); | |||
| newFace->setMonospaced ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0); | |||
| // Surely there must be a better way to do this? | |||
| const String name (face->family_name); | |||
| newFace->setSerif (! (name.containsIgnoreCase ("Sans") | |||
| || name.containsIgnoreCase ("Verdana") | |||
| || name.containsIgnoreCase ("Arial"))); | |||
| //DBG (fontFileIterator.getFile().getFullPathName() << " - " << name); | |||
| } | |||
| FT_Done_Face (face); | |||
| } | |||
| ++faceIndex; | |||
| } | |||
| while (faceIndex < numFaces); | |||
| } | |||
| if (fontDirs.size() == 0) | |||
| fontDirs.add ("/usr/X11R6/lib/X11/fonts"); | |||
| for (int i = 0; i < fontDirs.size(); ++i) | |||
| enumerateFaces (fontDirs[i]); | |||
| } | |||
| ~FreeTypeInterface() | |||
| @@ -153,66 +232,6 @@ public: | |||
| return newFace; | |||
| } | |||
| // Enumerate all font faces available in a given directory | |||
| void enumerateFaces (const String& path) | |||
| { | |||
| File dirPath (path); | |||
| if (path.isEmpty() || ! dirPath.isDirectory()) | |||
| return; | |||
| DirectoryIterator di (dirPath, true); | |||
| while (di.next()) | |||
| { | |||
| File possible (di.getFile()); | |||
| if (possible.hasFileExtension ("ttf") | |||
| || possible.hasFileExtension ("pfb") | |||
| || possible.hasFileExtension ("pcf")) | |||
| { | |||
| FT_Face face; | |||
| int faceIndex = 0; | |||
| int numFaces = 0; | |||
| do | |||
| { | |||
| if (FT_New_Face (ftLib, possible.getFullPathName().toUTF8(), | |||
| faceIndex, &face) == 0) | |||
| { | |||
| if (faceIndex == 0) | |||
| numFaces = face->num_faces; | |||
| if ((face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) | |||
| { | |||
| FreeTypeFontFace* const newFace = findOrCreate (face->family_name, true); | |||
| int style = (int) FreeTypeFontFace::Plain; | |||
| if ((face->style_flags & FT_STYLE_FLAG_BOLD) != 0) | |||
| style |= (int) FreeTypeFontFace::Bold; | |||
| if ((face->style_flags & FT_STYLE_FLAG_ITALIC) != 0) | |||
| style |= (int) FreeTypeFontFace::Italic; | |||
| newFace->setFileName (possible.getFullPathName(), faceIndex, (FreeTypeFontFace::FontStyle) style); | |||
| newFace->setMonospaced ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0); | |||
| // Surely there must be a better way to do this? | |||
| const String name (face->family_name); | |||
| newFace->setSerif (! (name.containsIgnoreCase ("Sans") | |||
| || name.containsIgnoreCase ("Verdana") | |||
| || name.containsIgnoreCase ("Arial"))); | |||
| } | |||
| FT_Done_Face (face); | |||
| } | |||
| ++faceIndex; | |||
| } | |||
| while (faceIndex < numFaces); | |||
| } | |||
| } | |||
| } | |||
| // Create a FreeType face object for a given font | |||
| FT_Face createFT_Face (const String& fontName, const bool bold, const bool italic) | |||
| { | |||
| @@ -473,11 +492,11 @@ public: | |||
| if (face == 0) | |||
| { | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| String msg ("Failed to create typeface: "); | |||
| msg << font.getTypefaceName() << " " << (font.isBold() ? 'B' : ' ') << (font.isItalic() ? 'I' : ' '); | |||
| DBG (msg); | |||
| #endif | |||
| #endif | |||
| } | |||
| else | |||
| { | |||
| @@ -509,15 +528,12 @@ const StringArray Font::findAllTypefaceNames() | |||
| return s; | |||
| } | |||
| namespace | |||
| namespace LinuxFontHelpers | |||
| { | |||
| const String pickBestFont (const StringArray& names, | |||
| const char* const choicesString) | |||
| const char* const* choicesString) | |||
| { | |||
| StringArray choices; | |||
| choices.addTokens (String (choicesString), ",", String::empty); | |||
| choices.trim(); | |||
| choices.removeEmptyStrings(); | |||
| const StringArray choices (choicesString); | |||
| int i, j; | |||
| for (j = 0; j < choices.size(); ++j) | |||
| @@ -537,36 +553,39 @@ namespace | |||
| return names[0]; | |||
| } | |||
| const String linux_getDefaultSansSerifFontName() | |||
| const String getDefaultSansSerifFontName() | |||
| { | |||
| StringArray allFonts; | |||
| FreeTypeInterface::getInstance()->getSansSerifNames (allFonts); | |||
| return pickBestFont (allFonts, "Verdana, Bitstream Vera Sans, Luxi Sans, Sans"); | |||
| const char* targets[] = { "Verdana", "Bitstream Vera Sans", "Luxi Sans", "Sans", 0 }; | |||
| return pickBestFont (allFonts, targets); | |||
| } | |||
| const String linux_getDefaultSerifFontName() | |||
| const String getDefaultSerifFontName() | |||
| { | |||
| StringArray allFonts; | |||
| FreeTypeInterface::getInstance()->getSerifNames (allFonts); | |||
| return pickBestFont (allFonts, "Bitstream Vera Serif, Times, Nimbus Roman, Serif"); | |||
| const char* targets[] = { "Bitstream Vera Serif", "Times", "Nimbus Roman", "Serif", 0 }; | |||
| return pickBestFont (allFonts, targets); | |||
| } | |||
| const String linux_getDefaultMonospacedFontName() | |||
| const String getDefaultMonospacedFontName() | |||
| { | |||
| StringArray allFonts; | |||
| FreeTypeInterface::getInstance()->getMonospacedNames (allFonts); | |||
| return pickBestFont (allFonts, "Bitstream Vera Sans Mono, Courier, Sans Mono, Mono"); | |||
| const char* targets[] = { "Bitstream Vera Sans Mono", "Courier", "Sans Mono", "Mono", 0 }; | |||
| return pickBestFont (allFonts, targets); | |||
| } | |||
| } | |||
| void Font::getPlatformDefaultFontNames (String& defaultSans, String& defaultSerif, String& defaultFixed, String& /*defaultFallback*/) | |||
| { | |||
| defaultSans = linux_getDefaultSansSerifFontName(); | |||
| defaultSerif = linux_getDefaultSerifFontName(); | |||
| defaultFixed = linux_getDefaultMonospacedFontName(); | |||
| defaultSans = LinuxFontHelpers::getDefaultSansSerifFontName(); | |||
| defaultSerif = LinuxFontHelpers::getDefaultSerifFontName(); | |||
| defaultFixed = LinuxFontHelpers::getDefaultMonospacedFontName(); | |||
| } | |||
| #endif | |||
| @@ -1115,11 +1115,10 @@ bool NSViewComponentPeer::contains (const Point<int>& position, bool trueIfInACh | |||
| && isPositiveAndBelow (position.getY(), component->getHeight()))) | |||
| return false; | |||
| NSPoint p; | |||
| p.x = (float) position.getX(); | |||
| p.y = (float) position.getY(); | |||
| NSRect frameRect = [view frame]; | |||
| NSView* v = [view hitTest: p]; | |||
| NSView* v = [view hitTest: NSMakePoint (frameRect.origin.x + position.getX(), | |||
| frameRect.origin.y + frameRect.size.height - position.getY())]; | |||
| if (trueIfInAChildWindow) | |||
| return v != nil; | |||