Skip to content

Commit

Permalink
more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
msft-Jeyaram committed Nov 15, 2016
1 parent 605d4ca commit 46d8097
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 58 deletions.
29 changes: 10 additions & 19 deletions Frameworks/CoreGraphics/CGContext.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1835,9 +1835,8 @@ inline void SetImage(CGImageRef image) {

/**
@Status Caveat
@Notes If the image colorspace is not a valid render target format (as per
https://msdn.microsoft.com/en-us/library/windows/desktop/dd756766(v=vs.85).aspx#supported_wic_formats), it's converted to 32bpp BGRA
format. Does not support conversion if data is already provided.
The following formats are supported GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppBGR and
GUID_WICPixelFormat8bppAlpha. Any other format will return a null value.
*/
CGContextRef CGBitmapContextCreate(void* data,
size_t width,
Expand All @@ -1851,9 +1850,9 @@ CGContextRef CGBitmapContextCreate(void* data,

/**
@Status Caveat
@Notes releaseCallback and releaseInfo is ignored. Also if the image colorspace is not a valid render target format (as per
https://msdn.microsoft.com/en-us/library/windows/desktop/dd756766(v=vs.85).aspx#supported_wic_formats), it's converted to 32bpp BGRA
format. Does not support conversion if data is already provided.
@Notes releaseCallback and releaseInfo is ignored.
The following formats are supported GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppBGR and
GUID_WICPixelFormat8bppAlpha. Any other format will return a null value.
*/
CGContextRef CGBitmapContextCreateWithData(void* data,
size_t width,
Expand All @@ -1872,21 +1871,13 @@ CGContextRef CGBitmapContextCreateWithData(void* data,
size_t bitsPerPixel = ((bytesPerRow / width) << 3);
REFGUID pixelFormat = _CGImageGetWICPixelFormatFromImageProperties(bitsPerComponent, bitsPerPixel, space, bitmapInfo);

ComPtr<IWICBitmap> customBitmap;

if (_CGIsValidRenderTargetPixelFormat(pixelFormat)) {
// if data is null, enough memory is allocated via CGIWICBitmap
customBitmap = Make<CGIWICBitmap>(data, pixelFormat, height, width);
} else {
// TODO #<GITHUB-ID>: this will be an issue if we have change in stride, account for that.
// Also as per documentation, it's best to leave CGBitmapContext to manage the memory
if (data != nullptr) {
UNIMPLEMENTED_WITH_MSG("Does not support conversion to supported rendering target format, if the data was provided.");
return nullptr;
}
customBitmap = Make<CGIWICBitmap>(data, GUID_WICPixelFormat32bppPBGRA, height, width);
if (!_CGIsValidRenderTargetPixelFormat(pixelFormat)) {
UNIMPLEMENTED_WITH_MSG("CGBitmapContext does not currently support conversion and can only render into 32bpp PRGBA buffers.");
return nullptr;
}

// if data is null, enough memory is allocated via CGIWICBitmap
ComPtr<IWICBitmap> customBitmap = Make<CGIWICBitmap>(data, pixelFormat, height, width);
RETURN_NULL_IF(!customBitmap);

woc::unique_cf<CGImageRef> image(_CGImageCreateWithWICBitmap(customBitmap.Get()));
Expand Down
2 changes: 1 addition & 1 deletion Frameworks/include/CGIWICBitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class CGIWICBitmap

~CGIWICBitmap() {
if (m_freeData) {
delete m_dataBuffer;
delete[] m_dataBuffer;
m_dataBuffer = nullptr;
m_freeData = false;
}
Expand Down
93 changes: 55 additions & 38 deletions tests/unittests/CoreGraphics/CGBitmapContextTests.mm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//******************************************************************************
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
Expand Down Expand Up @@ -44,41 +44,6 @@
CGContextRelease(context);
}

TEST(CGBitmapContext, BitmapInfoAPIs_RGB) {
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(nullptr, 0, 0, 8, 0, rgbColorSpace, 0);
EXPECT_EQ(nullptr, context);

context = CGBitmapContextCreate(nullptr, 5, 5, 20, 8, rgbColorSpace, 0);

EXPECT_EQ(CGBitmapContextGetWidth(context), 5);
EXPECT_EQ(CGBitmapContextGetHeight(context), 5);
EXPECT_EQ(CGBitmapContextGetBitsPerComponent(context), 8);
EXPECT_EQ(CGBitmapContextGetBitsPerPixel(context), 32);

CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
}

TEST(CGBitmapContext, BitmapInfoAPIs_Gray) {
CGColorSpaceRef grayColorSpace = CGColorSpaceCreateDeviceGray();
CGContextRef context = CGBitmapContextCreate(0, 0, 0, 8, 0, grayColorSpace, 0);
EXPECT_EQ(context, nullptr);

context = CGBitmapContextCreate(nullptr, 120, 20, 8, 480, grayColorSpace, 0);

EXPECT_EQ(CGBitmapContextGetBitsPerComponent(context), 8);
EXPECT_EQ(CGBitmapContextGetBitsPerPixel(context), 32);
EXPECT_EQ(CGBitmapContextGetWidth(context), 120);
EXPECT_EQ(CGBitmapContextGetHeight(context), 20);

EXPECT_EQ(CGBitmapContextGetBytesPerRow(context), 480);
EXPECT_NE(CGBitmapContextGetData(context), nullptr);

CGColorSpaceRelease(grayColorSpace);
CGContextRelease(context);
}

void _DrawText(CGContextRef context, NSString* text, const CGRect bounds) {
// Aligns origin for our frame
CGContextTranslateCTM(context, 0.0f, bounds.size.height);
Expand Down Expand Up @@ -182,10 +147,25 @@ void _TestPixelFormat(const CGRect bounds, const CGBitmapInfo info, DWORD expect
);
}

TEST(CGBitmapContext, Contexts) {
static void _expectArrayValues(BYTE* res, BYTE* source, int size) {
for (int i = 0; i < size; ++i) {
EXPECT_EQ(res[i], source[i]);
}
}

TEST(CGBitmapContext, BitmapInfoAPIs_Gray) {
CGColorSpaceRef grayColorSpace = CGColorSpaceCreateDeviceGray();
CGContextRef context = CGBitmapContextCreate(0, 0, 0, 8, 0, grayColorSpace, 0);
EXPECT_EQ(context, nullptr);

context = CGBitmapContextCreate(nullptr, 120, 20, 8, 480, grayColorSpace, 0);
EXPECT_EQ(context, nullptr);
}

TEST(CGBitmapContext, BitmapInfoAPIs_RGB) {
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();

CGContextRef context = CGBitmapContextCreate(nullptr, 120, 20, 8, 480, rgbColorSpace, 0);
CGContextRef context = CGBitmapContextCreate(nullptr, 120, 20, 8, 480, rgbColorSpace, kCGImageAlphaPremultipliedFirst);

EXPECT_EQ(CGBitmapContextGetBitsPerComponent(context), 8);
EXPECT_EQ(CGBitmapContextGetBitsPerPixel(context), 32);
Expand All @@ -198,3 +178,40 @@ void _TestPixelFormat(const CGRect bounds, const CGBitmapInfo info, DWORD expect
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
}

TEST(CGBitmapContext, Rendering) {
woc::unique_cf<CGColorSpaceRef> rgbColorSpace(CGColorSpaceCreateDeviceRGB());

BYTE result[4] = { 0xff, 0, 0, 0xff };
woc::unique_cf<CGContextRef> context(CGBitmapContextCreate(nullptr, 1, 1, 8, 4, rgbColorSpace.get(), kCGImageAlphaPremultipliedFirst));

EXPECT_EQ(CGBitmapContextGetBitsPerComponent(context.get()), 8);
EXPECT_EQ(CGBitmapContextGetBitsPerPixel(context.get()), 32);
EXPECT_EQ(CGBitmapContextGetWidth(context.get()), 1);
EXPECT_EQ(CGBitmapContextGetHeight(context.get()), 1);

EXPECT_EQ(CGBitmapContextGetBytesPerRow(context.get()), 4);
EXPECT_NE(CGBitmapContextGetData(context.get()), nullptr);

// Draw a rectangle into it.
CGRect rectangle = CGRectMake(0, 0, 2, 2);
CGContextSetRGBFillColor(context.get(), 1.0, 0.0, 0.0, 1.0);
CGContextSetRGBStrokeColor(context.get(), 1.0, 0.0, 0.0, 1.0);
CGContextFillRect(context.get(), rectangle);

// verify the rect was drawn
BYTE* data = static_cast<BYTE*>(CGBitmapContextGetData(context.get()));
ASSERT_NE(data, nullptr);

_expectArrayValues(result, data, 4);

// Create the image out of the bitmap context
woc::unique_cf<CGImageRef> image(CGBitmapContextCreateImage(context.get()));
ASSERT_NE(image, nullptr);

NSData* dataProvider = static_cast<NSData*>(CGImageGetDataProvider(image.get()));

This comment has been minimized.

Copy link
@DHowett-MSFT

DHowett-MSFT Nov 15, 2016

I'm not certain this is valid on the reference platform, but maybe? Let's check!

This comment has been minimized.

Copy link
@msft-Jeyaram

msft-Jeyaram Nov 15, 2016

Author Contributor

Ditto. this is due to our weird implementation of the dataprovider.
updated.

ASSERT_NE(dataProvider, nullptr);

NSData* ref = [[NSData dataWithBytesNoCopy:result length:4 freeWhenDone:NO] autorelease];
ASSERT_OBJCEQ(dataProvider, ref);
}

0 comments on commit 46d8097

Please sign in to comment.