Browse Source

More graphics updates, including fixes for CoreGraphics on PPC macs. Fix for keypress recursion in AU plugins, and fix for tabs in the CodeEditorComponent

tags/2021-05-28
Julian Storer 16 years ago
parent
commit
95fcc168d8
7 changed files with 271 additions and 594 deletions
  1. +8
    -2
      extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm
  2. +161
    -328
      juce_amalgamated.cpp
  3. +4
    -1
      src/gui/components/code_editor/juce_CodeEditorComponent.cpp
  4. +8
    -59
      src/native/mac/juce_mac_CameraDevice.mm
  5. +61
    -34
      src/native/mac/juce_mac_CoreGraphicsContext.mm
  6. +1
    -30
      src/native/mac/juce_mac_MouseCursor.mm
  7. +28
    -140
      src/native/mac/juce_mac_NSViewComponentPeer.mm

+ 8
- 2
extras/audio plugins/wrapper/AU/juce_AU_Wrapper.mm View File

@@ -1359,8 +1359,14 @@ private:
{
// If we have an unused keypress, move the key-focus to a host window
// and re-inject the event..
[[hostWindow parentWindow] makeKeyWindow];
[NSApp postEvent: [NSApp currentEvent] atStart: YES];
static NSTimeInterval lastEventTime = 0; // check we're not recursively sending the same event
if (lastEventTime != [[NSApp currentEvent] timestamp])
{
lastEventTime = [[NSApp currentEvent] timestamp];
[[hostWindow parentWindow] makeKeyWindow];
[NSApp postEvent: [NSApp currentEvent] atStart: YES];
}
}
return false;


+ 161
- 328
juce_amalgamated.cpp View File

@@ -730,7 +730,7 @@ public:
the rest of the codebase.
*/

#define USE_COREGRAPHICS_RENDERING 0
#define USE_COREGRAPHICS_RENDERING 1

#if JUCE_IPHONE
#import <Foundation/Foundation.h>
@@ -44829,8 +44829,11 @@ void CodeEditorComponent::insertTextAtCaret (const String& newText)

void CodeEditorComponent::insertTabAtCaret()
{
if (CharacterFunctions::isWhitespace (caretPos.getCharacter()))
if (CharacterFunctions::isWhitespace (caretPos.getCharacter())
&& caretPos.getLineNumber() == caretPos.movedBy (1).getLineNumber())
{
moveCaretTo (document.findWordBreakAfter (caretPos), false);
}

if (useSpacesForTabs)
{
@@ -261310,6 +261313,7 @@ void Font::getPlatformDefaultFontNames (String& defaultSans, String& defaultSeri
class CoreGraphicsImage : public Image
{
public:

CoreGraphicsImage (const PixelFormat format,
const int imageWidth,
const int imageHeight,
@@ -261320,9 +261324,7 @@ public:
: CGColorSpaceCreateDeviceRGB();

context = CGBitmapContextCreate (imageData, imageWidth, imageHeight, 8, lineStride,
colourSpace,
format == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little)
: kCGBitmapByteOrderDefault);
colourSpace, getCGImageFlags (*this));

CGColorSpaceRelease (colourSpace);
}
@@ -261334,7 +261336,62 @@ public:

LowLevelGraphicsContext* createLowLevelContext();

static CGImageRef createImage (const Image& juceImage, const bool forAlpha, CGColorSpaceRef colourSpace) throw()
{
const CoreGraphicsImage* nativeImage = dynamic_cast <const CoreGraphicsImage*> (&juceImage);

if (nativeImage != 0 && (juceImage.getFormat() == Image::SingleChannel || ! forAlpha))
{
return CGBitmapContextCreateImage (nativeImage->context);
}
else
{
const Image::BitmapData srcData (juceImage, 0, 0, juceImage.getWidth(), juceImage.getHeight());

CGDataProviderRef provider = CGDataProviderCreateWithData (0, srcData.data, srcData.lineStride * srcData.pixelStride, 0);

CGImageRef imageRef = CGImageCreate (srcData.width, srcData.height,
8, srcData.pixelStride * 8, srcData.lineStride,
colourSpace, getCGImageFlags (juceImage), provider,
0, true, kCGRenderingIntentDefault);

CGDataProviderRelease (provider);
return imageRef;
}
}

static NSImage* createNSImage (const Image& image)
{
const ScopedAutoReleasePool pool;

NSImage* im = [[NSImage alloc] init];
[im setSize: NSMakeSize (image.getWidth(), image.getHeight())];
[im lockFocus];

CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef imageRef = createImage (image, false, colourSpace);
CGColorSpaceRelease (colourSpace);

CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
CGContextDrawImage (cg, CGRectMake (0, 0, image.getWidth(), image.getHeight()), imageRef);

CGImageRelease (imageRef);
[im unlockFocus];

return im;
}

CGContextRef context;

private:
static CGBitmapInfo getCGImageFlags (const Image& image) throw()
{
#if JUCE_BIG_ENDIAN
return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big) : kCGBitmapByteOrderDefault;
#else
return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little) : kCGBitmapByteOrderDefault;
#endif
}
};

