@@ -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;) | |||
{ | |||