| @@ -32,11 +32,11 @@ package.libpaths = { | |||
| } | |||
| package.config["Debug"].links = { | |||
| "freetype", "pthread", "X11", "GL", "GLU", "Xinerama", "asound" | |||
| "freetype", "pthread", "X11", "GL", "GLU", "Xinerama", "asound", "dl", "Xext" | |||
| } | |||
| package.config["Release"].links = { | |||
| "freetype", "pthread", "X11", "GL", "GLU", "Xinerama", "asound" | |||
| "freetype", "pthread", "X11", "GL", "GLU", "Xinerama", "asound", "dl", "Xext" | |||
| } | |||
| package.linkflags = { "static-runtime" } | |||
| @@ -45,10 +45,6 @@ public: | |||
| setBackgroundColour (Colour (0xffe6f0ff)); | |||
| } | |||
| ~MultiDocHolder() | |||
| { | |||
| } | |||
| bool tryToCloseDocument (Component* component) | |||
| { | |||
| JucerDocumentHolder* const holder = dynamic_cast <JucerDocumentHolder*> (component); | |||
| @@ -41,10 +41,6 @@ public: | |||
| { | |||
| } | |||
| ~ColourEditorComponent() | |||
| { | |||
| } | |||
| void paint (Graphics& g) | |||
| { | |||
| g.fillAll (Colours::grey); | |||
| @@ -104,36 +100,31 @@ private: | |||
| ColourSelectorComp (ColourEditorComponent* owner_, | |||
| const bool canResetToDefault) | |||
| : owner (owner_), | |||
| defaultButton (0) | |||
| defaultButton ("Reset to Default") | |||
| { | |||
| addAndMakeVisible (selector = new ColourSelectorWithSwatches()); | |||
| selector->setName ("Colour"); | |||
| selector->setCurrentColour (owner->getColour()); | |||
| selector->addChangeListener (owner); | |||
| addAndMakeVisible (&selector); | |||
| selector.setName ("Colour"); | |||
| selector.setCurrentColour (owner->getColour()); | |||
| selector.addChangeListener (owner); | |||
| if (canResetToDefault) | |||
| { | |||
| addAndMakeVisible (defaultButton = new TextButton ("Reset to Default")); | |||
| defaultButton->addListener (this); | |||
| addAndMakeVisible (&defaultButton); | |||
| defaultButton.addListener (this); | |||
| } | |||
| } | |||
| ~ColourSelectorComp() | |||
| { | |||
| deleteAllChildren(); | |||
| } | |||
| void resized() | |||
| { | |||
| if (defaultButton != 0) | |||
| if (defaultButton.isVisible()) | |||
| { | |||
| selector->setBounds (0, 0, getWidth(), getHeight() - 30); | |||
| defaultButton->changeWidthToFitText (22); | |||
| defaultButton->setTopLeftPosition (10, getHeight() - 26); | |||
| selector.setBounds (0, 0, getWidth(), getHeight() - 30); | |||
| defaultButton.changeWidthToFitText (22); | |||
| defaultButton.setTopLeftPosition (10, getHeight() - 26); | |||
| } | |||
| else | |||
| { | |||
| selector->setBounds (0, 0, getWidth(), getHeight()); | |||
| selector.setBounds (0, 0, getWidth(), getHeight()); | |||
| } | |||
| } | |||
| @@ -141,7 +132,7 @@ private: | |||
| { | |||
| owner->resetToDefault(); | |||
| owner->refresh(); | |||
| selector->setCurrentColour (owner->getColour()); | |||
| selector.setCurrentColour (owner->getColour()); | |||
| } | |||
| private: | |||
| @@ -152,10 +143,6 @@ private: | |||
| { | |||
| } | |||
| ~ColourSelectorWithSwatches() | |||
| { | |||
| } | |||
| int getNumSwatches() const | |||
| { | |||
| return StoredSettings::getInstance()->swatchColours.size(); | |||
| @@ -173,8 +160,8 @@ private: | |||
| }; | |||
| ColourEditorComponent* owner; | |||
| ColourSelectorWithSwatches* selector; | |||
| TextButton* defaultButton; | |||
| ColourSelectorWithSwatches selector; | |||
| TextButton defaultButton; | |||
| }; | |||
| }; | |||
| @@ -79231,12 +79231,9 @@ public: | |||
| void buttonClicked (Button* button) | |||
| { | |||
| if (button == owner.getMinimiseButton()) | |||
| owner.minimiseButtonPressed(); | |||
| else if (button == owner.getMaximiseButton()) | |||
| owner.maximiseButtonPressed(); | |||
| else if (button == owner.getCloseButton()) | |||
| owner.closeButtonPressed(); | |||
| if (button == owner.getMinimiseButton()) owner.minimiseButtonPressed(); | |||
| else if (button == owner.getMaximiseButton()) owner.maximiseButtonPressed(); | |||
| else if (button == owner.getCloseButton()) owner.closeButtonPressed(); | |||
| } | |||
| private: | |||
| @@ -79490,14 +79487,9 @@ int DocumentWindow::getDesktopWindowStyleFlags() const | |||
| { | |||
| int styleFlags = ResizableWindow::getDesktopWindowStyleFlags(); | |||
| if ((requiredButtons & minimiseButton) != 0) | |||
| styleFlags |= ComponentPeer::windowHasMinimiseButton; | |||
| if ((requiredButtons & maximiseButton) != 0) | |||
| styleFlags |= ComponentPeer::windowHasMaximiseButton; | |||
| if ((requiredButtons & closeButton) != 0) | |||
| styleFlags |= ComponentPeer::windowHasCloseButton; | |||
| if ((requiredButtons & minimiseButton) != 0) styleFlags |= ComponentPeer::windowHasMinimiseButton; | |||
| if ((requiredButtons & maximiseButton) != 0) styleFlags |= ComponentPeer::windowHasMaximiseButton; | |||
| if ((requiredButtons & closeButton) != 0) styleFlags |= ComponentPeer::windowHasCloseButton; | |||
| return styleFlags; | |||
| } | |||
| @@ -79538,11 +79530,11 @@ void DocumentWindow::lookAndFeelChanged() | |||
| if (getCloseButton() != nullptr) | |||
| { | |||
| #if JUCE_MAC | |||
| #if JUCE_MAC | |||
| getCloseButton()->addShortcut (KeyPress ('w', ModifierKeys::commandModifier, 0)); | |||
| #else | |||
| #else | |||
| getCloseButton()->addShortcut (KeyPress (KeyPress::F4Key, ModifierKeys::altModifier, 0)); | |||
| #endif | |||
| #endif | |||
| } | |||
| } | |||
| @@ -97804,22 +97796,19 @@ public: | |||
| : input (in), | |||
| dataBlockIsZero (false), fresh (false), finished (false), | |||
| currentBit (0), lastBit (0), lastByteIndex (0), | |||
| codeSize (0), setCodeSize (0), | |||
| maxCode (0), maxCodeSize (0), | |||
| codeSize (0), setCodeSize (0), maxCode (0), maxCodeSize (0), | |||
| firstcode (0), oldcode (0), clearCode (0), endCode (0) | |||
| { | |||
| int imageWidth, imageHeight; | |||
| int transparent = -1; | |||
| if (! (getSizeFromHeader (imageWidth, imageHeight) | |||
| && imageWidth > 0 && imageHeight > 0)) | |||
| if (! getSizeFromHeader (imageWidth, imageHeight)) | |||
| return; | |||
| unsigned char buf [16]; | |||
| uint8 buf [16]; | |||
| if (in.read (buf, 3) != 3) | |||
| return; | |||
| int numColours = 2 << (buf[0] & 7); | |||
| int transparent = -1; | |||
| if ((buf[0] & 0x80) != 0) | |||
| readPalette (numColours); | |||
| @@ -97831,36 +97820,33 @@ public: | |||
| if (buf[0] == '!') | |||
| { | |||
| if (input.read (buf, 1) != 1) | |||
| break; | |||
| if (processExtension (buf[0], transparent) < 0) | |||
| break; | |||
| if (readExtension (transparent)) | |||
| continue; | |||
| continue; | |||
| break; | |||
| } | |||
| if (buf[0] != ',') | |||
| continue; | |||
| if (input.read (buf, 9) != 9) | |||
| break; | |||
| imageWidth = makeWord (buf[4], buf[5]); | |||
| imageHeight = makeWord (buf[6], buf[7]); | |||
| if (input.read (buf, 9) == 9) | |||
| { | |||
| imageWidth = makeWord (buf[4], buf[5]); | |||
| imageHeight = makeWord (buf[6], buf[7]); | |||
| numColours = 2 << (buf[8] & 7); | |||
| numColours = 2 << (buf[8] & 7); | |||
| if ((buf[8] & 0x80) != 0) | |||
| if (! readPalette (numColours)) | |||
| break; | |||
| if ((buf[8] & 0x80) != 0) | |||
| if (! readPalette (numColours)) | |||
| break; | |||
| image = Image ((transparent >= 0) ? Image::ARGB : Image::RGB, | |||
| imageWidth, imageHeight, (transparent >= 0)); | |||
| image = Image (transparent >= 0 ? Image::ARGB : Image::RGB, | |||
| imageWidth, imageHeight, transparent >= 0); | |||
| image.getProperties()->set ("originalImageHadAlpha", image.hasAlphaChannel()); | |||
| image.getProperties()->set ("originalImageHadAlpha", transparent >= 0); | |||
| readImage ((buf[8] & 0x40) != 0, transparent); | |||
| readImage ((buf[8] & 0x40) != 0, transparent); | |||
| } | |||
| break; | |||
| } | |||
| @@ -97870,8 +97856,8 @@ public: | |||
| private: | |||
| InputStream& input; | |||
| uint8 buffer [300]; | |||
| uint8 palette [256][4]; | |||
| uint8 buffer [260]; | |||
| PixelARGB palette [256]; | |||
| bool dataBlockIsZero, fresh, finished; | |||
| int currentBit, lastBit, lastByteIndex; | |||
| int codeSize, setCodeSize; | |||
| @@ -97885,19 +97871,17 @@ private: | |||
| bool getSizeFromHeader (int& w, int& h) | |||
| { | |||
| char b[8]; | |||
| char b[6]; | |||
| if (input.read (b, 6) == 6) | |||
| if (input.read (b, 6) == 6 | |||
| && (strncmp ("GIF87a", b, 6) == 0 | |||
| || strncmp ("GIF89a", b, 6) == 0)) | |||
| { | |||
| if ((strncmp ("GIF87a", b, 6) == 0) | |||
| || (strncmp ("GIF89a", b, 6) == 0)) | |||
| if (input.read (b, 4) == 4) | |||
| { | |||
| if (input.read (b, 4) == 4) | |||
| { | |||
| w = makeWord (b[0], b[1]); | |||
| h = makeWord (b[2], b[3]); | |||
| return true; | |||
| } | |||
| w = makeWord (b[0], b[1]); | |||
| h = makeWord (b[2], b[3]); | |||
| return w > 0 && h > 0; | |||
| } | |||
| } | |||
| @@ -97906,25 +97890,21 @@ private: | |||
| bool readPalette (const int numCols) | |||
| { | |||
| unsigned char rgb[4]; | |||
| for (int i = 0; i < numCols; ++i) | |||
| { | |||
| uint8 rgb[4]; | |||
| input.read (rgb, 3); | |||
| palette [i][0] = rgb[0]; | |||
| palette [i][1] = rgb[1]; | |||
| palette [i][2] = rgb[2]; | |||
| palette [i][3] = 0xff; | |||
| palette[i].setARGB (0xff, rgb[0], rgb[1], rgb[2]); | |||
| palette[i].premultiply(); | |||
| } | |||
| return true; | |||
| } | |||
| int readDataBlock (unsigned char* dest) | |||
| int readDataBlock (uint8* const dest) | |||
| { | |||
| unsigned char n; | |||
| uint8 n; | |||
| if (input.read (&n, 1) == 1) | |||
| { | |||
| dataBlockIsZero = (n == 0); | |||
| @@ -97936,9 +97916,13 @@ private: | |||
| return -1; | |||
| } | |||
| int processExtension (const int type, int& transparent) | |||
| int readExtension (int& transparent) | |||
| { | |||
| unsigned char b [300]; | |||
| uint8 type; | |||
| if (input.read (&type, 1) != 1) | |||
| return false; | |||
| uint8 b [260]; | |||
| int n = 0; | |||
| if (type == 0xf9) | |||
| @@ -97947,7 +97931,7 @@ private: | |||
| if (n < 0) | |||
| return 1; | |||
| if ((b[0] & 0x1) != 0) | |||
| if ((b[0] & 1) != 0) | |||
| transparent = b[3]; | |||
| } | |||
| @@ -97957,7 +97941,7 @@ private: | |||
| } | |||
| while (n > 0); | |||
| return n; | |||
| return n >= 0; | |||
| } | |||
| void clearTable() | |||
| @@ -98030,7 +98014,7 @@ private: | |||
| if (dataBlockIsZero) | |||
| return -2; | |||
| unsigned char buf [260]; | |||
| uint8 buf [260]; | |||
| int n; | |||
| while ((n = readDataBlock (buf)) > 0) | |||
| @@ -98100,7 +98084,7 @@ private: | |||
| buffer[0] = buffer [lastByteIndex - 2]; | |||
| buffer[1] = buffer [lastByteIndex - 1]; | |||
| const int n = readDataBlock (&buffer[2]); | |||
| const int n = readDataBlock (buffer + 2); | |||
| if (n == 0) | |||
| finished = true; | |||
| @@ -98126,66 +98110,40 @@ private: | |||
| bool readImage (const int interlace, const int transparent) | |||
| { | |||
| { | |||
| unsigned char c; | |||
| if (input.read (&c, 1) != 1) | |||
| return false; | |||
| uint8 c; | |||
| if (input.read (&c, 1) != 1) | |||
| return false; | |||
| initialise (c); | |||
| } | |||
| initialise (c); | |||
| if (transparent >= 0) | |||
| { | |||
| palette [transparent][0] = 0; | |||
| palette [transparent][1] = 0; | |||
| palette [transparent][2] = 0; | |||
| palette [transparent][3] = 0; | |||
| } | |||
| palette [transparent].setARGB (0, 0, 0, 0); | |||
| int index; | |||
| int xpos = 0, ypos = 0, pass = 0; | |||
| int xpos = 0, ypos = 0, yStep = 8, pass = 0; | |||
| const Image::BitmapData destData (image, Image::BitmapData::writeOnly); | |||
| uint8* p = destData.data; | |||
| const bool hasAlpha = image.hasAlphaChannel(); | |||
| uint8* p = destData.getPixelPointer (0, 0); | |||
| while ((index = readLZWByte()) >= 0) | |||
| for (;;) | |||
| { | |||
| const uint8* const paletteEntry = palette [index]; | |||
| if (hasAlpha) | |||
| { | |||
| ((PixelARGB*) p)->setARGB (paletteEntry[3], | |||
| paletteEntry[0], | |||
| paletteEntry[1], | |||
| paletteEntry[2]); | |||
| const int index = readLZWByte(); | |||
| if (index < 0) | |||
| break; | |||
| ((PixelARGB*) p)->premultiply(); | |||
| } | |||
| if (transparent >= 0) | |||
| ((PixelARGB*) p)->set (palette [index]); | |||
| else | |||
| { | |||
| ((PixelRGB*) p)->setARGB (0, | |||
| paletteEntry[0], | |||
| paletteEntry[1], | |||
| paletteEntry[2]); | |||
| } | |||
| ((PixelRGB*) p)->set (palette [index]); | |||
| p += destData.pixelStride; | |||
| ++xpos; | |||
| if (xpos == destData.width) | |||
| if (++xpos == destData.width) | |||
| { | |||
| xpos = 0; | |||
| if (interlace) | |||
| { | |||
| switch (pass) | |||
| { | |||
| case 0: | |||
| case 1: ypos += 8; break; | |||
| case 2: ypos += 4; break; | |||
| case 3: ypos += 2; break; | |||
| } | |||
| ypos += yStep; | |||
| while (ypos >= destData.height) | |||
| { | |||
| @@ -98193,29 +98151,27 @@ private: | |||
| switch (pass) | |||
| { | |||
| case 1: ypos = 4; break; | |||
| case 2: ypos = 2; break; | |||
| case 3: ypos = 1; break; | |||
| case 1: ypos = 4; yStep = 8; break; | |||
| case 2: ypos = 2; yStep = 4; break; | |||
| case 3: ypos = 1; yStep = 2; break; | |||
| default: return true; | |||
| } | |||
| } | |||
| } | |||
| else | |||
| { | |||
| ++ypos; | |||
| if (++ypos >= destData.height) | |||
| break; | |||
| } | |||
| p = destData.getPixelPointer (xpos, ypos); | |||
| } | |||
| if (ypos >= destData.height) | |||
| break; | |||
| } | |||
| return true; | |||
| } | |||
| static inline int makeWord (const uint8 a, const uint8 b) { return (b << 8) | a; } | |||
| static inline int makeWord (const int a, const int b) { return (b << 8) | a; } | |||
| JUCE_DECLARE_NON_COPYABLE (GIFLoader); | |||
| }; | |||
| @@ -281665,21 +281621,20 @@ public: | |||
| void updateSubMenu (NSMenuItem* parentItem, const PopupMenu& menuToCopy, | |||
| const String& name, const int menuId, const int tag) | |||
| { | |||
| [parentItem setTag: tag]; | |||
| NSMenu* menu = [parentItem submenu]; | |||
| [menu setTitle: juceStringToNS (name)]; | |||
| while ([menu numberOfItems] > 0) | |||
| [menu removeItemAtIndex: 0]; | |||
| // Note: This method used to update the contents of the existing menu in-place, but that caused | |||
| // weird side-effects which messed-up keyboard focus when switching between windows. By creating | |||
| // a new menu and replacing the old one with it, that problem seems to be avoided.. | |||
| NSMenu* menu = [[NSMenu alloc] initWithTitle: juceStringToNS (name)]; | |||
| PopupMenu::MenuItemIterator iter (menuToCopy); | |||
| while (iter.next()) | |||
| addMenuItem (iter, menu, menuId, tag); | |||
| [menu setAutoenablesItems: false]; | |||
| [menu update]; | |||
| [parentItem setTag: tag]; | |||
| [parentItem setSubmenu: menu]; | |||
| [menu release]; | |||
| } | |||
| void menuBarItemsChanged (MenuBarModel*) | |||
| @@ -281803,31 +281758,15 @@ public: | |||
| { | |||
| const KeyPress& kp = keyPresses.getReference(0); | |||
| if (kp.getKeyCode() != KeyPress::backspaceKey | |||
| && kp.getKeyCode() != KeyPress::deleteKey) // (adding these is annoying because it flashes the menu bar | |||
| // every time you press the key while editing text) | |||
| if (kp.getKeyCode() != KeyPress::backspaceKey // (adding these is annoying because it flashes the menu bar | |||
| && kp.getKeyCode() != KeyPress::deleteKey) // every time you press the key while editing text) | |||
| { | |||
| juce_wchar key = kp.getTextCharacter(); | |||
| if (kp.getKeyCode() == KeyPress::backspaceKey) | |||
| key = NSBackspaceCharacter; | |||
| else if (kp.getKeyCode() == KeyPress::deleteKey) | |||
| key = NSDeleteCharacter; | |||
| else if (key == 0) | |||
| if (key == 0) | |||
| key = (juce_wchar) kp.getKeyCode(); | |||
| unsigned int mods = 0; | |||
| if (kp.getModifiers().isShiftDown()) | |||
| mods |= NSShiftKeyMask; | |||
| if (kp.getModifiers().isCtrlDown()) | |||
| mods |= NSControlKeyMask; | |||
| if (kp.getModifiers().isAltDown()) | |||
| mods |= NSAlternateKeyMask; | |||
| if (kp.getModifiers().isCommandDown()) | |||
| mods |= NSCommandKeyMask; | |||
| [item setKeyEquivalent: juceStringToNS (String::charToString (key))]; | |||
| [item setKeyEquivalentModifierMask: mods]; | |||
| [item setKeyEquivalentModifierMask: juceModsToNSMods (kp.getModifiers())]; | |||
| } | |||
| } | |||
| } | |||
| @@ -281918,6 +281857,16 @@ private: | |||
| [menu release]; | |||
| } | |||
| static unsigned int juceModsToNSMods (const ModifierKeys& mods) | |||
| { | |||
| unsigned int m = 0; | |||
| if (mods.isShiftDown()) m |= NSShiftKeyMask; | |||
| if (mods.isCtrlDown()) m |= NSControlKeyMask; | |||
| if (mods.isAltDown()) m |= NSAlternateKeyMask; | |||
| if (mods.isCommandDown()) m |= NSCommandKeyMask; | |||
| return m; | |||
| } | |||
| }; | |||
| JuceMainMenuHandler* JuceMainMenuHandler::instance = nullptr; | |||
| @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 93 | |||
| #define JUCE_BUILDNUMBER 94 | |||
| /** Current Juce version number. | |||
| @@ -47268,8 +47268,7 @@ public: | |||
| Call this when the number of rows in the list changes, or if you want it | |||
| to call refreshComponentForRow() on all the row components. | |||
| Be careful not to call it from a different thread, though, as it's not | |||
| thread-safe. | |||
| This must only be called from the main message thread. | |||
| */ | |||
| void updateContent(); | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 93 | |||
| #define JUCE_BUILDNUMBER 94 | |||
| /** Current Juce version number. | |||
| @@ -196,8 +196,7 @@ public: | |||
| Call this when the number of rows in the list changes, or if you want it | |||
| to call refreshComponentForRow() on all the row components. | |||
| Be careful not to call it from a different thread, though, as it's not | |||
| thread-safe. | |||
| This must only be called from the main message thread. | |||
| */ | |||
| void updateContent(); | |||
| @@ -45,12 +45,9 @@ public: | |||
| void buttonClicked (Button* button) | |||
| { | |||
| if (button == owner.getMinimiseButton()) | |||
| owner.minimiseButtonPressed(); | |||
| else if (button == owner.getMaximiseButton()) | |||
| owner.maximiseButtonPressed(); | |||
| else if (button == owner.getCloseButton()) | |||
| owner.closeButtonPressed(); | |||
| if (button == owner.getMinimiseButton()) owner.minimiseButtonPressed(); | |||
| else if (button == owner.getMaximiseButton()) owner.maximiseButtonPressed(); | |||
| else if (button == owner.getCloseButton()) owner.closeButtonPressed(); | |||
| } | |||
| private: | |||
| @@ -309,14 +306,9 @@ int DocumentWindow::getDesktopWindowStyleFlags() const | |||
| { | |||
| int styleFlags = ResizableWindow::getDesktopWindowStyleFlags(); | |||
| if ((requiredButtons & minimiseButton) != 0) | |||
| styleFlags |= ComponentPeer::windowHasMinimiseButton; | |||
| if ((requiredButtons & maximiseButton) != 0) | |||
| styleFlags |= ComponentPeer::windowHasMaximiseButton; | |||
| if ((requiredButtons & closeButton) != 0) | |||
| styleFlags |= ComponentPeer::windowHasCloseButton; | |||
| if ((requiredButtons & minimiseButton) != 0) styleFlags |= ComponentPeer::windowHasMinimiseButton; | |||
| if ((requiredButtons & maximiseButton) != 0) styleFlags |= ComponentPeer::windowHasMaximiseButton; | |||
| if ((requiredButtons & closeButton) != 0) styleFlags |= ComponentPeer::windowHasCloseButton; | |||
| return styleFlags; | |||
| } | |||
| @@ -357,11 +349,11 @@ void DocumentWindow::lookAndFeelChanged() | |||
| if (getCloseButton() != nullptr) | |||
| { | |||
| #if JUCE_MAC | |||
| #if JUCE_MAC | |||
| getCloseButton()->addShortcut (KeyPress ('w', ModifierKeys::commandModifier, 0)); | |||
| #else | |||
| #else | |||
| getCloseButton()->addShortcut (KeyPress (KeyPress::F4Key, ModifierKeys::altModifier, 0)); | |||
| #endif | |||
| #endif | |||
| } | |||
| } | |||
| @@ -45,22 +45,19 @@ public: | |||
| : input (in), | |||
| dataBlockIsZero (false), fresh (false), finished (false), | |||
| currentBit (0), lastBit (0), lastByteIndex (0), | |||
| codeSize (0), setCodeSize (0), | |||
| maxCode (0), maxCodeSize (0), | |||
| codeSize (0), setCodeSize (0), maxCode (0), maxCodeSize (0), | |||
| firstcode (0), oldcode (0), clearCode (0), endCode (0) | |||
| { | |||
| int imageWidth, imageHeight; | |||
| int transparent = -1; | |||
| if (! (getSizeFromHeader (imageWidth, imageHeight) | |||
| && imageWidth > 0 && imageHeight > 0)) | |||
| if (! getSizeFromHeader (imageWidth, imageHeight)) | |||
| return; | |||
| unsigned char buf [16]; | |||
| uint8 buf [16]; | |||
| if (in.read (buf, 3) != 3) | |||
| return; | |||
| int numColours = 2 << (buf[0] & 7); | |||
| int transparent = -1; | |||
| if ((buf[0] & 0x80) != 0) | |||
| readPalette (numColours); | |||
| @@ -72,36 +69,33 @@ public: | |||
| if (buf[0] == '!') | |||
| { | |||
| if (input.read (buf, 1) != 1) | |||
| break; | |||
| if (processExtension (buf[0], transparent) < 0) | |||
| break; | |||
| if (readExtension (transparent)) | |||
| continue; | |||
| continue; | |||
| break; | |||
| } | |||
| if (buf[0] != ',') | |||
| continue; | |||
| if (input.read (buf, 9) != 9) | |||
| break; | |||
| imageWidth = makeWord (buf[4], buf[5]); | |||
| imageHeight = makeWord (buf[6], buf[7]); | |||
| if (input.read (buf, 9) == 9) | |||
| { | |||
| imageWidth = makeWord (buf[4], buf[5]); | |||
| imageHeight = makeWord (buf[6], buf[7]); | |||
| numColours = 2 << (buf[8] & 7); | |||
| numColours = 2 << (buf[8] & 7); | |||
| if ((buf[8] & 0x80) != 0) | |||
| if (! readPalette (numColours)) | |||
| break; | |||
| if ((buf[8] & 0x80) != 0) | |||
| if (! readPalette (numColours)) | |||
| break; | |||
| image = Image ((transparent >= 0) ? Image::ARGB : Image::RGB, | |||
| imageWidth, imageHeight, (transparent >= 0)); | |||
| image = Image (transparent >= 0 ? Image::ARGB : Image::RGB, | |||
| imageWidth, imageHeight, transparent >= 0); | |||
| image.getProperties()->set ("originalImageHadAlpha", image.hasAlphaChannel()); | |||
| image.getProperties()->set ("originalImageHadAlpha", transparent >= 0); | |||
| readImage ((buf[8] & 0x40) != 0, transparent); | |||
| readImage ((buf[8] & 0x40) != 0, transparent); | |||
| } | |||
| break; | |||
| } | |||
| @@ -111,8 +105,8 @@ public: | |||
| private: | |||
| InputStream& input; | |||
| uint8 buffer [300]; | |||
| uint8 palette [256][4]; | |||
| uint8 buffer [260]; | |||
| PixelARGB palette [256]; | |||
| bool dataBlockIsZero, fresh, finished; | |||
| int currentBit, lastBit, lastByteIndex; | |||
| int codeSize, setCodeSize; | |||
| @@ -126,19 +120,17 @@ private: | |||
| bool getSizeFromHeader (int& w, int& h) | |||
| { | |||
| char b[8]; | |||
| char b[6]; | |||
| if (input.read (b, 6) == 6) | |||
| if (input.read (b, 6) == 6 | |||
| && (strncmp ("GIF87a", b, 6) == 0 | |||
| || strncmp ("GIF89a", b, 6) == 0)) | |||
| { | |||
| if ((strncmp ("GIF87a", b, 6) == 0) | |||
| || (strncmp ("GIF89a", b, 6) == 0)) | |||
| if (input.read (b, 4) == 4) | |||
| { | |||
| if (input.read (b, 4) == 4) | |||
| { | |||
| w = makeWord (b[0], b[1]); | |||
| h = makeWord (b[2], b[3]); | |||
| return true; | |||
| } | |||
| w = makeWord (b[0], b[1]); | |||
| h = makeWord (b[2], b[3]); | |||
| return w > 0 && h > 0; | |||
| } | |||
| } | |||
| @@ -147,25 +139,21 @@ private: | |||
| bool readPalette (const int numCols) | |||
| { | |||
| unsigned char rgb[4]; | |||
| for (int i = 0; i < numCols; ++i) | |||
| { | |||
| uint8 rgb[4]; | |||
| input.read (rgb, 3); | |||
| palette [i][0] = rgb[0]; | |||
| palette [i][1] = rgb[1]; | |||
| palette [i][2] = rgb[2]; | |||
| palette [i][3] = 0xff; | |||
| palette[i].setARGB (0xff, rgb[0], rgb[1], rgb[2]); | |||
| palette[i].premultiply(); | |||
| } | |||
| return true; | |||
| } | |||
| int readDataBlock (unsigned char* dest) | |||
| int readDataBlock (uint8* const dest) | |||
| { | |||
| unsigned char n; | |||
| uint8 n; | |||
| if (input.read (&n, 1) == 1) | |||
| { | |||
| dataBlockIsZero = (n == 0); | |||
| @@ -177,9 +165,13 @@ private: | |||
| return -1; | |||
| } | |||
| int processExtension (const int type, int& transparent) | |||
| int readExtension (int& transparent) | |||
| { | |||
| unsigned char b [300]; | |||
| uint8 type; | |||
| if (input.read (&type, 1) != 1) | |||
| return false; | |||
| uint8 b [260]; | |||
| int n = 0; | |||
| if (type == 0xf9) | |||
| @@ -188,7 +180,7 @@ private: | |||
| if (n < 0) | |||
| return 1; | |||
| if ((b[0] & 0x1) != 0) | |||
| if ((b[0] & 1) != 0) | |||
| transparent = b[3]; | |||
| } | |||
| @@ -198,7 +190,7 @@ private: | |||
| } | |||
| while (n > 0); | |||
| return n; | |||
| return n >= 0; | |||
| } | |||
| void clearTable() | |||
| @@ -271,7 +263,7 @@ private: | |||
| if (dataBlockIsZero) | |||
| return -2; | |||
| unsigned char buf [260]; | |||
| uint8 buf [260]; | |||
| int n; | |||
| while ((n = readDataBlock (buf)) > 0) | |||
| @@ -341,7 +333,7 @@ private: | |||
| buffer[0] = buffer [lastByteIndex - 2]; | |||
| buffer[1] = buffer [lastByteIndex - 1]; | |||
| const int n = readDataBlock (&buffer[2]); | |||
| const int n = readDataBlock (buffer + 2); | |||
| if (n == 0) | |||
| finished = true; | |||
| @@ -367,66 +359,40 @@ private: | |||
| bool readImage (const int interlace, const int transparent) | |||
| { | |||
| { | |||
| unsigned char c; | |||
| if (input.read (&c, 1) != 1) | |||
| return false; | |||
| uint8 c; | |||
| if (input.read (&c, 1) != 1) | |||
| return false; | |||
| initialise (c); | |||
| } | |||
| initialise (c); | |||
| if (transparent >= 0) | |||
| { | |||
| palette [transparent][0] = 0; | |||
| palette [transparent][1] = 0; | |||
| palette [transparent][2] = 0; | |||
| palette [transparent][3] = 0; | |||
| } | |||
| palette [transparent].setARGB (0, 0, 0, 0); | |||
| int index; | |||
| int xpos = 0, ypos = 0, pass = 0; | |||
| int xpos = 0, ypos = 0, yStep = 8, pass = 0; | |||
| const Image::BitmapData destData (image, Image::BitmapData::writeOnly); | |||
| uint8* p = destData.data; | |||
| const bool hasAlpha = image.hasAlphaChannel(); | |||
| uint8* p = destData.getPixelPointer (0, 0); | |||
| while ((index = readLZWByte()) >= 0) | |||
| for (;;) | |||
| { | |||
| const uint8* const paletteEntry = palette [index]; | |||
| if (hasAlpha) | |||
| { | |||
| ((PixelARGB*) p)->setARGB (paletteEntry[3], | |||
| paletteEntry[0], | |||
| paletteEntry[1], | |||
| paletteEntry[2]); | |||
| const int index = readLZWByte(); | |||
| if (index < 0) | |||
| break; | |||
| ((PixelARGB*) p)->premultiply(); | |||
| } | |||
| if (transparent >= 0) | |||
| ((PixelARGB*) p)->set (palette [index]); | |||
| else | |||
| { | |||
| ((PixelRGB*) p)->setARGB (0, | |||
| paletteEntry[0], | |||
| paletteEntry[1], | |||
| paletteEntry[2]); | |||
| } | |||
| ((PixelRGB*) p)->set (palette [index]); | |||
| p += destData.pixelStride; | |||
| ++xpos; | |||
| if (xpos == destData.width) | |||
| if (++xpos == destData.width) | |||
| { | |||
| xpos = 0; | |||
| if (interlace) | |||
| { | |||
| switch (pass) | |||
| { | |||
| case 0: | |||
| case 1: ypos += 8; break; | |||
| case 2: ypos += 4; break; | |||
| case 3: ypos += 2; break; | |||
| } | |||
| ypos += yStep; | |||
| while (ypos >= destData.height) | |||
| { | |||
| @@ -434,29 +400,27 @@ private: | |||
| switch (pass) | |||
| { | |||
| case 1: ypos = 4; break; | |||
| case 2: ypos = 2; break; | |||
| case 3: ypos = 1; break; | |||
| case 1: ypos = 4; yStep = 8; break; | |||
| case 2: ypos = 2; yStep = 4; break; | |||
| case 3: ypos = 1; yStep = 2; break; | |||
| default: return true; | |||
| } | |||
| } | |||
| } | |||
| else | |||
| { | |||
| ++ypos; | |||
| if (++ypos >= destData.height) | |||
| break; | |||
| } | |||
| p = destData.getPixelPointer (xpos, ypos); | |||
| } | |||
| if (ypos >= destData.height) | |||
| break; | |||
| } | |||
| return true; | |||
| } | |||
| static inline int makeWord (const uint8 a, const uint8 b) { return (b << 8) | a; } | |||
| static inline int makeWord (const int a, const int b) { return (b << 8) | a; } | |||
| JUCE_DECLARE_NON_COPYABLE (GIFLoader); | |||
| }; | |||
| @@ -109,21 +109,20 @@ public: | |||
| void updateSubMenu (NSMenuItem* parentItem, const PopupMenu& menuToCopy, | |||
| const String& name, const int menuId, const int tag) | |||
| { | |||
| [parentItem setTag: tag]; | |||
| NSMenu* menu = [parentItem submenu]; | |||
| [menu setTitle: juceStringToNS (name)]; | |||
| while ([menu numberOfItems] > 0) | |||
| [menu removeItemAtIndex: 0]; | |||
| // Note: This method used to update the contents of the existing menu in-place, but that caused | |||
| // weird side-effects which messed-up keyboard focus when switching between windows. By creating | |||
| // a new menu and replacing the old one with it, that problem seems to be avoided.. | |||
| NSMenu* menu = [[NSMenu alloc] initWithTitle: juceStringToNS (name)]; | |||
| PopupMenu::MenuItemIterator iter (menuToCopy); | |||
| while (iter.next()) | |||
| addMenuItem (iter, menu, menuId, tag); | |||
| [menu setAutoenablesItems: false]; | |||
| [menu update]; | |||
| [parentItem setTag: tag]; | |||
| [parentItem setSubmenu: menu]; | |||
| [menu release]; | |||
| } | |||
| void menuBarItemsChanged (MenuBarModel*) | |||
| @@ -247,31 +246,15 @@ public: | |||
| { | |||
| const KeyPress& kp = keyPresses.getReference(0); | |||
| if (kp.getKeyCode() != KeyPress::backspaceKey | |||
| && kp.getKeyCode() != KeyPress::deleteKey) // (adding these is annoying because it flashes the menu bar | |||
| // every time you press the key while editing text) | |||
| if (kp.getKeyCode() != KeyPress::backspaceKey // (adding these is annoying because it flashes the menu bar | |||
| && kp.getKeyCode() != KeyPress::deleteKey) // every time you press the key while editing text) | |||
| { | |||
| juce_wchar key = kp.getTextCharacter(); | |||
| if (kp.getKeyCode() == KeyPress::backspaceKey) | |||
| key = NSBackspaceCharacter; | |||
| else if (kp.getKeyCode() == KeyPress::deleteKey) | |||
| key = NSDeleteCharacter; | |||
| else if (key == 0) | |||
| if (key == 0) | |||
| key = (juce_wchar) kp.getKeyCode(); | |||
| unsigned int mods = 0; | |||
| if (kp.getModifiers().isShiftDown()) | |||
| mods |= NSShiftKeyMask; | |||
| if (kp.getModifiers().isCtrlDown()) | |||
| mods |= NSControlKeyMask; | |||
| if (kp.getModifiers().isAltDown()) | |||
| mods |= NSAlternateKeyMask; | |||
| if (kp.getModifiers().isCommandDown()) | |||
| mods |= NSCommandKeyMask; | |||
| [item setKeyEquivalent: juceStringToNS (String::charToString (key))]; | |||
| [item setKeyEquivalentModifierMask: mods]; | |||
| [item setKeyEquivalentModifierMask: juceModsToNSMods (kp.getModifiers())]; | |||
| } | |||
| } | |||
| } | |||
| @@ -362,6 +345,16 @@ private: | |||
| [menu release]; | |||
| } | |||
| static unsigned int juceModsToNSMods (const ModifierKeys& mods) | |||
| { | |||
| unsigned int m = 0; | |||
| if (mods.isShiftDown()) m |= NSShiftKeyMask; | |||
| if (mods.isCtrlDown()) m |= NSControlKeyMask; | |||
| if (mods.isAltDown()) m |= NSAlternateKeyMask; | |||
| if (mods.isCommandDown()) m |= NSCommandKeyMask; | |||
| return m; | |||
| } | |||
| }; | |||
| JuceMainMenuHandler* JuceMainMenuHandler::instance = nullptr; | |||