Image* Image::createNativeImage (const PixelFormat format, const int imageWidth, const int imageHeight, const bool clearImage)
@@ -261423,7 +261480,7 @@ public:
if (! transform.isSingularity())
{
Image* singleChannelImage = createAlphaChannelImage (sourceImage);
CGImageRef image = createImage (*singleChannelImage, true);
CGImageRef image = CoreGraphicsImage::createImage (*singleChannelImage, true, greyColourSpace);

flip();
AffineTransform t (AffineTransform::scale (1.0f, -1.0f).translated (0, sourceImage.getHeight()).followedBy (transform));
@@ -261589,7 +261646,7 @@ public:
void drawImage (const Image& sourceImage, const Rectangle& srcClip,
const AffineTransform& transform, const bool fillEntireClipAsTiles)
{
CGImageRef fullImage = createImage (sourceImage, false);
CGImageRef fullImage = CoreGraphicsImage::createImage (sourceImage, false, rgbColourSpace);
CGImageRef image = CGImageCreateWithImageInRect (fullImage, CGRectMake (srcClip.getX(), sourceImage.getHeight() - srcClip.getBottom(),
srcClip.getWidth(), srcClip.getHeight()));
CGImageRelease (fullImage);
@@ -261887,35 +261944,6 @@ private:
}
}

CGImageRef createImage (const Image& juceImage, const bool forAlpha) const throw()
{
const CoreGraphicsImage* nativeImage = dynamic_cast <const CoreGraphicsImage*> (&juceImage);

if (nativeImage != 0 && (juceImage.getFormat() == Image::SingleChannel || ! forAlpha))
{
return CGBitmapContextCreateImage (nativeImage->context);
}
else
{
const Image::BitmapData srcData (juceImage, 0, 0, juceImage.getWidth(), juceImage.getHeight());

CGDataProviderRef provider = CGDataProviderCreateWithData (0, srcData.data, srcData.lineStride * srcData.pixelStride, 0);
CGColorSpaceRef colourSpace = forAlpha ? greyColourSpace : rgbColourSpace;

CGImageRef imageRef = CGImageCreate (srcData.width, srcData.height,
8, srcData.pixelStride * 8, srcData.lineStride,
colourSpace,
(juceImage.hasAlphaChannel() && ! forAlpha)
? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little)
: kCGBitmapByteOrderDefault,
provider,
0, true, kCGRenderingIntentDefault);

CGDataProviderRelease (provider);
return imageRef;
}
}

static Image* createAlphaChannelImage (const Image& im) throw()
{
if (im.getFormat() == Image::SingleChannel)
@@ -263519,38 +263547,9 @@ void juce_glViewport (const int w, const int h)

#if JUCE_MAC

static NSImage* juceImageToNSImage (const Image& image)
{
const ScopedAutoReleasePool pool;

const Image::BitmapData srcData (image, 0, 0, image.getWidth(), image.getHeight());

NSBitmapImageRep* rep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes: NULL
pixelsWide: srcData.width
pixelsHigh: srcData.height
bitsPerSample: 8
samplesPerPixel: image.hasAlphaChannel() ? 4 : 3
hasAlpha: image.hasAlphaChannel()
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bitmapFormat: (NSBitmapFormat) 0
bytesPerRow: srcData.lineStride
bitsPerPixel: srcData.pixelStride * 8];

unsigned char* newData = [rep bitmapData];
memcpy (newData, srcData.data, srcData.lineStride * srcData.height);

NSImage* im = [[NSImage alloc] init];
[im addRepresentation: rep];
[rep release];

return im;
}

void* juce_createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY) throw()
{
NSImage* im = juceImageToNSImage (image);
NSImage* im = CoreGraphicsImage::createNSImage (image);
NSCursor* c = [[NSCursor alloc] initWithImage: im
hotSpot: NSMakePoint (hotspotX, hotspotY)];
[im release];
@@ -265759,6 +265758,7 @@ void Font::getPlatformDefaultFontNames (String& defaultSans, String& defaultSeri
class CoreGraphicsImage : public Image
{
public:

CoreGraphicsImage (const PixelFormat format,
const int imageWidth,
const int imageHeight,
@@ -265769,9 +265769,7 @@ public:
: CGColorSpaceCreateDeviceRGB();

context = CGBitmapContextCreate (imageData, imageWidth, imageHeight, 8, lineStride,
colourSpace,
format == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little)
: kCGBitmapByteOrderDefault);
colourSpace, getCGImageFlags (*this));

CGColorSpaceRelease (colourSpace);
}
@@ -265783,7 +265781,62 @@ public:

LowLevelGraphicsContext* createLowLevelContext();

static CGImageRef createImage (const Image& juceImage, const bool forAlpha, CGColorSpaceRef colourSpace) throw()
{
const CoreGraphicsImage* nativeImage = dynamic_cast <const CoreGraphicsImage*> (&juceImage);

if (nativeImage != 0 && (juceImage.getFormat() == Image::SingleChannel || ! forAlpha))
{
return CGBitmapContextCreateImage (nativeImage->context);
}
else
{
const Image::BitmapData srcData (juceImage, 0, 0, juceImage.getWidth(), juceImage.getHeight());

CGDataProviderRef provider = CGDataProviderCreateWithData (0, srcData.data, srcData.lineStride * srcData.pixelStride, 0);

CGImageRef imageRef = CGImageCreate (srcData.width, srcData.height,
8, srcData.pixelStride * 8, srcData.lineStride,
colourSpace, getCGImageFlags (juceImage), provider,
0, true, kCGRenderingIntentDefault);

CGDataProviderRelease (provider);
return imageRef;
}
}

static NSImage* createNSImage (const Image& image)
{
const ScopedAutoReleasePool pool;

NSImage* im = [[NSImage alloc] init];
[im setSize: NSMakeSize (image.getWidth(), image.getHeight())];
[im lockFocus];

CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef imageRef = createImage (image, false, colourSpace);
CGColorSpaceRelease (colourSpace);

CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
CGContextDrawImage (cg, CGRectMake (0, 0, image.getWidth(), image.getHeight()), imageRef);

CGImageRelease (imageRef);
[im unlockFocus];

return im;
}

CGContextRef context;

private:
static CGBitmapInfo getCGImageFlags (const Image& image) throw()
{
#if JUCE_BIG_ENDIAN
return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big) : kCGBitmapByteOrderDefault;
#else
return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little) : kCGBitmapByteOrderDefault;
#endif
}
};

