| @@ -128,7 +128,7 @@ public: | |||
| glPixelStorei (GL_UNPACK_ALIGNMENT, 4); | |||
| Image::BitmapData srcData (image, false); | |||
| Image::BitmapData srcData (image, Image::BitmapData::readOnly); | |||
| glTexImage2D (GL_TEXTURE_2D, 0, 4, image.getWidth(), image.getHeight(), | |||
| 0, GL_RGB, | |||
| @@ -222,6 +222,13 @@ void JuceDemoPluginAudioProcessor::releaseResources() | |||
| keyboardState.reset(); | |||
| } | |||
| void JuceDemoPluginAudioProcessor::reset() | |||
| { | |||
| // Use this method as the place to clear any delay lines, buffers, etc, as it | |||
| // means there's been a break in the audio's continuity. | |||
| delayBuffer.clear(); | |||
| } | |||
| void JuceDemoPluginAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) | |||
| { | |||
| const int numSamples = buffer.getNumSamples(); | |||
| @@ -28,8 +28,8 @@ public: | |||
| //============================================================================== | |||
| void prepareToPlay (double sampleRate, int samplesPerBlock); | |||
| void releaseResources(); | |||
| void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages); | |||
| void reset(); | |||
| //============================================================================== | |||
| bool hasEditor() const { return true; } | |||
| @@ -73,11 +73,6 @@ BEGIN_JUCE_NAMESPACE | |||
| #pragma pack (pop) | |||
| #endif | |||
| #if defined (JUCE_DLL) && ! (JUCE_AMALGAMATED_TEMPLATE || defined (JUCE_DLL_BUILD)) | |||
| #undef JUCE_LEAK_DETECTOR | |||
| #define JUCE_LEAK_DETECTOR(OwnerClass) | |||
| #endif | |||
| END_JUCE_NAMESPACE | |||
| @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 28 | |||
| #define JUCE_BUILDNUMBER 29 | |||
| /** Current Juce version number. | |||
| @@ -2371,7 +2371,7 @@ inline Type Atomic<Type>::operator++() throw() | |||
| return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value) | |||
| : (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value); | |||
| #elif JUCE_ATOMICS_ANDROID | |||
| return (Type) __atomic_inc ((volatile int*) &value); | |||
| return (Type) (__atomic_inc ((volatile int*) &value) + 1); | |||
| #elif JUCE_ATOMICS_GCC | |||
| return (Type) __sync_add_and_fetch (&value, 1); | |||
| #endif | |||
| @@ -2387,7 +2387,7 @@ inline Type Atomic<Type>::operator--() throw() | |||
| return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value) | |||
| : (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value); | |||
| #elif JUCE_ATOMICS_ANDROID | |||
| return (Type) __atomic_dec ((volatile int*) &value); | |||
| return (Type) (__atomic_dec ((volatile int*) &value) - 1); | |||
| #elif JUCE_ATOMICS_GCC | |||
| return (Type) __sync_add_and_fetch (&value, -1); | |||
| #endif | |||
| @@ -26479,7 +26479,9 @@ public: | |||
| { | |||
| } | |||
| forcedinline uint32 getARGB() const throw() { return argb; } | |||
| forcedinline uint32 getARGB() const throw() { return argb; } | |||
| forcedinline uint32 getUnpremultipliedARGB() const throw() { PixelARGB p (argb); p.unpremultiply(); return p.getARGB(); } | |||
| forcedinline uint32 getRB() const throw() { return 0x00ff00ff & argb; } | |||
| forcedinline uint32 getAG() const throw() { return 0x00ff00ff & (argb >> 8); } | |||
| @@ -26710,7 +26712,9 @@ public: | |||
| b = (uint8) (argb); | |||
| } | |||
| forcedinline uint32 getARGB() const throw() { return 0xff000000 | b | (g << 8) | (r << 16); } | |||
| forcedinline uint32 getARGB() const throw() { return 0xff000000 | b | (g << 8) | (r << 16); } | |||
| forcedinline uint32 getUnpremultipliedARGB() const throw() { return getARGB(); } | |||
| forcedinline uint32 getRB() const throw() { return b | (uint32) (r << 16); } | |||
| forcedinline uint32 getAG() const throw() { return 0xff0000 | g; } | |||
| @@ -26872,7 +26876,9 @@ public: | |||
| a = (uint8) (argb >> 24); | |||
| } | |||
| forcedinline uint32 getARGB() const throw() { return (((uint32) a) << 24) | (((uint32) a) << 16) | (((uint32) a) << 8) | a; } | |||
| forcedinline uint32 getARGB() const throw() { return (((uint32) a) << 24) | (((uint32) a) << 16) | (((uint32) a) << 8) | a; } | |||
| forcedinline uint32 getUnpremultipliedARGB() const throw() { return (((uint32) a) << 24) | 0xffffff; } | |||
| forcedinline uint32 getRB() const throw() { return (((uint32) a) << 16) | a; } | |||
| forcedinline uint32 getAG() const throw() { return (((uint32) a) << 16) | a; } | |||
| @@ -28625,9 +28631,16 @@ public: | |||
| class BitmapData | |||
| { | |||
| public: | |||
| BitmapData (Image& image, int x, int y, int w, int h, bool needsToBeWritable); | |||
| enum ReadWriteMode | |||
| { | |||
| readOnly, | |||
| writeOnly, | |||
| readWrite | |||
| }; | |||
| BitmapData (Image& image, int x, int y, int w, int h, ReadWriteMode mode); | |||
| BitmapData (const Image& image, int x, int y, int w, int h); | |||
| BitmapData (const Image& image, bool needsToBeWritable); | |||
| BitmapData (const Image& image, ReadWriteMode mode); | |||
| ~BitmapData(); | |||
| /** Returns a pointer to the start of a line in the image. | |||
| @@ -28655,9 +28668,20 @@ public: | |||
| void setPixelColour (int x, int y, const Colour& colour) const throw(); | |||
| uint8* data; | |||
| const PixelFormat pixelFormat; | |||
| PixelFormat pixelFormat; | |||
| int lineStride, pixelStride, width, height; | |||
| /** Used internally by custom image types to manage pixel data lifetime. */ | |||
| class BitmapDataReleaser | |||
| { | |||
| protected: | |||
| BitmapDataReleaser() {} | |||
| public: | |||
| virtual ~BitmapDataReleaser() {} | |||
| }; | |||
| ScopedPointer<BitmapDataReleaser> dataReleaser; | |||
| private: | |||
| JUCE_DECLARE_NON_COPYABLE (BitmapData); | |||
| }; | |||
| @@ -28717,6 +28741,7 @@ public: | |||
| virtual LowLevelGraphicsContext* createLowLevelContext() = 0; | |||
| virtual SharedImage* clone() = 0; | |||
| virtual ImageType getType() const = 0; | |||
| virtual void initialiseBitmapData (BitmapData& bitmapData, int x, int y, BitmapData::ReadWriteMode mode) = 0; | |||
| static SharedImage* createNativeImage (PixelFormat format, int width, int height, bool clearImage); | |||
| static SharedImage* createSoftwareImage (PixelFormat format, int width, int height, bool clearImage); | |||
| @@ -28724,17 +28749,12 @@ public: | |||
| const PixelFormat getPixelFormat() const throw() { return format; } | |||
| int getWidth() const throw() { return width; } | |||
| int getHeight() const throw() { return height; } | |||
| int getPixelStride() const throw() { return pixelStride; } | |||
| int getLineStride() const throw() { return lineStride; } | |||
| uint8* getPixelData (int x, int y) const throw(); | |||
| protected: | |||
| friend class Image; | |||
| friend class BitmapData; | |||
| const PixelFormat format; | |||
| const int width, height; | |||
| int pixelStride, lineStride; | |||
| uint8* imageData; | |||
| NamedValueSet userData; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SharedImage); | |||
| @@ -28938,7 +28958,7 @@ public: | |||
| const Path toPath() const; | |||
| /** An iterator for accessing all the rectangles in a RectangleList. */ | |||
| class Iterator | |||
| class JUCE_API Iterator | |||
| { | |||
| public: | |||
| @@ -38944,7 +38964,7 @@ public: | |||
| @see MidiBuffer | |||
| */ | |||
| class Iterator | |||
| class JUCE_API Iterator | |||
| { | |||
| public: | |||
| @@ -50326,7 +50346,7 @@ public: | |||
| @see CodeDocument, SyntaxAnalyser | |||
| */ | |||
| class Iterator | |||
| class JUCE_API Iterator | |||
| { | |||
| public: | |||
| Iterator (CodeDocument* document); | |||
| @@ -66216,11 +66236,6 @@ private: | |||
| #pragma pack (pop) | |||
| #endif | |||
| #if defined (JUCE_DLL) && ! (JUCE_AMALGAMATED_TEMPLATE || defined (JUCE_DLL_BUILD)) | |||
| #undef JUCE_LEAK_DETECTOR | |||
| #define JUCE_LEAK_DETECTOR(OwnerClass) | |||
| #endif | |||
| END_JUCE_NAMESPACE | |||
| #ifndef DONT_SET_USING_JUCE_NAMESPACE | |||
| @@ -291,7 +291,7 @@ public: | |||
| startSampleInFile += samplesReceived; | |||
| numSamples -= samplesReceived; | |||
| if ((outFlags & kQTMovieAudioExtractionComplete) != 0 && numSamples > 0) | |||
| if (((outFlags & kQTMovieAudioExtractionComplete) != 0 || samplesReceived == 0) && numSamples > 0) | |||
| { | |||
| for (int j = numDestChannels; --j >= 0;) | |||
| if (destSamples[j] != 0) | |||
| @@ -170,7 +170,7 @@ public: | |||
| @see MidiBuffer | |||
| */ | |||
| class Iterator | |||
| class JUCE_API Iterator | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| @@ -265,6 +265,8 @@ public: | |||
| void setStateInformation (const void* data, int sizeInBytes); | |||
| void setCurrentProgramStateInformation (const void* data, int sizeInBytes); | |||
| void refreshParameterListFromPlugin(); | |||
| private: | |||
| //============================================================================== | |||
| friend class AudioUnitPluginWindowCarbon; | |||
| @@ -287,7 +289,6 @@ private: | |||
| //============================================================================== | |||
| bool getComponentDescFromFile (const String& fileOrIdentifier); | |||
| void setPluginCallbacks(); | |||
| void getParameterListFromPlugin(); | |||
| //============================================================================== | |||
| OSStatus renderGetInput (AudioUnitRenderActionFlags* ioActionFlags, | |||
| @@ -535,7 +536,7 @@ bool AudioUnitPluginInstance::getComponentDescFromFile (const String& fileOrIden | |||
| //============================================================================== | |||
| void AudioUnitPluginInstance::initialise() | |||
| { | |||
| getParameterListFromPlugin(); | |||
| refreshParameterListFromPlugin(); | |||
| setPluginCallbacks(); | |||
| int numIns, numOuts; | |||
| @@ -544,7 +545,7 @@ void AudioUnitPluginInstance::initialise() | |||
| setLatencySamples (0); | |||
| } | |||
| void AudioUnitPluginInstance::getParameterListFromPlugin() | |||
| void AudioUnitPluginInstance::refreshParameterListFromPlugin() | |||
| { | |||
| parameterIds.clear(); | |||
| @@ -559,7 +560,7 @@ void AudioUnitPluginInstance::getParameterListFromPlugin() | |||
| parameterIds.insertMultiple (0, 0, paramListSize / sizeof (int)); | |||
| AudioUnitGetProperty (audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, | |||
| 0, ¶meterIds.getReference(0), ¶mListSize); | |||
| 0, parameterIds.getRawDataPointer(), ¶mListSize); | |||
| } | |||
| } | |||
| } | |||
| @@ -231,7 +231,9 @@ public: | |||
| a.memoryBarrier(); | |||
| a -= (Type) 5; | |||
| test.expect (a.get() == (Type) 20); | |||
| ++a; ++a; --a; | |||
| test.expect (++a == (Type) 21); | |||
| ++a; | |||
| test.expect (--a == (Type) 21); | |||
| test.expect (a.get() == (Type) 21); | |||
| a.memoryBarrier(); | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 28 | |||
| #define JUCE_BUILDNUMBER 29 | |||
| /** Current Juce version number. | |||
| @@ -127,7 +127,7 @@ void MessageManager::deliverMessage (Message* const message) | |||
| } | |||
| //============================================================================== | |||
| #if ! (JUCE_MAC || JUCE_IOS) | |||
| #if ! (JUCE_MAC || JUCE_IOS || JUCE_ANDROID) | |||
| void MessageManager::runDispatchLoop() | |||
| { | |||
| jassert (isThisTheMessageThread()); // must only be called by the message thread | |||
| @@ -336,7 +336,7 @@ public: | |||
| @see CodeDocument, SyntaxAnalyser | |||
| */ | |||
| class Iterator | |||
| class JUCE_API Iterator | |||
| { | |||
| public: | |||
| Iterator (CodeDocument* document); | |||
| @@ -103,7 +103,7 @@ public: | |||
| const int height = getHeight() / 2; | |||
| colours = Image (Image::RGB, width, height, false); | |||
| Image::BitmapData pixels (colours, true); | |||
| Image::BitmapData pixels (colours, Image::BitmapData::writeOnly); | |||
| for (int y = 0; y < height; ++y) | |||
| { | |||
| @@ -42,6 +42,7 @@ | |||
| class PixelRGB; | |||
| class PixelAlpha; | |||
| //============================================================================== | |||
| /** | |||
| Represents a 32-bit ARGB pixel with premultiplied alpha, and can perform compositing | |||
| operations with it. | |||
| @@ -64,7 +65,9 @@ public: | |||
| { | |||
| } | |||
| forcedinline uint32 getARGB() const throw() { return argb; } | |||
| forcedinline uint32 getARGB() const throw() { return argb; } | |||
| forcedinline uint32 getUnpremultipliedARGB() const throw() { PixelARGB p (argb); p.unpremultiply(); return p.getARGB(); } | |||
| forcedinline uint32 getRB() const throw() { return 0x00ff00ff & argb; } | |||
| forcedinline uint32 getAG() const throw() { return 0x00ff00ff & (argb >> 8); } | |||
| @@ -300,7 +303,9 @@ public: | |||
| b = (uint8) (argb); | |||
| } | |||
| forcedinline uint32 getARGB() const throw() { return 0xff000000 | b | (g << 8) | (r << 16); } | |||
| forcedinline uint32 getARGB() const throw() { return 0xff000000 | b | (g << 8) | (r << 16); } | |||
| forcedinline uint32 getUnpremultipliedARGB() const throw() { return getARGB(); } | |||
| forcedinline uint32 getRB() const throw() { return b | (uint32) (r << 16); } | |||
| forcedinline uint32 getAG() const throw() { return 0xff0000 | g; } | |||
| @@ -464,7 +469,9 @@ public: | |||
| a = (uint8) (argb >> 24); | |||
| } | |||
| forcedinline uint32 getARGB() const throw() { return (((uint32) a) << 24) | (((uint32) a) << 16) | (((uint32) a) << 8) | a; } | |||
| forcedinline uint32 getARGB() const throw() { return (((uint32) a) << 24) | (((uint32) a) << 16) | (((uint32) a) << 8) | a; } | |||
| forcedinline uint32 getUnpremultipliedARGB() const throw() { return (((uint32) a) << 24) | 0xffffff; } | |||
| forcedinline uint32 getRB() const throw() { return (((uint32) a) << 16) | a; } | |||
| forcedinline uint32 getAG() const throw() { return (((uint32) a) << 16) | a; } | |||
| @@ -1273,7 +1273,7 @@ public: | |||
| const Ptr clipToImageAlpha (const Image& image, const AffineTransform& transform, const bool betterQuality) | |||
| { | |||
| const Image::BitmapData srcData (image, false); | |||
| const Image::BitmapData srcData (image, Image::BitmapData::readOnly); | |||
| if (transform.isOnlyTranslation()) | |||
| { | |||
| @@ -2010,7 +2010,7 @@ public: | |||
| { | |||
| if (fillType.isColour()) | |||
| { | |||
| Image::BitmapData destData (image, true); | |||
| Image::BitmapData destData (image, Image::BitmapData::readWrite); | |||
| clip->fillRectWithColour (destData, r.translated (xOffset, yOffset), fillType.colour.getPixelARGB(), replaceContents); | |||
| } | |||
| else | |||
| @@ -2039,7 +2039,7 @@ public: | |||
| { | |||
| if (fillType.isColour()) | |||
| { | |||
| Image::BitmapData destData (image, true); | |||
| Image::BitmapData destData (image, Image::BitmapData::readWrite); | |||
| clip->fillRectWithColour (destData, r.translated ((float) xOffset, (float) yOffset), fillType.colour.getPixelARGB()); | |||
| } | |||
| else | |||
| @@ -2087,7 +2087,7 @@ public: | |||
| if (shapeToFill != 0) | |||
| { | |||
| Image::BitmapData destData (image, true); | |||
| Image::BitmapData destData (image, Image::BitmapData::readWrite); | |||
| if (fillType.isGradient()) | |||
| { | |||
| @@ -2125,8 +2125,8 @@ public: | |||
| { | |||
| const AffineTransform transform (getTransformWith (t)); | |||
| const Image::BitmapData destData (image, true); | |||
| const Image::BitmapData srcData (sourceImage, false); | |||
| const Image::BitmapData destData (image, Image::BitmapData::readWrite); | |||
| const Image::BitmapData srcData (sourceImage, Image::BitmapData::readOnly); | |||
| const int alpha = fillType.colour.getAlpha(); | |||
| const bool betterQuality = (interpolationQuality != Graphics::lowResamplingQuality); | |||
| @@ -66,38 +66,40 @@ void DropShadowEffect::applyEffect (Image& image, Graphics& g, float alpha) | |||
| Image shadowImage (Image::SingleChannel, w, h, false); | |||
| const Image::BitmapData srcData (image, false); | |||
| const Image::BitmapData destData (shadowImage, true); | |||
| const int filter = roundToInt (63.0f / radius); | |||
| const int radiusMinus1 = roundToInt ((radius - 1.0f) * 63.0f); | |||
| for (int x = w; --x >= 0;) | |||
| { | |||
| int shadowAlpha = 0; | |||
| const Image::BitmapData srcData (image, Image::BitmapData::readOnly); | |||
| const Image::BitmapData destData (shadowImage, Image::BitmapData::readWrite); | |||
| const PixelARGB* src = ((const PixelARGB*) srcData.data) + x; | |||
| uint8* shadowPix = destData.data + x; | |||
| const int filter = roundToInt (63.0f / radius); | |||
| const int radiusMinus1 = roundToInt ((radius - 1.0f) * 63.0f); | |||
| for (int y = h; --y >= 0;) | |||
| for (int x = w; --x >= 0;) | |||
| { | |||
| shadowAlpha = ((shadowAlpha * radiusMinus1 + (src->getAlpha() << 6)) * filter) >> 12; | |||
| int shadowAlpha = 0; | |||
| *shadowPix = (uint8) shadowAlpha; | |||
| src = (const PixelARGB*) (((const uint8*) src) + srcData.lineStride); | |||
| shadowPix += destData.lineStride; | |||
| } | |||
| } | |||
| const PixelARGB* src = ((const PixelARGB*) srcData.data) + x; | |||
| uint8* shadowPix = destData.data + x; | |||
| for (int y = h; --y >= 0;) | |||
| { | |||
| int shadowAlpha = 0; | |||
| uint8* shadowPix = destData.getLinePointer (y); | |||
| for (int y = h; --y >= 0;) | |||
| { | |||
| shadowAlpha = ((shadowAlpha * radiusMinus1 + (src->getAlpha() << 6)) * filter) >> 12; | |||
| for (int x = w; --x >= 0;) | |||
| *shadowPix = (uint8) shadowAlpha; | |||
| src = addBytesToPointer (src, srcData.lineStride); | |||
| shadowPix += destData.lineStride; | |||
| } | |||
| } | |||
| for (int y = h; --y >= 0;) | |||
| { | |||
| shadowAlpha = ((shadowAlpha * radiusMinus1 + (*shadowPix << 6)) * filter) >> 12; | |||
| *shadowPix++ = (uint8) shadowAlpha; | |||
| int shadowAlpha = 0; | |||
| uint8* shadowPix = destData.getLinePointer (y); | |||
| for (int x = w; --x >= 0;) | |||
| { | |||
| shadowAlpha = ((shadowAlpha * radiusMinus1 + (*shadowPix << 6)) * filter) >> 12; | |||
| *shadowPix++ = (uint8) shadowAlpha; | |||
| } | |||
| } | |||
| } | |||
| @@ -214,7 +214,7 @@ public: | |||
| //============================================================================== | |||
| /** An iterator for accessing all the rectangles in a RectangleList. */ | |||
| class Iterator | |||
| class JUCE_API Iterator | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| @@ -400,7 +400,7 @@ private: | |||
| int index; | |||
| int xpos = 0, ypos = 0, pass = 0; | |||
| const Image::BitmapData destData (image, true); | |||
| const Image::BitmapData destData (image, Image::BitmapData::writeOnly); | |||
| uint8* p = destData.data; | |||
| const bool hasAlpha = image.hasAlphaChannel(); | |||
| @@ -307,7 +307,7 @@ const Image JPEGImageFormat::decodeImage (InputStream& in) | |||
| image.getProperties()->set ("originalImageHadAlpha", false); | |||
| const bool hasAlphaChan = image.hasAlphaChannel(); // (the native image creator may not give back what we expect) | |||
| const Image::BitmapData destData (image, true); | |||
| const Image::BitmapData destData (image, Image::BitmapData::writeOnly); | |||
| for (int y = 0; y < height; ++y) | |||
| { | |||
| @@ -411,7 +411,7 @@ bool JPEGImageFormat::writeImageToStream (const Image& image, OutputStream& out) | |||
| JSAMPARRAY buffer = (*jpegCompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegCompStruct, | |||
| JPOOL_IMAGE, strideBytes, 1); | |||
| const Image::BitmapData srcData (image, false); | |||
| const Image::BitmapData srcData (image, Image::BitmapData::readOnly); | |||
| while (jpegCompStruct.next_scanline < jpegCompStruct.image_height) | |||
| { | |||
| @@ -234,7 +234,7 @@ const Image PNGImageFormat::decodeImage (InputStream& in) | |||
| image.getProperties()->set ("originalImageHadAlpha", image.hasAlphaChannel()); | |||
| hasAlphaChan = image.hasAlphaChannel(); // (the native image creator may not give back what we expect) | |||
| const Image::BitmapData destData (image, true); | |||
| const Image::BitmapData destData (image, Image::BitmapData::writeOnly); | |||
| uint8* srcRow = tempBuffer; | |||
| uint8* destRow = destData.data; | |||
| @@ -313,7 +313,7 @@ bool PNGImageFormat::writeImageToStream (const Image& image, OutputStream& out) | |||
| png_set_shift (pngWriteStruct, &sig_bit); | |||
| png_set_packing (pngWriteStruct); | |||
| const Image::BitmapData srcData (image, false); | |||
| const Image::BitmapData srcData (image, Image::BitmapData::readOnly); | |||
| for (int y = 0; y < height; ++y) | |||
| { | |||
| @@ -46,23 +46,16 @@ Image::SharedImage::~SharedImage() | |||
| { | |||
| } | |||
| inline uint8* Image::SharedImage::getPixelData (const int x, const int y) const throw() | |||
| { | |||
| return imageData + lineStride * y + pixelStride * x; | |||
| } | |||
| //============================================================================== | |||
| class SoftwareSharedImage : public Image::SharedImage | |||
| { | |||
| public: | |||
| SoftwareSharedImage (const Image::PixelFormat format_, const int width_, const int height_, const bool clearImage) | |||
| : Image::SharedImage (format_, width_, height_) | |||
| : Image::SharedImage (format_, width_, height_), | |||
| pixelStride (format_ == Image::RGB ? 3 : ((format_ == Image::ARGB) ? 4 : 1)), | |||
| lineStride ((pixelStride * jmax (1, width_) + 3) & ~3) | |||
| { | |||
| pixelStride = format_ == Image::RGB ? 3 : ((format_ == Image::ARGB) ? 4 : 1); | |||
| lineStride = (pixelStride * jmax (1, width) + 3) & ~3; | |||
| imageDataAllocated.allocate (lineStride * jmax (1, height), clearImage); | |||
| imageData = imageDataAllocated; | |||
| imageData.allocate (lineStride * jmax (1, height_), clearImage); | |||
| } | |||
| Image::ImageType getType() const | |||
| @@ -75,6 +68,14 @@ public: | |||
| return new LowLevelGraphicsSoftwareRenderer (Image (this)); | |||
| } | |||
| void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode /*mode*/) | |||
| { | |||
| bitmap.data = imageData + x * pixelStride + y * lineStride; | |||
| bitmap.pixelFormat = format; | |||
| bitmap.lineStride = lineStride; | |||
| bitmap.pixelStride = pixelStride; | |||
| } | |||
| Image::SharedImage* clone() | |||
| { | |||
| SoftwareSharedImage* s = new SoftwareSharedImage (format, width, height, false); | |||
| @@ -83,7 +84,8 @@ public: | |||
| } | |||
| private: | |||
| HeapBlock<uint8> imageDataAllocated; | |||
| HeapBlock<uint8> imageData; | |||
| const int pixelStride, lineStride; | |||
| JUCE_LEAK_DETECTOR (SoftwareSharedImage); | |||
| }; | |||
| @@ -101,9 +103,6 @@ public: | |||
| : Image::SharedImage (image_->getPixelFormat(), area_.getWidth(), area_.getHeight()), | |||
| image (image_), area (area_) | |||
| { | |||
| pixelStride = image_->getPixelStride(); | |||
| lineStride = image_->getLineStride(); | |||
| imageData = image_->getPixelData (area_.getX(), area_.getY()); | |||
| } | |||
| Image::ImageType getType() const | |||
| @@ -119,6 +118,11 @@ public: | |||
| return g; | |||
| } | |||
| void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode mode) | |||
| { | |||
| image->initialiseBitmapData (bitmap, x + area.getX(), y + area.getY(), mode); | |||
| } | |||
| Image::SharedImage* clone() | |||
| { | |||
| return new SubsectionSharedImage (image->clone(), area); | |||
| @@ -220,7 +224,7 @@ const Image Image::convertedToFormat (PixelFormat newFormat) const | |||
| } | |||
| else | |||
| { | |||
| const BitmapData destData (newImage, 0, 0, w, h, true); | |||
| const BitmapData destData (newImage, 0, 0, w, h, BitmapData::writeOnly); | |||
| const BitmapData srcData (*this, 0, 0, w, h); | |||
| for (int y = 0; y < h; ++y) | |||
| @@ -254,37 +258,39 @@ NamedValueSet* Image::getProperties() const | |||
| } | |||
| //============================================================================== | |||
| Image::BitmapData::BitmapData (Image& image, const int x, const int y, const int w, const int h, const bool /*makeWritable*/) | |||
| : data (image.image == 0 ? 0 : image.image->getPixelData (x, y)), | |||
| pixelFormat (image.getFormat()), | |||
| lineStride (image.image == 0 ? 0 : image.image->lineStride), | |||
| pixelStride (image.image == 0 ? 0 : image.image->pixelStride), | |||
| width (w), | |||
| Image::BitmapData::BitmapData (Image& image, const int x, const int y, const int w, const int h, BitmapData::ReadWriteMode mode) | |||
| : width (w), | |||
| height (h) | |||
| { | |||
| jassert (data != 0); | |||
| // The BitmapData class must be given a valid image, and a valid rectangle within it! | |||
| jassert (image.image != 0); | |||
| jassert (x >= 0 && y >= 0 && w > 0 && h > 0 && x + w <= image.getWidth() && y + h <= image.getHeight()); | |||
| image.image->initialiseBitmapData (*this, x, y, mode); | |||
| jassert (data != 0 && pixelStride > 0 && lineStride != 0); | |||
| } | |||
| Image::BitmapData::BitmapData (const Image& image, const int x, const int y, const int w, const int h) | |||
| : data (image.image == 0 ? 0 : image.image->getPixelData (x, y)), | |||
| pixelFormat (image.getFormat()), | |||
| lineStride (image.image == 0 ? 0 : image.image->lineStride), | |||
| pixelStride (image.image == 0 ? 0 : image.image->pixelStride), | |||
| width (w), | |||
| : width (w), | |||
| height (h) | |||
| { | |||
| // The BitmapData class must be given a valid image, and a valid rectangle within it! | |||
| jassert (image.image != 0); | |||
| jassert (x >= 0 && y >= 0 && w > 0 && h > 0 && x + w <= image.getWidth() && y + h <= image.getHeight()); | |||
| image.image->initialiseBitmapData (*this, x, y, readOnly); | |||
| jassert (data != 0 && pixelStride > 0 && lineStride != 0); | |||
| } | |||
| Image::BitmapData::BitmapData (const Image& image, bool /*needsToBeWritable*/) | |||
| : data (image.image == 0 ? 0 : image.image->imageData), | |||
| pixelFormat (image.getFormat()), | |||
| lineStride (image.image == 0 ? 0 : image.image->lineStride), | |||
| pixelStride (image.image == 0 ? 0 : image.image->pixelStride), | |||
| width (image.getWidth()), | |||
| Image::BitmapData::BitmapData (const Image& image, BitmapData::ReadWriteMode mode) | |||
| : width (image.getWidth()), | |||
| height (image.getHeight()) | |||
| { | |||
| // The BitmapData class must be given a valid image! | |||
| jassert (image.image != 0); | |||
| image.image->initialiseBitmapData (*this, 0, 0, mode); | |||
| jassert (data != 0 && pixelStride > 0 && lineStride != 0); | |||
| } | |||
| Image::BitmapData::~BitmapData() | |||
| @@ -299,21 +305,10 @@ const Colour Image::BitmapData::getPixelColour (const int x, const int y) const | |||
| switch (pixelFormat) | |||
| { | |||
| case Image::ARGB: | |||
| { | |||
| PixelARGB p (*(const PixelARGB*) pixel); | |||
| p.unpremultiply(); | |||
| return Colour (p.getARGB()); | |||
| } | |||
| case Image::RGB: | |||
| return Colour (((const PixelRGB*) pixel)->getARGB()); | |||
| case Image::SingleChannel: | |||
| return Colour ((uint8) 0, (uint8) 0, (uint8) 0, *pixel); | |||
| default: | |||
| jassertfalse; | |||
| break; | |||
| 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; | |||
| } | |||
| return Colour(); | |||
| @@ -342,7 +337,7 @@ void Image::setPixelData (int x, int y, int w, int h, | |||
| if (Rectangle<int>::intersectRectangles (x, y, w, h, 0, 0, getWidth(), getHeight())) | |||
| { | |||
| const BitmapData dest (*this, x, y, w, h, true); | |||
| const BitmapData dest (*this, x, y, w, h, BitmapData::writeOnly); | |||
| for (int i = 0; i < h; ++i) | |||
| { | |||
| @@ -362,7 +357,7 @@ void Image::clear (const Rectangle<int>& area, const Colour& colourToClearTo) | |||
| { | |||
| const PixelARGB col (colourToClearTo.getPixelARGB()); | |||
| const BitmapData destData (*this, clipped.getX(), clipped.getY(), clipped.getWidth(), clipped.getHeight(), true); | |||
| const BitmapData destData (*this, clipped.getX(), clipped.getY(), clipped.getWidth(), clipped.getHeight(), BitmapData::writeOnly); | |||
| uint8* dest = destData.data; | |||
| int dh = clipped.getHeight(); | |||
| @@ -415,7 +410,7 @@ void Image::setPixelAt (const int x, const int y, const Colour& colour) | |||
| { | |||
| if (isPositiveAndBelow (x, getWidth()) && isPositiveAndBelow (y, getHeight())) | |||
| { | |||
| const BitmapData destData (*this, x, y, 1, 1, true); | |||
| const BitmapData destData (*this, x, y, 1, 1, BitmapData::writeOnly); | |||
| destData.setPixelColour (0, 0, colour); | |||
| } | |||
| } | |||
| @@ -425,7 +420,7 @@ void Image::multiplyAlphaAt (const int x, const int y, const float multiplier) | |||
| if (isPositiveAndBelow (x, getWidth()) && isPositiveAndBelow (y, getHeight()) | |||
| && hasAlphaChannel()) | |||
| { | |||
| const BitmapData destData (*this, x, y, 1, 1, true); | |||
| const BitmapData destData (*this, x, y, 1, 1, BitmapData::readWrite); | |||
| if (isARGB()) | |||
| ((PixelARGB*) destData.data)->multiplyAlpha (multiplier); | |||
| @@ -438,7 +433,7 @@ void Image::multiplyAllAlphas (const float amountToMultiplyBy) | |||
| { | |||
| if (hasAlphaChannel()) | |||
| { | |||
| const BitmapData destData (*this, 0, 0, getWidth(), getHeight(), true); | |||
| const BitmapData destData (*this, 0, 0, getWidth(), getHeight(), BitmapData::readWrite); | |||
| if (isARGB()) | |||
| { | |||
| @@ -477,7 +472,7 @@ void Image::desaturate() | |||
| { | |||
| if (isARGB() || isRGB()) | |||
| { | |||
| const BitmapData destData (*this, 0, 0, getWidth(), getHeight(), true); | |||
| const BitmapData destData (*this, 0, 0, getWidth(), getHeight(), BitmapData::readWrite); | |||
| if (isARGB()) | |||
| { | |||
| @@ -601,7 +596,7 @@ void Image::moveImageSection (int dx, int dy, | |||
| const int maxX = jmax (dx, sx) + w; | |||
| const int maxY = jmax (dy, sy) + h; | |||
| const BitmapData destData (*this, minX, minY, maxX - minX, maxY - minY, true); | |||
| const BitmapData destData (*this, minX, minY, maxX - minX, maxY - minY, BitmapData::readWrite); | |||
| uint8* dst = destData.getPixelPointer (dx - minX, dy - minY); | |||
| const uint8* src = destData.getPixelPointer (sx - minX, sy - minY); | |||
| @@ -292,9 +292,16 @@ public: | |||
| class BitmapData | |||
| { | |||
| public: | |||
| BitmapData (Image& image, int x, int y, int w, int h, bool needsToBeWritable); | |||
| enum ReadWriteMode | |||
| { | |||
| readOnly, | |||
| writeOnly, | |||
| readWrite | |||
| }; | |||
| BitmapData (Image& image, int x, int y, int w, int h, ReadWriteMode mode); | |||
| BitmapData (const Image& image, int x, int y, int w, int h); | |||
| BitmapData (const Image& image, bool needsToBeWritable); | |||
| BitmapData (const Image& image, ReadWriteMode mode); | |||
| ~BitmapData(); | |||
| /** Returns a pointer to the start of a line in the image. | |||
| @@ -322,9 +329,21 @@ public: | |||
| void setPixelColour (int x, int y, const Colour& colour) const throw(); | |||
| uint8* data; | |||
| const PixelFormat pixelFormat; | |||
| PixelFormat pixelFormat; | |||
| int lineStride, pixelStride, width, height; | |||
| //============================================================================== | |||
| /** Used internally by custom image types to manage pixel data lifetime. */ | |||
| class BitmapDataReleaser | |||
| { | |||
| protected: | |||
| BitmapDataReleaser() {} | |||
| public: | |||
| virtual ~BitmapDataReleaser() {} | |||
| }; | |||
| ScopedPointer<BitmapDataReleaser> dataReleaser; | |||
| private: | |||
| JUCE_DECLARE_NON_COPYABLE (BitmapData); | |||
| }; | |||
| @@ -387,6 +406,7 @@ public: | |||
| virtual LowLevelGraphicsContext* createLowLevelContext() = 0; | |||
| virtual SharedImage* clone() = 0; | |||
| virtual ImageType getType() const = 0; | |||
| virtual void initialiseBitmapData (BitmapData& bitmapData, int x, int y, BitmapData::ReadWriteMode mode) = 0; | |||
| static SharedImage* createNativeImage (PixelFormat format, int width, int height, bool clearImage); | |||
| static SharedImage* createSoftwareImage (PixelFormat format, int width, int height, bool clearImage); | |||
| @@ -394,17 +414,12 @@ public: | |||
| const PixelFormat getPixelFormat() const throw() { return format; } | |||
| int getWidth() const throw() { return width; } | |||
| int getHeight() const throw() { return height; } | |||
| int getPixelStride() const throw() { return pixelStride; } | |||
| int getLineStride() const throw() { return lineStride; } | |||
| uint8* getPixelData (int x, int y) const throw(); | |||
| protected: | |||
| friend class Image; | |||
| friend class BitmapData; | |||
| const PixelFormat format; | |||
| const int width, height; | |||
| int pixelStride, lineStride; | |||
| uint8* imageData; | |||
| NamedValueSet userData; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SharedImage); | |||
| @@ -134,10 +134,11 @@ void ImageConvolutionKernel::applyToImage (Image& destImage, | |||
| const int right = area.getRight(); | |||
| const int bottom = area.getBottom(); | |||
| const Image::BitmapData destData (destImage, area.getX(), area.getY(), area.getWidth(), area.getHeight(), true); | |||
| const Image::BitmapData destData (destImage, area.getX(), area.getY(), area.getWidth(), area.getHeight(), | |||
| Image::BitmapData::writeOnly); | |||
| uint8* line = destData.data; | |||
| const Image::BitmapData srcData (sourceImage, false); | |||
| const Image::BitmapData srcData (sourceImage, Image::BitmapData::readOnly); | |||
| if (destData.pixelStride == 4) | |||
| { | |||
| @@ -310,7 +310,7 @@ inline Type Atomic<Type>::operator++() throw() | |||
| return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value) | |||
| : (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value); | |||
| #elif JUCE_ATOMICS_ANDROID | |||
| return (Type) __atomic_inc ((volatile int*) &value); | |||
| return (Type) (__atomic_inc ((volatile int*) &value) + 1); | |||
| #elif JUCE_ATOMICS_GCC | |||
| return (Type) __sync_add_and_fetch (&value, 1); | |||
| #endif | |||
| @@ -326,7 +326,7 @@ inline Type Atomic<Type>::operator--() throw() | |||
| return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value) | |||
| : (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value); | |||
| #elif JUCE_ATOMICS_ANDROID | |||
| return (Type) __atomic_dec ((volatile int*) &value); | |||
| return (Type) (__atomic_dec ((volatile int*) &value) - 1); | |||
| #elif JUCE_ATOMICS_GCC | |||
| return (Type) __sync_add_and_fetch (&value, -1); | |||
| #endif | |||
| @@ -31,10 +31,16 @@ import android.graphics.*; | |||
| //============================================================================== | |||
| public class ComponentPeerView extends View | |||
| implements View.OnFocusChangeListener | |||
| { | |||
| public ComponentPeerView (Context context) | |||
| public ComponentPeerView (Context context, boolean opaque_) | |||
| { | |||
| super (context); | |||
| opaque = opaque_; | |||
| setFocusable (true); | |||
| setFocusableInTouchMode (true); | |||
| setOnFocusChangeListener (this); | |||
| requestFocus(); | |||
| } | |||
| //============================================================================== | |||
| @@ -46,6 +52,14 @@ public class ComponentPeerView extends View | |||
| handlePaint (canvas); | |||
| } | |||
| @Override | |||
| public boolean isOpaque() | |||
| { | |||
| return opaque; | |||
| } | |||
| private boolean opaque; | |||
| //============================================================================== | |||
| private native void handleMouseDown (float x, float y, long time); | |||
| private native void handleMouseDrag (float x, float y, long time); | |||
| @@ -70,6 +84,7 @@ public class ComponentPeerView extends View | |||
| @Override | |||
| protected void onSizeChanged (int w, int h, int oldw, int oldh) | |||
| { | |||
| viewSizeChanged(); | |||
| } | |||
| @Override | |||
| @@ -77,16 +92,33 @@ public class ComponentPeerView extends View | |||
| { | |||
| } | |||
| private native void viewSizeChanged(); | |||
| @Override | |||
| public void onFocusChange (View v, boolean hasFocus) | |||
| { | |||
| if (v == this) | |||
| focusChanged (hasFocus); | |||
| } | |||
| private native void focusChanged (boolean hasFocus); | |||
| public void setViewName (String newName) | |||
| { | |||
| } | |||
| public boolean isVisible() | |||
| { | |||
| return true; | |||
| return getVisibility() == VISIBLE; | |||
| } | |||
| public void setVisible (boolean b) | |||
| { | |||
| setVisibility (b ? VISIBLE : INVISIBLE); | |||
| } | |||
| public boolean containsPoint (int x, int y) | |||
| { | |||
| return true; //xxx needs to check overlapping views | |||
| } | |||
| } | |||
| @@ -27,11 +27,16 @@ package com.juce; | |||
| import android.app.Activity; | |||
| import android.os.Bundle; | |||
| import android.content.*; | |||
| import android.view.*; | |||
| import android.content.Context; | |||
| import android.view.ViewGroup; | |||
| import android.view.Display; | |||
| import android.view.WindowManager; | |||
| import android.graphics.Paint; | |||
| import android.graphics.Path; | |||
| import android.text.ClipboardManager; | |||
| import com.juce.ComponentPeerView; | |||
| //============================================================================== | |||
| public class JuceAppActivity extends Activity | |||
| { | |||
| @@ -106,9 +111,9 @@ public class JuceAppActivity extends Activity | |||
| //============================================================================== | |||
| private ViewHolder viewHolder; | |||
| public ComponentPeerView createNewView() | |||
| public ComponentPeerView createNewView (boolean opaque) | |||
| { | |||
| ComponentPeerView v = new ComponentPeerView (this); | |||
| ComponentPeerView v = new ComponentPeerView (this, opaque); | |||
| viewHolder.addView (v); | |||
| return v; | |||
| } | |||
| @@ -123,6 +128,8 @@ public class JuceAppActivity extends Activity | |||
| public ViewHolder (Context context) | |||
| { | |||
| super (context); | |||
| setDescendantFocusability (ViewGroup.FOCUS_AFTER_DESCENDANTS); | |||
| setFocusable (false); | |||
| } | |||
| protected void onLayout (boolean changed, int left, int top, int right, int bottom) | |||
| @@ -130,6 +137,11 @@ public class JuceAppActivity extends Activity | |||
| } | |||
| } | |||
| public void excludeClipRegion (android.graphics.Canvas canvas, float left, float top, float right, float bottom) | |||
| { | |||
| canvas.clipRect (left, top, right, bottom, android.graphics.Region.Op.DIFFERENCE); | |||
| } | |||
| //============================================================================== | |||
| public String getClipboardContent() | |||
| { | |||
| @@ -142,4 +154,97 @@ public class JuceAppActivity extends Activity | |||
| ClipboardManager clipboard = (ClipboardManager) getSystemService (CLIPBOARD_SERVICE); | |||
| clipboard.setText (newText); | |||
| } | |||
| //============================================================================== | |||
| /*class PathGrabber extends Path | |||
| { | |||
| public PathGrabber() | |||
| { | |||
| pathString = new StringBuilder(); | |||
| } | |||
| @Override | |||
| public void addPath (Path src) | |||
| { | |||
| } | |||
| @Override | |||
| public void addPath (Path src, float dx, float dy) | |||
| { | |||
| } | |||
| @Override | |||
| public void close() | |||
| { | |||
| pathString.append ('c'); | |||
| } | |||
| @Override | |||
| public void moveTo (float x, float y) | |||
| { | |||
| pathString.append ('m'); | |||
| pathString.append (String.valueOf (x)); | |||
| pathString.append (String.valueOf (y)); | |||
| } | |||
| @Override | |||
| public void lineTo (float x, float y) | |||
| { | |||
| pathString.append ('l'); | |||
| pathString.append (String.valueOf (x)); | |||
| pathString.append (String.valueOf (y)); | |||
| } | |||
| @Override | |||
| public void quadTo (float x1, float y1, float x2, float y2) | |||
| { | |||
| pathString.append ('q'); | |||
| pathString.append (String.valueOf (x1)); | |||
| pathString.append (String.valueOf (y1)); | |||
| pathString.append (String.valueOf (x2)); | |||
| pathString.append (String.valueOf (y2)); | |||
| } | |||
| @Override | |||
| public void cubicTo (float x1, float y1, float x2, float y2, float x3, float y3) | |||
| { | |||
| pathString.append ('b'); | |||
| pathString.append (String.valueOf (x1)); | |||
| pathString.append (String.valueOf (y1)); | |||
| pathString.append (String.valueOf (x2)); | |||
| pathString.append (String.valueOf (y2)); | |||
| pathString.append (String.valueOf (x3)); | |||
| pathString.append (String.valueOf (y3)); | |||
| } | |||
| @Override | |||
| public void reset() | |||
| { | |||
| rewind(); | |||
| } | |||
| @Override | |||
| public void rewind() | |||
| { | |||
| pathString.setLength (0); | |||
| } | |||
| public String getJucePath() | |||
| { | |||
| if (getFillType() == FillType.EVEN_ODD) | |||
| return "z" + pathString.toString(); | |||
| else | |||
| return "n" + pathString.toString(); | |||
| } | |||
| private StringBuilder pathString; | |||
| }*/ | |||
| public String createPathForGlyph (Paint paint, char c) | |||
| { | |||
| /*PathGrabber pg = new PathGrabber(); | |||
| paint.getTextPath (String.valueOf (c), 0, 1, 0, 0, pg); | |||
| return pg.getJucePath();*/ | |||
| return ""; | |||
| } | |||
| } | |||
| @@ -127,8 +127,14 @@ public: | |||
| bool getOutlineForGlyph (int glyphNumber, Path& destPath) | |||
| { | |||
| // TODO | |||
| return false; | |||
| LocalRef<jstring> s ((jstring) android.activity.callObjectMethod (android.createPathForGlyph, paint.get(), (jchar) glyphNumber)); | |||
| if (s == 0) | |||
| return false; | |||
| const String ourString (juceString (s)); | |||
| destPath.restoreFromString (ourString); | |||
| return ourString.isNotEmpty(); | |||
| } | |||
| GlobalRef typeface, paint; | |||
| @@ -27,22 +27,141 @@ | |||
| // compiled on its own). | |||
| #if JUCE_INCLUDED_FILE | |||
| //============================================================================== | |||
| class AndroidImage : public Image::SharedImage | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| AndroidImage (const int width_, const int height_, const bool clearImage) | |||
| : Image::SharedImage (Image::ARGB, width_, height_) | |||
| { | |||
| JNIEnv* env = getEnv(); | |||
| jobject mode = env->GetStaticObjectField (android.bitmapConfigClass, android.ARGB_8888); | |||
| bitmap = GlobalRef (env->CallStaticObjectMethod (android.bitmapClass, android.createBitmap, width_, height_, mode)); | |||
| env->DeleteLocalRef (mode); | |||
| } | |||
| AndroidImage (const int width_, const int height_, const GlobalRef& bitmap_) | |||
| : Image::SharedImage (Image::ARGB, width_, height_), | |||
| bitmap (bitmap_) | |||
| { | |||
| } | |||
| ~AndroidImage() | |||
| { | |||
| bitmap.callVoidMethod (android.recycle); | |||
| } | |||
| Image::ImageType getType() const { return Image::NativeImage; } | |||
| LowLevelGraphicsContext* createLowLevelContext(); | |||
| void initialiseBitmapData (Image::BitmapData& bm, int x, int y, Image::BitmapData::ReadWriteMode mode) | |||
| { | |||
| bm.lineStride = width * sizeof (jint); | |||
| bm.pixelStride = sizeof (jint); | |||
| bm.pixelFormat = Image::ARGB; | |||
| bm.dataReleaser = new CopyHandler (*this, bm, x, y, mode); | |||
| } | |||
| SharedImage* clone() | |||
| { | |||
| JNIEnv* env = getEnv(); | |||
| jobject mode = env->GetStaticObjectField (android.bitmapConfigClass, android.ARGB_8888); | |||
| GlobalRef newCopy (bitmap.callObjectMethod (android.bitmapCopy, mode, true)); | |||
| env->DeleteLocalRef (mode); | |||
| return new AndroidImage (width, height, newCopy); | |||
| } | |||
| //============================================================================== | |||
| GlobalRef bitmap; | |||
| private: | |||
| class CopyHandler : public Image::BitmapData::BitmapDataReleaser | |||
| { | |||
| public: | |||
| CopyHandler (AndroidImage& owner_, Image::BitmapData& bitmapData_, | |||
| const int x_, const int y_, const Image::BitmapData::ReadWriteMode mode_) | |||
| : owner (owner_), bitmapData (bitmapData_), mode (mode_), x (x_), y (y_) | |||
| { | |||
| JNIEnv* env = getEnv(); | |||
| intArray = env->NewIntArray (bitmapData.width * bitmapData.height); | |||
| if (mode != Image::BitmapData::writeOnly) | |||
| owner_.bitmap.callVoidMethod (android.getPixels, intArray, 0, bitmapData.width, x_, y_, | |||
| bitmapData.width, bitmapData.height); | |||
| bitmapData.data = (uint8*) env->GetIntArrayElements (intArray, 0); | |||
| if (mode != Image::BitmapData::writeOnly) | |||
| { | |||
| for (int yy = 0; yy < bitmapData.height; ++yy) | |||
| { | |||
| PixelARGB* p = (PixelARGB*) bitmapData.getLinePointer (yy); | |||
| for (int xx = 0; xx < bitmapData.width; ++xx) | |||
| p[xx].premultiply(); | |||
| } | |||
| } | |||
| } | |||
| ~CopyHandler() | |||
| { | |||
| JNIEnv* env = getEnv(); | |||
| if (mode != Image::BitmapData::readOnly) | |||
| { | |||
| for (int yy = 0; yy < bitmapData.height; ++yy) | |||
| { | |||
| PixelARGB* p = (PixelARGB*) bitmapData.getLinePointer (yy); | |||
| for (int xx = 0; xx < bitmapData.width; ++xx) | |||
| p[xx].unpremultiply(); | |||
| } | |||
| } | |||
| env->ReleaseIntArrayElements (intArray, (jint*) bitmapData.data, 0); | |||
| if (mode != Image::BitmapData::readOnly) | |||
| owner.bitmap.callVoidMethod (android.setPixels, intArray, 0, bitmapData.width, x, y, | |||
| bitmapData.width, bitmapData.height); | |||
| env->DeleteLocalRef (intArray); | |||
| } | |||
| private: | |||
| AndroidImage& owner; | |||
| Image::BitmapData& bitmapData; | |||
| jintArray intArray; | |||
| const Image::BitmapData::ReadWriteMode mode; | |||
| const int x, y; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CopyHandler); | |||
| }; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidImage); | |||
| }; | |||
| Image::SharedImage* Image::SharedImage::createNativeImage (PixelFormat format, int width, int height, bool clearImage) | |||
| { | |||
| if (format == Image::SingleChannel) | |||
| return createSoftwareImage (format, width, height, clearImage); | |||
| else | |||
| return new AndroidImage (width, height, clearImage); | |||
| } | |||
| //============================================================================== | |||
| class AndroidLowLevelGraphicsContext : public LowLevelGraphicsContext | |||
| { | |||
| public: | |||
| AndroidLowLevelGraphicsContext (const GlobalRef& canvas_) | |||
| AndroidLowLevelGraphicsContext (jobject canvas_) | |||
| : canvas (canvas_), | |||
| currentState (new SavedState()) | |||
| { | |||
| setFill (Colours::black); | |||
| } | |||
| ~AndroidLowLevelGraphicsContext() | |||
| { | |||
| } | |||
| bool isVectorDevice() const { return false; } | |||
| //============================================================================== | |||
| @@ -68,11 +187,19 @@ public: | |||
| bool clipToRectangleList (const RectangleList& clipRegion) | |||
| { | |||
| return canvas.callBooleanMethod (android.clipRegion, createRegion (getEnv(), clipRegion).get()); | |||
| RectangleList excluded (getClipBounds()); | |||
| excluded.subtract (clipRegion); | |||
| const int numRects = excluded.getNumRectangles(); | |||
| for (int i = 0; i < numRects; ++i) | |||
| excludeClipRectangle (excluded.getRectangle(i)); | |||
| } | |||
| void excludeClipRectangle (const Rectangle<int>& r) | |||
| { | |||
| android.activity.callVoidMethod (android.excludeClipRegion, canvas.get(), | |||
| (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom()); | |||
| } | |||
| void clipToPath (const Path& path, const AffineTransform& transform) | |||
| @@ -82,6 +209,7 @@ public: | |||
| void clipToImageAlpha (const Image& sourceImage, const AffineTransform& transform) | |||
| { | |||
| // TODO xxx | |||
| } | |||
| bool clipRegionIntersects (const Rectangle<int>& r) | |||
| @@ -117,10 +245,12 @@ public: | |||
| void setOpacity (float newOpacity) | |||
| { | |||
| currentState->setAlpha (newOpacity); | |||
| } | |||
| void setInterpolationQuality (Graphics::ResamplingQuality quality) | |||
| { | |||
| // TODO xxx | |||
| } | |||
| //============================================================================== | |||
| @@ -139,6 +269,60 @@ public: | |||
| void drawImage (const Image& sourceImage, const AffineTransform& transform, bool fillEntireClipAsTiles) | |||
| { | |||
| AndroidImage* androidImage = dynamic_cast <AndroidImage*> (sourceImage.getSharedImage()); | |||
| if (androidImage != 0) | |||
| { | |||
| JNIEnv* env = getEnv(); | |||
| canvas.callVoidMethod (android.drawBitmap, androidImage->bitmap.get(), | |||
| createMatrix (env, transform).get(), getImagePaint()); | |||
| } | |||
| else | |||
| { | |||
| if (transform.isOnlyTranslation()) | |||
| { | |||
| JNIEnv* env = getEnv(); | |||
| Image::BitmapData bm (sourceImage, Image::BitmapData::readOnly); | |||
| jintArray imageData = env->NewIntArray (bm.width * bm.height); | |||
| jint* dest = env->GetIntArrayElements (imageData, 0); | |||
| if (dest != 0) | |||
| { | |||
| const uint8* srcLine = bm.getLinePointer (0); | |||
| jint* dstLine = dest; | |||
| for (int y = 0; y < bm.height; ++y) | |||
| { | |||
| switch (bm.pixelFormat) | |||
| { | |||
| case Image::ARGB: copyPixels (dstLine, (PixelARGB*) srcLine, bm.width, bm.pixelStride); break; | |||
| case Image::RGB: copyPixels (dstLine, (PixelRGB*) srcLine, bm.width, bm.pixelStride); break; | |||
| case Image::SingleChannel: copyPixels (dstLine, (PixelAlpha*) srcLine, bm.width, bm.pixelStride); break; | |||
| default: jassertfalse; break; | |||
| } | |||
| srcLine += bm.lineStride; | |||
| dstLine += bm.width; | |||
| } | |||
| canvas.callVoidMethod (android.drawMemoryBitmap, imageData, 0, bm.width, | |||
| transform.getTranslationX(), transform.getTranslationY(), | |||
| bm.width, bm.height, true, getImagePaint()); | |||
| env->ReleaseIntArrayElements (imageData, dest, 0); | |||
| env->DeleteLocalRef (imageData); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| saveState(); | |||
| addTransform (transform); | |||
| drawImage (sourceImage, AffineTransform::identity, fillEntireClipAsTiles); | |||
| restoreState(); | |||
| } | |||
| } | |||
| } | |||
| void drawLine (const Line <float>& line) | |||
| @@ -215,10 +399,12 @@ public: | |||
| void beginTransparencyLayer (float opacity) | |||
| { | |||
| // TODO xxx | |||
| } | |||
| void endTransparencyLayer() | |||
| { | |||
| // TODO xxx | |||
| } | |||
| class SavedState | |||
| @@ -240,6 +426,12 @@ public: | |||
| fillType = newType; | |||
| } | |||
| void setAlpha (float alpha) | |||
| { | |||
| fillNeedsUpdate = true; | |||
| fillType.colour = fillType.colour.withAlpha (alpha); | |||
| } | |||
| jobject getPaint() | |||
| { | |||
| if (fillNeedsUpdate) | |||
| @@ -299,6 +491,7 @@ public: | |||
| tileMode); | |||
| } | |||
| env->DeleteLocalRef (tileMode); | |||
| env->DeleteLocalRef (coloursArray); | |||
| env->DeleteLocalRef (positionsArray); | |||
| @@ -309,6 +502,7 @@ public: | |||
| } | |||
| else | |||
| { | |||
| } | |||
| } | |||
| @@ -330,11 +524,22 @@ public: | |||
| paint.callObjectMethod (android.setTypeface, atf->typeface.get()); | |||
| paint.callVoidMethod (android.setTextSize, font.getHeight()); | |||
| } | |||
| fillNeedsUpdate = true; | |||
| paint.callVoidMethod (android.setAlpha, (jint) fillType.colour.getAlpha()); | |||
| } | |||
| return p; | |||
| } | |||
| jobject getImagePaint() | |||
| { | |||
| jobject p = getPaint(); | |||
| paint.callVoidMethod (android.setAlpha, (jint) fillType.colour.getAlpha()); | |||
| fillNeedsUpdate = true; | |||
| return p; | |||
| } | |||
| FillType fillType; | |||
| Font font; | |||
| GlobalRef paint; | |||
| @@ -347,10 +552,8 @@ private: | |||
| ScopedPointer <SavedState> currentState; | |||
| OwnedArray <SavedState> stateStack; | |||
| jobject getCurrentPaint() const | |||
| { | |||
| return currentState->getPaint(); | |||
| } | |||
| jobject getCurrentPaint() const { return currentState->getPaint(); } | |||
| jobject getImagePaint() const { return currentState->getImagePaint(); } | |||
| static const LocalRef<jobject> createPath (JNIEnv* env, const Path& path) | |||
| { | |||
| @@ -424,8 +627,24 @@ private: | |||
| return col.getARGB(); | |||
| } | |||
| template <class PixelType> | |||
| static void copyPixels (jint* const dest, const PixelType* src, const int width, const int pixelStride) throw() | |||
| { | |||
| for (int x = 0; x < width; ++x) | |||
| { | |||
| dest[x] = src->getUnpremultipliedARGB(); | |||
| src = addBytesToPointer (src, pixelStride); | |||
| } | |||
| } | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidLowLevelGraphicsContext); | |||
| }; | |||
| LowLevelGraphicsContext* AndroidImage::createLowLevelContext() | |||
| { | |||
| jobject canvas = getEnv()->NewObject (android.canvasClass, android.canvasBitmapConstructor, bitmap.get()); | |||
| return new AndroidLowLevelGraphicsContext (canvas); | |||
| } | |||
| #endif | |||
| @@ -29,31 +29,14 @@ | |||
| //============================================================================== | |||
| void MessageManager::doPlatformSpecificInitialisation() | |||
| { | |||
| } | |||
| void MessageManager::doPlatformSpecificShutdown() | |||
| { | |||
| } | |||
| void MessageManager::doPlatformSpecificInitialisation() {} | |||
| void MessageManager::doPlatformSpecificShutdown() {} | |||
| //============================================================================== | |||
| bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages) | |||
| { | |||
| // TODO | |||
| /* | |||
| The idea here is that this will check the system message queue, pull off a | |||
| message if there is one, deliver it, and return true if a message was delivered. | |||
| If the queue's empty, return false. | |||
| If the message is one of our special ones (i.e. a Message object being delivered, | |||
| this must call MessageManager::getInstance()->deliverMessage() to deliver it | |||
| */ | |||
| Logger::outputDebugString ("*** Modal loops are not possible in Android!! Exiting..."); | |||
| exit (1); | |||
| return true; | |||
| } | |||
| @@ -61,14 +44,16 @@ bool juce_dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages | |||
| //============================================================================== | |||
| bool juce_postMessageToSystemQueue (Message* message) | |||
| { | |||
| message->incReferenceCount(); | |||
| getEnv()->CallVoidMethod (android.activity, android.postMessage, (jlong) (pointer_sized_uint) message); | |||
| return true; | |||
| } | |||
| JUCE_JNI_CALLBACK (JuceAppActivity, deliverMessage, void, (jobject activity, jlong value)) | |||
| { | |||
| Message* m = (Message*) (pointer_sized_uint) value; | |||
| MessageManager::getInstance()->deliverMessage ((Message*) (pointer_sized_uint) value); | |||
| Message* const message = (Message*) (pointer_sized_uint) value; | |||
| MessageManager::getInstance()->deliverMessage (message); | |||
| message->decReferenceCount(); | |||
| } | |||
| //============================================================================== | |||
| @@ -115,4 +100,31 @@ void MessageManager::broadcastMessage (const String&) | |||
| { | |||
| } | |||
| void MessageManager::runDispatchLoop() | |||
| { | |||
| } | |||
| class QuitCallback : public CallbackMessage | |||
| { | |||
| public: | |||
| QuitCallback() {} | |||
| void messageCallback() | |||
| { | |||
| android.activity.callVoidMethod (android.finish); | |||
| } | |||
| }; | |||
| void MessageManager::stopDispatchLoop() | |||
| { | |||
| (new QuitCallback())->post(); | |||
| quitMessagePosted = true; | |||
| } | |||
| bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | |||
| { | |||
| juce_dispatchNextMessageOnSystemQueue (false); | |||
| return false; | |||
| } | |||
| #endif | |||
| @@ -103,6 +103,8 @@ BEGIN_JUCE_NAMESPACE | |||
| JAVACLASS (canvasClass, "android/graphics/Canvas") \ | |||
| JAVACLASS (paintClass, "android/graphics/Paint") \ | |||
| JAVACLASS (pathClass, "android/graphics/Path") \ | |||
| JAVACLASS (bitmapClass, "android/graphics/Bitmap") \ | |||
| JAVACLASS (bitmapConfigClass, "android/graphics/Bitmap$Config") \ | |||
| JAVACLASS (matrixClass, "android/graphics/Matrix") \ | |||
| JAVACLASS (rectClass, "android/graphics/Rect") \ | |||
| JAVACLASS (regionClass, "android/graphics/Region") \ | |||
| @@ -116,11 +118,14 @@ BEGIN_JUCE_NAMESPACE | |||
| #define JUCE_JNI_METHODS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| \ | |||
| STATICMETHOD (activityClass, printToConsole, "printToConsole", "(Ljava/lang/String;)V") \ | |||
| METHOD (activityClass, createNewView, "createNewView", "()Lcom/juce/ComponentPeerView;") \ | |||
| METHOD (activityClass, createNewView, "createNewView", "(Z)Lcom/juce/ComponentPeerView;") \ | |||
| METHOD (activityClass, deleteView, "deleteView", "(Lcom/juce/ComponentPeerView;)V") \ | |||
| METHOD (activityClass, postMessage, "postMessage", "(J)V") \ | |||
| METHOD (activityClass, finish, "finish", "()V") \ | |||
| METHOD (activityClass, getClipboardContent, "getClipboardContent", "()Ljava/lang/String;") \ | |||
| METHOD (activityClass, setClipboardContent, "setClipboardContent", "(Ljava/lang/String;)V") \ | |||
| METHOD (activityClass, excludeClipRegion, "excludeClipRegion", "(Landroid/graphics/Canvas;FFFF)V") \ | |||
| METHOD (activityClass, createPathForGlyph, "createPathForGlyph", "(Landroid/graphics/Paint;C)Ljava/lang/String;") \ | |||
| \ | |||
| METHOD (fileClass, fileExists, "exists", "()Z") \ | |||
| \ | |||
| @@ -137,7 +142,9 @@ BEGIN_JUCE_NAMESPACE | |||
| METHOD (componentPeerViewClass, isVisible, "isVisible", "()Z") \ | |||
| METHOD (componentPeerViewClass, hasFocus, "hasFocus", "()Z") \ | |||
| METHOD (componentPeerViewClass, invalidate, "invalidate", "(IIII)V") \ | |||
| METHOD (componentPeerViewClass, containsPoint, "containsPoint", "(II)Z") \ | |||
| \ | |||
| METHOD (canvasClass, canvasBitmapConstructor, "<init>", "(Landroid/graphics/Bitmap;)V") \ | |||
| METHOD (canvasClass, drawRect, "drawRect", "(FFFFLandroid/graphics/Paint;)V") \ | |||
| METHOD (canvasClass, translate, "translate", "(FF)V") \ | |||
| METHOD (canvasClass, clipPath, "clipPath", "(Landroid/graphics/Path;)Z") \ | |||
| @@ -145,6 +152,7 @@ BEGIN_JUCE_NAMESPACE | |||
| METHOD (canvasClass, clipRegion, "clipRegion", "(Landroid/graphics/Region;)Z") \ | |||
| METHOD (canvasClass, concat, "concat", "(Landroid/graphics/Matrix;)V") \ | |||
| METHOD (canvasClass, drawBitmap, "drawBitmap", "(Landroid/graphics/Bitmap;Landroid/graphics/Matrix;Landroid/graphics/Paint;)V") \ | |||
| METHOD (canvasClass, drawMemoryBitmap, "drawBitmap", "([IIIFFIIZLandroid/graphics/Paint;)V") \ | |||
| METHOD (canvasClass, drawLine, "drawLine", "(FFFFLandroid/graphics/Paint;)V") \ | |||
| METHOD (canvasClass, drawPath, "drawPath", "(Landroid/graphics/Path;Landroid/graphics/Paint;)V") \ | |||
| METHOD (canvasClass, drawText, "drawText", "(Ljava/lang/String;FFLandroid/graphics/Paint;)V") \ | |||
| @@ -157,13 +165,13 @@ BEGIN_JUCE_NAMESPACE | |||
| \ | |||
| METHOD (paintClass, paintClassConstructor, "<init>", "(I)V") \ | |||
| METHOD (paintClass, setColor, "setColor", "(I)V") \ | |||
| METHOD (paintClass, setAlpha, "setAlpha", "(I)V") \ | |||
| METHOD (paintClass, setShader, "setShader", "(Landroid/graphics/Shader;)Landroid/graphics/Shader;") \ | |||
| METHOD (paintClass, setTypeface, "setTypeface", "(Landroid/graphics/Typeface;)Landroid/graphics/Typeface;") \ | |||
| METHOD (paintClass, ascent, "ascent", "()F") \ | |||
| METHOD (paintClass, descent, "descent", "()F") \ | |||
| METHOD (paintClass, setTextSize, "setTextSize", "(F)V") \ | |||
| METHOD (paintClass, getTextWidths, "getTextWidths", "(Ljava/lang/String;[F)I") \ | |||
| METHOD (paintClass, getTextPath, "getTextPath", "(Ljava/lang/String;IIFFLandroid/graphics/Path;)V") \ | |||
| \ | |||
| METHOD (shaderClass, setLocalMatrix, "setLocalMatrix", "(Landroid/graphics/Matrix;)V") \ | |||
| STATICFIELD (shaderTileModeClass, clampMode, "CLAMP", "Landroid/graphics/Shader$TileMode;") \ | |||
| @@ -174,6 +182,13 @@ BEGIN_JUCE_NAMESPACE | |||
| METHOD (pathClass, quadTo, "quadTo", "(FFFF)V") \ | |||
| METHOD (pathClass, cubicTo, "cubicTo", "(FFFFFF)V") \ | |||
| METHOD (pathClass, closePath, "close", "()V") \ | |||
| \ | |||
| STATICMETHOD (bitmapClass, createBitmap, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;") \ | |||
| STATICFIELD (bitmapConfigClass, ARGB_8888, "ARGB_8888", "Landroid/graphics/Bitmap$Config;") \ | |||
| METHOD (bitmapClass, bitmapCopy, "copy", "(Landroid/graphics/Bitmap$Config;Z)Landroid/graphics/Bitmap;") \ | |||
| METHOD (bitmapClass, getPixels, "getPixels", "([IIIIIII)V") \ | |||
| METHOD (bitmapClass, setPixels, "setPixels", "([IIIIIII)V") \ | |||
| METHOD (bitmapClass, recycle, "recycle", "()V") \ | |||
| \ | |||
| METHOD (matrixClass, matrixClassConstructor, "<init>", "()V") \ | |||
| METHOD (matrixClass, setValues, "setValues", "([F)V") \ | |||
| @@ -315,7 +330,10 @@ public: | |||
| inline void clear() | |||
| { | |||
| if (obj != 0) | |||
| { | |||
| getEnv()->DeleteGlobalRef (obj); | |||
| obj = 0; | |||
| } | |||
| } | |||
| inline GlobalRef& operator= (const GlobalRef& other) | |||
| @@ -27,7 +27,6 @@ | |||
| // compiled on its own). | |||
| #if JUCE_INCLUDED_FILE | |||
| static ModifierKeys currentModifiers; | |||
| //============================================================================== | |||
| class AndroidComponentPeer : public ComponentPeer | |||
| @@ -36,8 +35,10 @@ public: | |||
| //============================================================================== | |||
| AndroidComponentPeer (Component* const component, const int windowStyleFlags) | |||
| : ComponentPeer (component, windowStyleFlags), | |||
| view (android.activity.callObjectMethod (android.createNewView)) | |||
| view (android.activity.callObjectMethod (android.createNewView, component->isOpaque())) | |||
| { | |||
| if (isFocused()) | |||
| handleFocusGain(); | |||
| } | |||
| ~AndroidComponentPeer() | |||
| @@ -88,7 +89,7 @@ public: | |||
| const Point<int> getScreenPosition() const | |||
| { | |||
| JNIEnv* const env = getEnv(); | |||
| /*JNIEnv* const env = getEnv(); | |||
| jintArray pos = env->NewIntArray (2); | |||
| view.callVoidMethod (android.getLocationOnScreen, pos); | |||
| @@ -97,7 +98,10 @@ public: | |||
| env->GetIntArrayRegion (pos, 0, 2, coords); | |||
| env->DeleteLocalRef (pos); | |||
| return Point<int> (coords[0], coords[1]); | |||
| return Point<int> (coords[0], coords[1]);*/ | |||
| return Point<int> (view.callIntMethod (android.getLeft), | |||
| view.callIntMethod (android.getTop)); | |||
| } | |||
| const Point<int> localToGlobal (const Point<int>& relativePosition) | |||
| @@ -138,10 +142,9 @@ public: | |||
| bool contains (const Point<int>& position, bool trueIfInAChildWindow) const | |||
| { | |||
| // TODO | |||
| return isPositiveAndBelow (position.getX(), component->getWidth()) | |||
| && isPositiveAndBelow (position.getY(), component->getHeight()); | |||
| && isPositiveAndBelow (position.getY(), component->getHeight()) | |||
| && ((! trueIfInAChildWindow) || view.callBooleanMethod (android.containsPoint, position.getX(), position.getY())); | |||
| } | |||
| const BorderSize<int> getFrameSize() const | |||
| @@ -162,6 +165,8 @@ public: | |||
| if (makeActive) | |||
| grabFocus(); | |||
| handleBroughtToFront(); | |||
| } | |||
| void toBehind (ComponentPeer* other) | |||
| @@ -172,21 +177,24 @@ public: | |||
| //============================================================================== | |||
| void handleMouseDownCallback (float x, float y, int64 time) | |||
| { | |||
| lastMousePos.setXY ((int) x, (int) y); | |||
| currentModifiers = currentModifiers.withoutMouseButtons(); | |||
| handleMouseEvent (0, Point<int> ((int) x, (int) y), currentModifiers, time); | |||
| handleMouseEvent (0, lastMousePos, currentModifiers, time); | |||
| currentModifiers = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier); | |||
| handleMouseEvent (0, Point<int> ((int) x, (int) y), currentModifiers, time); | |||
| handleMouseEvent (0, lastMousePos, currentModifiers, time); | |||
| } | |||
| void handleMouseDragCallback (float x, float y, int64 time) | |||
| { | |||
| handleMouseEvent (0, Point<int> ((int) x, (int) y), currentModifiers, time); | |||
| lastMousePos.setXY ((int) x, (int) y); | |||
| handleMouseEvent (0, lastMousePos, currentModifiers, time); | |||
| } | |||
| void handleMouseUpCallback (float x, float y, int64 time) | |||
| { | |||
| lastMousePos.setXY ((int) x, (int) y); | |||
| currentModifiers = currentModifiers.withoutMouseButtons(); | |||
| handleMouseEvent (0, Point<int> ((int) x, (int) y), currentModifiers, time); | |||
| handleMouseEvent (0, lastMousePos, currentModifiers, time); | |||
| } | |||
| //============================================================================== | |||
| @@ -197,7 +205,15 @@ public: | |||
| void grabFocus() | |||
| { | |||
| (void) view.callBooleanMethod (android.requestFocus); | |||
| view.callBooleanMethod (android.requestFocus); | |||
| } | |||
| void handleFocusChangeCallback (bool hasFocus) | |||
| { | |||
| if (hasFocus) | |||
| handleFocusGain(); | |||
| else | |||
| handleFocusLoss(); | |||
| } | |||
| void textInputRequired (const Point<int>& position) | |||
| @@ -208,8 +224,7 @@ public: | |||
| //============================================================================== | |||
| void handlePaintCallback (JNIEnv* env, jobject canvas) | |||
| { | |||
| GlobalRef canvasRef (canvas); | |||
| AndroidLowLevelGraphicsContext g (canvasRef); | |||
| AndroidLowLevelGraphicsContext g (canvas); | |||
| handlePaint (g); | |||
| } | |||
| @@ -243,6 +258,9 @@ public: | |||
| return 0; | |||
| } | |||
| static ModifierKeys currentModifiers; | |||
| static Point<int> lastMousePos; | |||
| private: | |||
| //============================================================================== | |||
| GlobalRef view; | |||
| @@ -250,6 +268,9 @@ private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidComponentPeer); | |||
| }; | |||
| ModifierKeys AndroidComponentPeer::currentModifiers = 0; | |||
| Point<int> AndroidComponentPeer::lastMousePos; | |||
| //============================================================================== | |||
| #define JUCE_VIEW_CALLBACK(returnType, javaMethodName, params, juceMethodInvocation) \ | |||
| JUCE_JNI_CALLBACK (ComponentPeerView, javaMethodName, returnType, params) \ | |||
| @@ -269,6 +290,12 @@ JUCE_VIEW_CALLBACK (void, handleMouseDrag, (JNIEnv*, jobject view, jfloat x, jfl | |||
| JUCE_VIEW_CALLBACK (void, handleMouseUp, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), | |||
| handleMouseUpCallback ((float) x, (float) y, (int64) time)) | |||
| JUCE_VIEW_CALLBACK (void, viewSizeChanged, (JNIEnv*, jobject view), | |||
| handleMovedOrResized()) | |||
| JUCE_VIEW_CALLBACK (void, focusChanged, (JNIEnv*, jobject view, jboolean hasFocus), | |||
| handleFocusChangeCallback (hasFocus)) | |||
| //============================================================================== | |||
| ComponentPeer* Component::createNewPeer (int styleFlags, void*) | |||
| { | |||
| @@ -298,8 +325,7 @@ void Desktop::createMouseInputSources() | |||
| const Point<int> MouseInputSource::getCurrentMousePosition() | |||
| { | |||
| // TODO | |||
| return Point<int>(); | |||
| return AndroidComponentPeer::lastMousePos; | |||
| } | |||
| void Desktop::setMousePosition (const Point<int>& newPosition) | |||
| @@ -316,12 +342,12 @@ bool KeyPress::isKeyCurrentlyDown (const int keyCode) | |||
| void ModifierKeys::updateCurrentModifiers() throw() | |||
| { | |||
| // not needed | |||
| currentModifiers = AndroidComponentPeer::currentModifiers; | |||
| } | |||
| const ModifierKeys ModifierKeys::getCurrentModifiersRealtime() throw() | |||
| { | |||
| return currentModifiers; | |||
| return AndroidComponentPeer::currentModifiers; | |||
| } | |||
| //============================================================================== | |||
| @@ -340,11 +366,6 @@ bool AlertWindow::showNativeDialogBox (const String& title, | |||
| } | |||
| //============================================================================== | |||
| Image::SharedImage* Image::SharedImage::createNativeImage (PixelFormat format, int width, int height, bool clearImage) | |||
| { | |||
| return createSoftwareImage (format, width, height, clearImage); | |||
| } | |||
| void Desktop::setScreenSaverEnabled (const bool isEnabled) | |||
| { | |||
| // TODO | |||
| @@ -585,6 +585,14 @@ public: | |||
| return new LowLevelGraphicsSoftwareRenderer (Image (this)); | |||
| } | |||
| void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode /*mode*/) | |||
| { | |||
| bitmap.data = imageData + x * pixelStride + y * lineStride; | |||
| bitmap.pixelFormat = format; | |||
| bitmap.lineStride = lineStride; | |||
| bitmap.pixelStride = pixelStride; | |||
| } | |||
| SharedImage* clone() | |||
| { | |||
| jassertfalse; | |||
| @@ -622,7 +630,7 @@ public: | |||
| const uint32 bShiftL = jmax (0, getShiftNeeded (bMask)); | |||
| const uint32 bShiftR = jmax (0, -getShiftNeeded (bMask)); | |||
| const Image::BitmapData srcData (Image (this), false); | |||
| const Image::BitmapData srcData (Image (this), Image::BitmapData::readOnly); | |||
| for (int y = sy; y < sy + dh; ++y) | |||
| { | |||
| @@ -656,6 +664,8 @@ private: | |||
| const int imageDepth; | |||
| HeapBlock <uint8> imageDataAllocated; | |||
| HeapBlock <char> imageData16Bit; | |||
| int pixelStride, lineStride; | |||
| uint8* imageData; | |||
| GC gc; | |||
| @@ -38,8 +38,7 @@ public: | |||
| pixelStride = format_ == Image::RGB ? 3 : ((format_ == Image::ARGB) ? 4 : 1); | |||
| lineStride = (pixelStride * jmax (1, width) + 3) & ~3; | |||
| imageDataAllocated.allocate (lineStride * jmax (1, height), clearImage); | |||
| imageData = imageDataAllocated; | |||
| imageData.allocate (lineStride * jmax (1, height), clearImage); | |||
| CGColorSpaceRef colourSpace = (format == Image::SingleChannel) ? CGColorSpaceCreateDeviceGray() | |||
| : CGColorSpaceCreateDeviceRGB(); | |||
| @@ -58,6 +57,14 @@ public: | |||
| Image::ImageType getType() const { return Image::NativeImage; } | |||
| LowLevelGraphicsContext* createLowLevelContext(); | |||
| void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode /*mode*/) | |||
| { | |||
| bitmap.data = imageData + x * pixelStride + y * lineStride; | |||
| bitmap.pixelFormat = format; | |||
| bitmap.lineStride = lineStride; | |||
| bitmap.pixelStride = pixelStride; | |||
| } | |||
| SharedImage* clone() | |||
| { | |||
| CoreGraphicsImage* im = new CoreGraphicsImage (format, width, height, false); | |||
| @@ -77,7 +84,7 @@ public: | |||
| } | |||
| else | |||
| { | |||
| const Image::BitmapData srcData (juceImage, false); | |||
| const Image::BitmapData srcData (juceImage, Image::BitmapData::readOnly); | |||
| CGDataProviderRef provider; | |||
| if (mustOutliveSource) | |||
| @@ -126,7 +133,8 @@ public: | |||
| //============================================================================== | |||
| CGContextRef context; | |||
| HeapBlock<uint8> imageDataAllocated; | |||
| HeapBlock<uint8> imageData; | |||
| int pixelStride, lineStride; | |||
| private: | |||
| static CGBitmapInfo getCGImageFlags (const Image::PixelFormat& format) | |||
| @@ -212,7 +212,7 @@ public: | |||
| const ScopedLock sl (imageSwapLock); | |||
| { | |||
| const Image::BitmapData destData (loadingImage, 0, 0, width, height, true); | |||
| const Image::BitmapData destData (loadingImage, 0, 0, width, height, Image::BitmapData::writeOnly); | |||
| for (int i = 0; i < height; ++i) | |||
| memcpy (destData.getLinePointer ((height - 1) - i), | |||
| @@ -243,7 +243,7 @@ public: | |||
| D2D1_BITMAP_PROPERTIES bp = D2D1::BitmapProperties(); | |||
| Image img (image.convertedToFormat (Image::ARGB)); | |||
| Image::BitmapData bd (img, false); | |||
| Image::BitmapData bd (img, Image::BitmapData::readOnly); | |||
| bp.pixelFormat = renderingTarget->GetPixelFormat(); | |||
| bp.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; | |||
| @@ -479,7 +479,7 @@ public: | |||
| D2D1_BITMAP_PROPERTIES bp = D2D1::BitmapProperties(); | |||
| maskImage = image.convertedToFormat (Image::ARGB); | |||
| Image::BitmapData bd (this->image, false); // xxx should be maskImage? | |||
| Image::BitmapData bd (this->image, Image::BitmapData::readOnly); // xxx should be maskImage? | |||
| bp.pixelFormat = owner.renderingTarget->GetPixelFormat(); | |||
| bp.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; | |||
| @@ -658,7 +658,7 @@ public: | |||
| D2D1_BITMAP_PROPERTIES bp = D2D1::BitmapProperties(); | |||
| this->image = image.convertedToFormat (Image::ARGB); | |||
| Image::BitmapData bd (this->image, false); | |||
| Image::BitmapData bd (this->image, Image::BitmapData::readOnly); | |||
| bp.pixelFormat = owner.renderingTarget->GetPixelFormat(); | |||
| bp.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; | |||
| @@ -145,13 +145,6 @@ const int KeyPress::rewindKey = 0x30003; | |||
| class WindowsBitmapImage : public Image::SharedImage | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| HBITMAP hBitmap; | |||
| HGDIOBJ previousBitmap; | |||
| BITMAPV4HEADER bitmapInfo; | |||
| HDC hdc; | |||
| unsigned char* bitmapData; | |||
| //============================================================================== | |||
| WindowsBitmapImage (const Image::PixelFormat format_, | |||
| const int w, const int h, const bool clearImage) | |||
| @@ -160,6 +153,7 @@ public: | |||
| jassert (format_ == Image::RGB || format_ == Image::ARGB); | |||
| pixelStride = (format_ == Image::RGB) ? 3 : 4; | |||
| lineStride = -((w * pixelStride + 3) & ~3); | |||
| zerostruct (bitmapInfo); | |||
| bitmapInfo.bV4Size = sizeof (BITMAPV4HEADER); | |||
| @@ -182,19 +176,14 @@ public: | |||
| bitmapInfo.bV4V4Compression = BI_RGB; | |||
| } | |||
| lineStride = -((w * pixelStride + 3) & ~3); | |||
| HDC dc = GetDC (0); | |||
| hdc = CreateCompatibleDC (dc); | |||
| ReleaseDC (0, dc); | |||
| SetMapMode (hdc, MM_TEXT); | |||
| hBitmap = CreateDIBSection (hdc, | |||
| (BITMAPINFO*) &(bitmapInfo), | |||
| DIB_RGB_COLORS, | |||
| (void**) &bitmapData, | |||
| 0, 0); | |||
| hBitmap = CreateDIBSection (hdc, (BITMAPINFO*) &(bitmapInfo), DIB_RGB_COLORS, | |||
| (void**) &bitmapData, 0, 0); | |||
| previousBitmap = SelectObject (hdc, hBitmap); | |||
| @@ -218,6 +207,14 @@ public: | |||
| return new LowLevelGraphicsSoftwareRenderer (Image (this)); | |||
| } | |||
| void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode /*mode*/) | |||
| { | |||
| bitmap.data = imageData + x * pixelStride + y * lineStride; | |||
| bitmap.pixelFormat = format; | |||
| bitmap.lineStride = lineStride; | |||
| bitmap.pixelStride = pixelStride; | |||
| } | |||
| Image::SharedImage* clone() | |||
| { | |||
| WindowsBitmapImage* im = new WindowsBitmapImage (format, width, height, false); | |||
| @@ -318,6 +315,15 @@ public: | |||
| } | |||
| } | |||
| //============================================================================== | |||
| HBITMAP hBitmap; | |||
| HGDIOBJ previousBitmap; | |||
| BITMAPV4HEADER bitmapInfo; | |||
| HDC hdc; | |||
| uint8* bitmapData; | |||
| int pixelStride, lineStride; | |||
| uint8* imageData; | |||
| private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WindowsBitmapImage); | |||
| }; | |||
| @@ -342,7 +348,7 @@ namespace IconConverters | |||
| SelectObject (dc, bitmap); | |||
| im = Image (Image::ARGB, bm.bmWidth, bm.bmHeight, true); | |||
| Image::BitmapData imageData (im, true); | |||
| Image::BitmapData imageData (im, Image::BitmapData::writeOnly); | |||
| for (int y = bm.bmHeight; --y >= 0;) | |||
| { | |||