Skip to content

Commit

Permalink
Add support for CGImageCreateWithMask. (#1555)
Browse files Browse the repository at this point in the history
Fixes #1425.
  • Loading branch information
DHowett authored Dec 17, 2016
1 parent 7c5a470 commit 447e12e
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 5 deletions.
29 changes: 25 additions & 4 deletions Frameworks/CoreGraphics/CGImage.mm
Original file line number Diff line number Diff line change
Expand Up @@ -525,13 +525,34 @@ CGImageRef CGImageCreateCopyWithColorSpace(CGImageRef ref, CGColorSpaceRef color
}

/**
@Status Stub
@Status Interoperable
@Notes This function does not defer the composition of its mask.
This function supports non-grayscale alpha masks, unlike the reference platform.
*/
CGImageRef CGImageCreateWithMask(CGImageRef image, CGImageRef mask) {
// TODO #1425 - masks are applied during rendering via D2D.
RETURN_NULL_IF(!image);
UNIMPLEMENTED();
return StubReturn();
RETURN_NULL_IF(!mask);
RETURN_NULL_IF(CGImageIsMask(image));

size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);

woc::unique_cf<CGContextRef> context{ CGBitmapContextCreate(nullptr,
width,
height,
8,
width * 4,
CGImageGetColorSpace(image),
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big) };
RETURN_NULL_IF(!context);

CGRect rect{
CGPointZero, { width, height },
};
CGContextClipToMask(context.get(), rect, mask);
CGContextDrawImage(context.get(), rect, image);

return CGBitmapContextCreateImage(context.get());
}

/**
Expand Down
2 changes: 1 addition & 1 deletion include/CoreGraphics/CGImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ COREGRAPHICS_EXPORT CGImageRef CGImageCreateWithPNGDataProvider(CGDataProviderRe

COREGRAPHICS_EXPORT CGImageRef CGImageCreateWithImageInRect(CGImageRef image, CGRect rect);

COREGRAPHICS_EXPORT CGImageRef CGImageCreateWithMask(CGImageRef image, CGImageRef mask) STUB_METHOD;
COREGRAPHICS_EXPORT CGImageRef CGImageCreateWithMask(CGImageRef image, CGImageRef mask);

COREGRAPHICS_EXPORT CGImageRef CGImageCreateWithMaskingColors(CGImageRef image, const CGFloat* components) STUB_METHOD;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,3 +366,74 @@ DRAW_TEST(CGContextClipping, ClipATransparencyLayer) {
// If the clip mask applies twice (wrong) it will be 25%.
CGContextEndTransparencyLayer(context);
}

DRAW_TEST(CGImage, CreateWithSameSizeMask) {
auto drawingConfig = DrawingTestConfig::Get();

woc::unique_cf<CFStringRef> testFilename{ _CFStringCreateWithStdString(drawingConfig->GetResourcePath("jpg1.jpg")) };
woc::unique_cf<CGImageRef> image{ _CGImageCreateFromJPEGFile(testFilename.get()) };
ASSERT_NE(nullptr, image);

CGSize imageSize{ static_cast<CGFloat>(CGImageGetWidth(image.get())), static_cast<CGFloat>(CGImageGetHeight(image.get())) };

woc::unique_cf<CGImageRef> alphaMask{
__CreateClipImage(imageSize,
ClippingTypeMask,
[](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, { CGPointZero, size });

CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 10.0);
CGContextStrokeRect(context, CGRectInset({ CGPointZero, size }, 20, 20));
})
};

ASSERT_NE(nullptr, alphaMask);

woc::unique_cf<CGImageRef> preMaskedImage{ CGImageCreateWithMask(image.get(), alphaMask.get()) };

ASSERT_NE(nullptr, preMaskedImage);

CGContextRef context = GetDrawingContext();
CGRect bounds = GetDrawingBounds();

CGContextDrawImage(context, bounds, preMaskedImage.get());
}

DRAW_TEST(CGImage, CreateWithScaledMask) {
auto drawingConfig = DrawingTestConfig::Get();

woc::unique_cf<CFStringRef> testFilename{ _CFStringCreateWithStdString(drawingConfig->GetResourcePath("jpg1.jpg")) };
woc::unique_cf<CGImageRef> image{ _CGImageCreateFromJPEGFile(testFilename.get()) };
ASSERT_NE(nullptr, image);

CGSize imageSize{ static_cast<CGFloat>(CGImageGetWidth(image.get())), static_cast<CGFloat>(CGImageGetHeight(image.get())) };

woc::unique_cf<CGImageRef> alphaMask{
__CreateClipImage({ 64, 64 },
ClippingTypeMask,
[](CGContextRef context, CGSize size, ClippingType clipType) {
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context, { CGPointZero, size });

CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 4.0);
CGPoint points[]{
{ 0, 0 }, { 64, 64 }, { 0, 64 }, { 64, 0 },
};
CGContextStrokeLineSegments(context, points, 4);
})
};

ASSERT_NE(nullptr, alphaMask);

woc::unique_cf<CGImageRef> preMaskedImage{ CGImageCreateWithMask(image.get(), alphaMask.get()) };

ASSERT_NE(nullptr, preMaskedImage);

CGContextRef context = GetDrawingContext();
CGRect bounds = GetDrawingBounds();

CGContextDrawImage(context, bounds, preMaskedImage.get());
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 447e12e

Please sign in to comment.