Image* Image::createNativeImage (const PixelFormat format, const int imageWidth, const int imageHeight, const bool clearImage)
@@ -265872,7 +265925,7 @@ public:
if (! transform.isSingularity())
{
Image* singleChannelImage = createAlphaChannelImage (sourceImage);
CGImageRef image = createImage (*singleChannelImage, true);
CGImageRef image = CoreGraphicsImage::createImage (*singleChannelImage, true, greyColourSpace);

flip();
AffineTransform t (AffineTransform::scale (1.0f, -1.0f).translated (0, sourceImage.getHeight()).followedBy (transform));
@@ -266038,7 +266091,7 @@ public:
void drawImage (const Image& sourceImage, const Rectangle& srcClip,
const AffineTransform& transform, const bool fillEntireClipAsTiles)
{
CGImageRef fullImage = createImage (sourceImage, false);
CGImageRef fullImage = CoreGraphicsImage::createImage (sourceImage, false, rgbColourSpace);
CGImageRef image = CGImageCreateWithImageInRect (fullImage, CGRectMake (srcClip.getX(), sourceImage.getHeight() - srcClip.getBottom(),
srcClip.getWidth(), srcClip.getHeight()));
CGImageRelease (fullImage);
@@ -266336,35 +266389,6 @@ private:
}
}

CGImageRef createImage (const Image& juceImage, const bool forAlpha) const throw()
{
const CoreGraphicsImage* nativeImage = dynamic_cast <const CoreGraphicsImage*> (&juceImage);

if (nativeImage != 0 && (juceImage.getFormat() == Image::SingleChannel || ! forAlpha))
{
return CGBitmapContextCreateImage (nativeImage->context);
}
else
{
const Image::BitmapData srcData (juceImage, 0, 0, juceImage.getWidth(), juceImage.getHeight());

CGDataProviderRef provider = CGDataProviderCreateWithData (0, srcData.data, srcData.lineStride * srcData.pixelStride, 0);
CGColorSpaceRef colourSpace = forAlpha ? greyColourSpace : rgbColourSpace;

CGImageRef imageRef = CGImageCreate (srcData.width, srcData.height,
8, srcData.pixelStride * 8, srcData.lineStride,
colourSpace,
(juceImage.hasAlphaChannel() && ! forAlpha)
? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little)
: kCGBitmapByteOrderDefault,
provider,
0, true, kCGRenderingIntentDefault);

CGDataProviderRelease (provider);
return imageRef;
}
}

static Image* createAlphaChannelImage (const Image& im) throw()
{
if (im.getFormat() == Image::SingleChannel)
@@ -266928,122 +266952,6 @@ END_JUCE_NAMESPACE

BEGIN_JUCE_NAMESPACE

class JuceNSImage
{
public:
JuceNSImage (const int width, const int height, const bool hasAlpha)
: juceImage (hasAlpha ? Image::ARGB : Image::RGB,
width, height, hasAlpha),
srcData (juceImage, 0, 0, width, height)
{
imageRep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes: (unsigned char**) &(srcData.data)
pixelsWide: width
pixelsHigh: height
bitsPerSample: 8
samplesPerPixel: srcData.pixelStride
hasAlpha: hasAlpha
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bitmapFormat: /*NSAlphaFirstBitmapFormat*/ (NSBitmapFormat) 0
bytesPerRow: srcData.lineStride
bitsPerPixel: 8 * srcData.pixelStride ];
}

~JuceNSImage()
{
[imageRep release];
}

Image& getJuceImage() throw() { return juceImage; }

void draw (const float x, const float y,
const RectangleList& clip,
const int originX, const int originY) const
{
// Our data is BGRA and the damned image rep only takes RGBA, so
// we need to byte-swap the active areas if there's an alpha channel...
if (juceImage.hasAlphaChannel())
{
RectangleList::Iterator iter (clip);
while (iter.next())
{
const Rectangle* const r = iter.getRectangle();

swapRGBOrder (r->getX() + originX,
r->getY() + originY,
r->getWidth(),
r->getHeight());
}
}

NSPoint p;
p.x = x;
p.y = y;
[imageRep drawAtPoint: p];
}

void drawNSImage (NSImage* imageToDraw)
{
const ScopedAutoReleasePool pool;

[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:
[NSGraphicsContext graphicsContextWithBitmapImageRep: imageRep]];

[imageToDraw drawAtPoint: NSZeroPoint
fromRect: NSMakeRect (0, 0, [imageToDraw size].width, [imageToDraw size].height)
operation: NSCompositeSourceOver
fraction: 1.0f];

[[NSGraphicsContext currentContext] flushGraphics];
[NSGraphicsContext restoreGraphicsState];

if (juceImage.hasAlphaChannel())
swapRGBOrder (0, 0, juceImage.getWidth(), juceImage.getHeight());
}

private:
Image juceImage;
NSBitmapImageRep* imageRep;
const Image::BitmapData srcData;

void swapRGBOrder (const int x, const int y, const int w, int h) const
{
#if JUCE_BIG_ENDIAN
jassert (srcData.pixelStride == 4);
#endif
jassert (Rectangle (0, 0, juceImage.getWidth(), juceImage.getHeight())
.contains (Rectangle (x, y, w, h)));

uint8* start = srcData.getPixelPointer (x, y);

while (--h >= 0)
{
uint8* p = start;
start += srcData.lineStride;

for (int i = w; --i >= 0;)
{
#if JUCE_BIG_ENDIAN
const uint8 oldp3 = p[3];
const uint8 oldp1 = p[1];
p[3] = p[0];
p[0] = oldp1;
p[1] = p[2];
p[2] = oldp3;
#else
const uint8 oldp0 = p[0];
p[0] = p[2];
p[2] = oldp0;
#endif

p += srcData.pixelStride;
}
}
}
};

static ComponentPeer* currentlyFocusedPeer = 0;
static VoidArray keysCurrentlyDown;

@@ -267801,28 +267709,26 @@ void NSViewComponentPeer::drawRect (NSRect r)
if (r.size.width < 1.0f || r.size.height < 1.0f)
return;

#if USE_COREGRAPHICS_RENDERING
CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];

if (! component->isOpaque())
CGContextClearRect (cg, CGContextGetClipBoundingBox (cg));

#if USE_COREGRAPHICS_RENDERING
CoreGraphicsContext context (cg, [view frame].size.height);

insideDrawRect = true;
handlePaint (context);
insideDrawRect = false;
#else
const float y = [view frame].size.height - (r.origin.y + r.size.height);

JuceNSImage temp ((int) (r.size.width + 0.5f),
(int) (r.size.height + 0.5f),
! getComponent()->isOpaque());
Image temp (getComponent()->isOpaque() ? Image::RGB : Image::ARGB,
(int) (r.size.width + 0.5f),
(int) (r.size.height + 0.5f),
! getComponent()->isOpaque());

LowLevelGraphicsSoftwareRenderer context (temp.getJuceImage());
const int originX = -roundFloatToInt (r.origin.x);
const int originY = -roundFloatToInt (y);
context.setOrigin (originX, originY);
LowLevelGraphicsSoftwareRenderer context (temp);
context.setOrigin (-roundFloatToInt (r.origin.x),
-roundFloatToInt ([view frame].size.height - (r.origin.y + r.size.height)));

const NSRect* rects = 0;
NSInteger numRects = 0;
@@ -267843,7 +267749,11 @@ void NSViewComponentPeer::drawRect (NSRect r)
handlePaint (context);
insideDrawRect = false;

temp.draw (r.origin.x, r.origin.y, clip, originX, originY);
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef image = CoreGraphicsImage::createImage (temp, false, colourSpace);
CGColorSpaceRelease (colourSpace);
CGContextDrawImage (cg, CGRectMake (r.origin.x, r.origin.y, temp.getWidth(), temp.getHeight()), image);
CGImageRelease (image);
}
#endif
}
@@ -267930,22 +267840,25 @@ ComponentPeer* Component::createNewPeer (int styleFlags, void* windowToAttachTo)
return new NSViewComponentPeer (this, styleFlags, (NSView*) windowToAttachTo);
}

static Image* NSImageToJuceImage (NSImage* image)
{
JuceNSImage juceIm ((int) [image size].width,
(int) [image size].height,
true);

juceIm.drawNSImage (image);
return juceIm.getJuceImage().createCopy();
}

Image* juce_createIconForFile (const File& file)
{
const ScopedAutoReleasePool pool;

NSImage* im = [[NSWorkspace sharedWorkspace] iconForFile: juceStringToNS (file.getFullPathName())];
return NSImageToJuceImage (im);
NSImage* image = [[NSWorkspace sharedWorkspace] iconForFile: juceStringToNS (file.getFullPathName())];

CoreGraphicsImage* result = new CoreGraphicsImage (Image::ARGB, (int) [image size].width, (int) [image size].height, true);

[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithGraphicsPort: result->context flipped: false]];

[image drawAtPoint: NSMakePoint (0, 0)
fromRect: NSMakeRect (0, 0, [image size].width, [image size].height)
operation: NSCompositeSourceOver fraction: 1.0f];

[[NSGraphicsContext currentContext] flushGraphics];
[NSGraphicsContext restoreGraphicsState];

return result;
}

const int KeyPress::spaceKey = ' ';
@@ -268012,38 +267925,9 @@ const int KeyPress::rewindKey = 0x30003;

#if JUCE_MAC

static NSImage* juceImageToNSImage (const Image& image)
{
const ScopedAutoReleasePool pool;

const Image::BitmapData srcData (image, 0, 0, image.getWidth(), image.getHeight());

NSBitmapImageRep* rep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes: NULL
pixelsWide: srcData.width
pixelsHigh: srcData.height
bitsPerSample: 8
samplesPerPixel: image.hasAlphaChannel() ? 4 : 3
hasAlpha: image.hasAlphaChannel()
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bitmapFormat: (NSBitmapFormat) 0
bytesPerRow: srcData.lineStride
bitsPerPixel: srcData.pixelStride * 8];

unsigned char* newData = [rep bitmapData];
memcpy (newData, srcData.data, srcData.lineStride * srcData.height);

NSImage* im = [[NSImage alloc] init];
[im addRepresentation: rep];
[rep release];

return im;
}

void* juce_createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY) throw()
{
NSImage* im = juceImageToNSImage (image);
NSImage* im = CoreGraphicsImage::createNSImage (image);
NSCursor* c = [[NSCursor alloc] initWithImage: im
hotSpot: NSMakePoint (hotspotX, hotspotY)];
[im release];
@@ -273104,63 +272988,12 @@ public:
[session removeOutput: imageOutput];
}

static void drawNSBitmapIntoJuceImage (Image& dest, NSBitmapImageRep* source)
{
const ScopedAutoReleasePool pool;

const Image::BitmapData destData (dest, 0, 0, dest.getWidth(), dest.getHeight(), true);

NSBitmapImageRep* rep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes: (unsigned char**) &(destData.data)
pixelsWide: destData.width
pixelsHigh: destData.height
bitsPerSample: 8
samplesPerPixel: destData.pixelStride
hasAlpha: dest.hasAlphaChannel()
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bitmapFormat: (NSBitmapFormat) 0
bytesPerRow: destData.lineStride
bitsPerPixel: destData.pixelStride * 8];

[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithBitmapImageRep: rep]];

[source drawAtPoint: NSZeroPoint];

[[NSGraphicsContext currentContext] flushGraphics];
[NSGraphicsContext restoreGraphicsState];

uint8* start = destData.data;
for (int h = dest.getHeight(); --h >= 0;)
{
uint8* p = start;
start += destData.lineStride;

for (int i = dest.getWidth(); --i >= 0;)
{
#if JUCE_BIG_ENDIAN
const uint8 oldp3 = p[3];
const uint8 oldp1 = p[1];
p[3] = p[0];
p[0] = oldp1;
p[1] = p[2];
p[2] = oldp3;
#else
const uint8 oldp0 = p[0];
p[0] = p[2];
p[2] = oldp0;
#endif

p += destData.pixelStride;
}
}
}

void callListeners (NSBitmapImageRep* bitmap)
void callListeners (CIImage* frame, int w, int h)
{
Image image (Image::ARGB, [bitmap size].width, [bitmap size].height, false);
drawNSBitmapIntoJuceImage (image, bitmap);
CoreGraphicsImage image (Image::ARGB, w, h, false);
CIContext* cic = [CIContext contextWithCGContext: image.context options: nil];
[cic drawImage: frame inRect: CGRectMake (0, 0, w, h) fromRect: CGRectMake (0, 0, w, h)];
CGContextFlush (image.context);

const ScopedLock sl (listenerLock);

@@ -273210,10 +273043,10 @@ END_JUCE_NAMESPACE
fromConnection: (QTCaptureConnection*) connection
{
const ScopedAutoReleasePool pool;
CIImage* image = [CIImage imageWithCVImageBuffer: videoFrame];
NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] initWithCIImage: image] autorelease];

internal->callListeners (bitmap);
internal->callListeners ([CIImage imageWithCVImageBuffer: videoFrame],
CVPixelBufferGetWidth (videoFrame),
CVPixelBufferGetHeight (videoFrame));
}

- (void) captureOutput: (QTCaptureFileOutput*) captureOutput


+ 4
- 1
src/gui/components/code_editor/juce_CodeEditorComponent.cpp View File

@@ -618,8 +618,11 @@ void CodeEditorComponent::insertTextAtCaret (const String& newText)
void CodeEditorComponent::insertTabAtCaret()
{
if (CharacterFunctions::isWhitespace (caretPos.getCharacter()))
if (CharacterFunctions::isWhitespace (caretPos.getCharacter())
&& caretPos.getLineNumber() == caretPos.movedBy (1).getLineNumber())
{
moveCaretTo (document.findWordBreakAfter (caretPos), false);
}
if (useSpacesForTabs)
{


+ 8
- 59
src/native/mac/juce_mac_CameraDevice.mm View File

@@ -145,63 +145,12 @@ public:
[session removeOutput: imageOutput];
}
static void drawNSBitmapIntoJuceImage (Image& dest, NSBitmapImageRep* source)
void callListeners (CIImage* frame, int w, int h)
{
const ScopedAutoReleasePool pool;
const Image::BitmapData destData (dest, 0, 0, dest.getWidth(), dest.getHeight(), true);
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes: (unsigned char**) &(destData.data)
pixelsWide: destData.width
pixelsHigh: destData.height
bitsPerSample: 8
samplesPerPixel: destData.pixelStride
hasAlpha: dest.hasAlphaChannel()
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bitmapFormat: (NSBitmapFormat) 0
bytesPerRow: destData.lineStride
bitsPerPixel: destData.pixelStride * 8];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithBitmapImageRep: rep]];
[source drawAtPoint: NSZeroPoint];
[[NSGraphicsContext currentContext] flushGraphics];
[NSGraphicsContext restoreGraphicsState];
uint8* start = destData.data;
for (int h = dest.getHeight(); --h >= 0;)
{
uint8* p = start;
start += destData.lineStride;
for (int i = dest.getWidth(); --i >= 0;)
{
#if JUCE_BIG_ENDIAN
const uint8 oldp3 = p[3];
const uint8 oldp1 = p[1];
p[3] = p[0];
p[0] = oldp1;
p[1] = p[2];
p[2] = oldp3;
#else
const uint8 oldp0 = p[0];
p[0] = p[2];
p[2] = oldp0;
#endif
p += destData.pixelStride;
}
}
}
void callListeners (NSBitmapImageRep* bitmap)
{
Image image (Image::ARGB, [bitmap size].width, [bitmap size].height, false);
drawNSBitmapIntoJuceImage (image, bitmap);
CoreGraphicsImage image (Image::ARGB, w, h, false);
CIContext* cic = [CIContext contextWithCGContext: image.context options: nil];
[cic drawImage: frame inRect: CGRectMake (0, 0, w, h) fromRect: CGRectMake (0, 0, w, h)];
CGContextFlush (image.context);
const ScopedLock sl (listenerLock);
@@ -251,10 +200,10 @@ END_JUCE_NAMESPACE
fromConnection: (QTCaptureConnection*) connection
{
const ScopedAutoReleasePool pool;
CIImage* image = [CIImage imageWithCVImageBuffer: videoFrame];
NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] initWithCIImage: image] autorelease];
internal->callListeners (bitmap);
internal->callListeners ([CIImage imageWithCVImageBuffer: videoFrame],
CVPixelBufferGetWidth (videoFrame),
CVPixelBufferGetHeight (videoFrame));
}
- (void) captureOutput: (QTCaptureFileOutput*) captureOutput


+ 61
- 34
src/native/mac/juce_mac_CoreGraphicsContext.mm View File

@@ -31,6 +31,7 @@
class CoreGraphicsImage : public Image
{
public:
//==============================================================================
CoreGraphicsImage (const PixelFormat format,
const int imageWidth,
const int imageHeight,
@@ -41,9 +42,7 @@ public:
: CGColorSpaceCreateDeviceRGB();
context = CGBitmapContextCreate (imageData, imageWidth, imageHeight, 8, lineStride,
colourSpace,
format == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little)
: kCGBitmapByteOrderDefault);
colourSpace, getCGImageFlags (*this));
CGColorSpaceRelease (colourSpace);
}
@@ -55,7 +54,64 @@ public:
LowLevelGraphicsContext* createLowLevelContext();
//==============================================================================
static CGImageRef createImage (const Image& juceImage, const bool forAlpha, CGColorSpaceRef colourSpace) throw()
{
const CoreGraphicsImage* nativeImage = dynamic_cast <const CoreGraphicsImage*> (&juceImage);
if (nativeImage != 0 && (juceImage.getFormat() == Image::SingleChannel || ! forAlpha))
{
return CGBitmapContextCreateImage (nativeImage->context);
}
else
{
const Image::BitmapData srcData (juceImage, 0, 0, juceImage.getWidth(), juceImage.getHeight());
CGDataProviderRef provider = CGDataProviderCreateWithData (0, srcData.data, srcData.lineStride * srcData.pixelStride, 0);
CGImageRef imageRef = CGImageCreate (srcData.width, srcData.height,
8, srcData.pixelStride * 8, srcData.lineStride,
colourSpace, getCGImageFlags (juceImage), provider,
0, true, kCGRenderingIntentDefault);
CGDataProviderRelease (provider);
return imageRef;
}
}
static NSImage* createNSImage (const Image& image)
{
const ScopedAutoReleasePool pool;
NSImage* im = [[NSImage alloc] init];
[im setSize: NSMakeSize (image.getWidth(), image.getHeight())];
[im lockFocus];
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef imageRef = createImage (image, false, colourSpace);
CGColorSpaceRelease (colourSpace);
CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
CGContextDrawImage (cg, CGRectMake (0, 0, image.getWidth(), image.getHeight()), imageRef);
CGImageRelease (imageRef);
[im unlockFocus];
return im;
}
//==============================================================================
CGContextRef context;
private:
static CGBitmapInfo getCGImageFlags (const Image& image) throw()
{
#if JUCE_BIG_ENDIAN
return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big) : kCGBitmapByteOrderDefault;
#else
return image.getFormat() == Image::ARGB ? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little) : kCGBitmapByteOrderDefault;
#endif
}
};
Image* Image::createNativeImage (const PixelFormat format, const int imageWidth, const int imageHeight, const bool clearImage)
@@ -146,7 +202,7 @@ public:
if (! transform.isSingularity())
{
Image* singleChannelImage = createAlphaChannelImage (sourceImage);
CGImageRef image = createImage (*singleChannelImage, true);
CGImageRef image = CoreGraphicsImage::createImage (*singleChannelImage, true, greyColourSpace);
flip();
AffineTransform t (AffineTransform::scale (1.0f, -1.0f).translated (0, sourceImage.getHeight()).followedBy (transform));
@@ -315,7 +371,7 @@ public:
void drawImage (const Image& sourceImage, const Rectangle& srcClip,
const AffineTransform& transform, const bool fillEntireClipAsTiles)
{
CGImageRef fullImage = createImage (sourceImage, false);
CGImageRef fullImage = CoreGraphicsImage::createImage (sourceImage, false, rgbColourSpace);
CGImageRef image = CGImageCreateWithImageInRect (fullImage, CGRectMake (srcClip.getX(), sourceImage.getHeight() - srcClip.getBottom(),
srcClip.getWidth(), srcClip.getHeight()));
CGImageRelease (fullImage);
@@ -614,35 +670,6 @@ private:
}
}
CGImageRef createImage (const Image& juceImage, const bool forAlpha) const throw()
{
const CoreGraphicsImage* nativeImage = dynamic_cast <const CoreGraphicsImage*> (&juceImage);
if (nativeImage != 0 && (juceImage.getFormat() == Image::SingleChannel || ! forAlpha))
{
return CGBitmapContextCreateImage (nativeImage->context);
}
else
{
const Image::BitmapData srcData (juceImage, 0, 0, juceImage.getWidth(), juceImage.getHeight());
CGDataProviderRef provider = CGDataProviderCreateWithData (0, srcData.data, srcData.lineStride * srcData.pixelStride, 0);
CGColorSpaceRef colourSpace = forAlpha ? greyColourSpace : rgbColourSpace;
CGImageRef imageRef = CGImageCreate (srcData.width, srcData.height,
8, srcData.pixelStride * 8, srcData.lineStride,
colourSpace,
(juceImage.hasAlphaChannel() && ! forAlpha)
? (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little)
: kCGBitmapByteOrderDefault,
provider,
0, true, kCGRenderingIntentDefault);
CGDataProviderRelease (provider);
return imageRef;
}
}
static Image* createAlphaChannelImage (const Image& im) throw()
{
if (im.getFormat() == Image::SingleChannel)


+ 1
- 30
src/native/mac/juce_mac_MouseCursor.mm View File

@@ -29,40 +29,11 @@
#if JUCE_MAC
//==============================================================================
static NSImage* juceImageToNSImage (const Image& image)
{
const ScopedAutoReleasePool pool;
const Image::BitmapData srcData (image, 0, 0, image.getWidth(), image.getHeight());
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes: NULL
pixelsWide: srcData.width
pixelsHigh: srcData.height
bitsPerSample: 8
samplesPerPixel: image.hasAlphaChannel() ? 4 : 3
hasAlpha: image.hasAlphaChannel()
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bitmapFormat: (NSBitmapFormat) 0
bytesPerRow: srcData.lineStride
bitsPerPixel: srcData.pixelStride * 8];
unsigned char* newData = [rep bitmapData];
memcpy (newData, srcData.data, srcData.lineStride * srcData.height);
NSImage* im = [[NSImage alloc] init];
[im addRepresentation: rep];
[rep release];
return im;
}
//==============================================================================
void* juce_createMouseCursorFromImage (const Image& image, int hotspotX, int hotspotY) throw()
{
NSImage* im = juceImageToNSImage (image);
NSImage* im = CoreGraphicsImage::createNSImage (image);
NSCursor* c = [[NSCursor alloc] initWithImage: im
hotSpot: NSMakePoint (hotspotX, hotspotY)];
[im release];


+ 28
- 140
src/native/mac/juce_mac_NSViewComponentPeer.mm View File

@@ -555,123 +555,6 @@ END_JUCE_NAMESPACE
//==============================================================================
BEGIN_JUCE_NAMESPACE
//==============================================================================
class JuceNSImage
{
public:
JuceNSImage (const int width, const int height, const bool hasAlpha)
: juceImage (hasAlpha ? Image::ARGB : Image::RGB,
width, height, hasAlpha),
srcData (juceImage, 0, 0, width, height)
{
imageRep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes: (unsigned char**) &(srcData.data)
pixelsWide: width
pixelsHigh: height
bitsPerSample: 8
samplesPerPixel: srcData.pixelStride
hasAlpha: hasAlpha
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bitmapFormat: /*NSAlphaFirstBitmapFormat*/ (NSBitmapFormat) 0
bytesPerRow: srcData.lineStride
bitsPerPixel: 8 * srcData.pixelStride ];
}
~JuceNSImage()
{
[imageRep release];
}
Image& getJuceImage() throw() { return juceImage; }
void draw (const float x, const float y,
const RectangleList& clip,
const int originX, const int originY) const
{
// Our data is BGRA and the damned image rep only takes RGBA, so
// we need to byte-swap the active areas if there's an alpha channel...
if (juceImage.hasAlphaChannel())
{
RectangleList::Iterator iter (clip);
while (iter.next())
{
const Rectangle* const r = iter.getRectangle();
swapRGBOrder (r->getX() + originX,
r->getY() + originY,
r->getWidth(),
r->getHeight());
}
}
NSPoint p;
p.x = x;
p.y = y;
[imageRep drawAtPoint: p];
}
void drawNSImage (NSImage* imageToDraw)
{
const ScopedAutoReleasePool pool;
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:
[NSGraphicsContext graphicsContextWithBitmapImageRep: imageRep]];
[imageToDraw drawAtPoint: NSZeroPoint
fromRect: NSMakeRect (0, 0, [imageToDraw size].width, [imageToDraw size].height)
operation: NSCompositeSourceOver
fraction: 1.0f];
[[NSGraphicsContext currentContext] flushGraphics];
[NSGraphicsContext restoreGraphicsState];
if (juceImage.hasAlphaChannel())
swapRGBOrder (0, 0, juceImage.getWidth(), juceImage.getHeight());
}
private:
Image juceImage;
NSBitmapImageRep* imageRep;
const Image::BitmapData srcData;
void swapRGBOrder (const int x, const int y, const int w, int h) const
{
#if JUCE_BIG_ENDIAN
jassert (srcData.pixelStride == 4);
#endif
jassert (Rectangle (0, 0, juceImage.getWidth(), juceImage.getHeight())
.contains (Rectangle (x, y, w, h)));
uint8* start = srcData.getPixelPointer (x, y);
while (--h >= 0)
{
uint8* p = start;
start += srcData.lineStride;
for (int i = w; --i >= 0;)
{
#if JUCE_BIG_ENDIAN
const uint8 oldp3 = p[3];
const uint8 oldp1 = p[1];
p[3] = p[0];
p[0] = oldp1;
p[1] = p[2];
p[2] = oldp3;
#else
const uint8 oldp0 = p[0];
p[0] = p[2];
p[2] = oldp0;
#endif
p += srcData.pixelStride;
}
}
}
};
//==============================================================================
static ComponentPeer* currentlyFocusedPeer = 0;
static VoidArray keysCurrentlyDown;
@@ -1435,28 +1318,26 @@ void NSViewComponentPeer::drawRect (NSRect r)
if (r.size.width < 1.0f || r.size.height < 1.0f)
return;
#if USE_COREGRAPHICS_RENDERING
CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort];
if (! component->isOpaque())
CGContextClearRect (cg, CGContextGetClipBoundingBox (cg));
#if USE_COREGRAPHICS_RENDERING
CoreGraphicsContext context (cg, [view frame].size.height);
insideDrawRect = true;
handlePaint (context);
insideDrawRect = false;
#else
const float y = [view frame].size.height - (r.origin.y + r.size.height);
JuceNSImage temp ((int) (r.size.width + 0.5f),
(int) (r.size.height + 0.5f),
! getComponent()->isOpaque());
Image temp (getComponent()->isOpaque() ? Image::RGB : Image::ARGB,
(int) (r.size.width + 0.5f),
(int) (r.size.height + 0.5f),
! getComponent()->isOpaque());
LowLevelGraphicsSoftwareRenderer context (temp.getJuceImage());
const int originX = -roundFloatToInt (r.origin.x);
const int originY = -roundFloatToInt (y);
context.setOrigin (originX, originY);
LowLevelGraphicsSoftwareRenderer context (temp);
context.setOrigin (-roundFloatToInt (r.origin.x),
-roundFloatToInt ([view frame].size.height - (r.origin.y + r.size.height)));
const NSRect* rects = 0;
NSInteger numRects = 0;
@@ -1477,7 +1358,11 @@ void NSViewComponentPeer::drawRect (NSRect r)
handlePaint (context);
insideDrawRect = false;
temp.draw (r.origin.x, r.origin.y, clip, originX, originY);
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGImageRef image = CoreGraphicsImage::createImage (temp, false, colourSpace);
CGColorSpaceRelease (colourSpace);
CGContextDrawImage (cg, CGRectMake (r.origin.x, r.origin.y, temp.getWidth(), temp.getHeight()), image);
CGImageRelease (image);
}
#endif
}
@@ -1567,22 +1452,25 @@ ComponentPeer* Component::createNewPeer (int styleFlags, void* windowToAttachTo)
}
//==============================================================================
static Image* NSImageToJuceImage (NSImage* image)
{
JuceNSImage juceIm ((int) [image size].width,
(int) [image size].height,
true);
juceIm.drawNSImage (image);
return juceIm.getJuceImage().createCopy();
}
Image* juce_createIconForFile (const File& file)
{
const ScopedAutoReleasePool pool;
NSImage* im = [[NSWorkspace sharedWorkspace] iconForFile: juceStringToNS (file.getFullPathName())];
return NSImageToJuceImage (im);
NSImage* image = [[NSWorkspace sharedWorkspace] iconForFile: juceStringToNS (file.getFullPathName())];
CoreGraphicsImage* result = new CoreGraphicsImage (Image::ARGB, (int) [image size].width, (int) [image size].height, true);
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithGraphicsPort: result->context flipped: false]];
[image drawAtPoint: NSMakePoint (0, 0)
fromRect: NSMakeRect (0, 0, [image size].width, [image size].height)
operation: NSCompositeSourceOver fraction: 1.0f];
[[NSGraphicsContext currentContext] flushGraphics];
[NSGraphicsContext restoreGraphicsState];
return result;
}
//==============================================================================


Loading…
Cancel
Save