Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor CoreGraphics to use IWIC/D2D #1332

Merged

Conversation

msft-Jeyaram
Copy link
Contributor

@msft-Jeyaram msft-Jeyaram commented Nov 8, 2016

This change is Reviewable

@msft-Jeyaram
Copy link
Contributor Author

My Clang went mad again... Ignore the clang formats. They will be corrected.


#import <memory>

class IDisplayTextureImpl : public IDisplayTexture {
Copy link
Contributor Author

@msft-Jeyaram msft-Jeyaram Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class will go away, when we get Jared's changes. #ByDesign

Copy link
Contributor

@rajsesh rajsesh Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for unblocking us in the interim. #ByDesign

virtual void RetainDisplayTexture(DisplayTexture* tex) = 0;
virtual void ReleaseDisplayTexture(DisplayTexture* tex) = 0;
};

Copy link
Contributor Author

@msft-Jeyaram msft-Jeyaram Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will also go away when we get Jared's refactoring work. #ByDesign

context->Impl().deviceTransform = CGAffineTransformMake(1.f, 0.f, 0.f, -1.f, 0.f, targetSize.height);
}

CGContextRef _CGContextCreateWithD2DRenderTarget(ID2D1RenderTarget* renderTarget) {
FAIL_FAST_HR_IF_NULL(E_INVALIDARG, renderTarget);
CGContextRef context = __CGContext::CreateInstance(kCFAllocatorDefault);
__CGContextInitWithRenderTarget(context, renderTarget);

// TODO: RAM: a constructor with the new baseCPP would make life easier here.
Copy link
Contributor Author

@msft-Jeyaram msft-Jeyaram Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/ TODO: RAM: a constructor with the new baseCPP would make life easier here. [](start = 5, length = 76)

will do with merge #Pending

// Today we do not support locking a region of the WIC bitmap for rendering. We only support locking the complete bitmap. This will
// TODO #1124: Today we do not support locking a region of the WIC bitmap for rendering. We only support locking the complete bitmap.
// This
// will
Copy link
Contributor Author

@msft-Jeyaram msft-Jeyaram Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixing this and all the other crazy clang gone wild issues. #Resolved

@msft-Jeyaram msft-Jeyaram changed the title Full Implementation using IWICImage and D2D Refactor to use IWICImage and D2D and removal of the old image pattern. Nov 8, 2016

return S_OK;
});
HRESULT hr = __CGContextRenderToCommandList(context,
Copy link
Contributor

@rajsesh rajsesh Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what is happening in several of these lines, is it just a clang format change? #Pending

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is Clang :(


In reply to: 86919144 [](ancestors = 86919144)

@@ -376,6 +369,54 @@ CGImageRef CGImageCreateWithMaskingColors(CGImageRef image, const CGFloat* compo

#pragma region WIC_HELPERS

DisplayTexture* _CGImageGetDisplayTexture(CGImageRef image) {
RETURN_NULL_IF(!image);
CGIWICBitmap* iwicImg = dynamic_cast<CGIWICBitmap*>(image->ImageSource().Get());
Copy link
Contributor

@rajsesh rajsesh Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why dymanic_cast<> here? Are these cases where we will have other type of image sources? If not, static_cast<> would suffice. #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but given it's a COM object. I've updated how this gets resolved.


In reply to: 86919393 [](ancestors = 86919393)

Copy link
Contributor

@aballway aballway Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be keeping these all within ComPtr rather than mucking around with raw pointers #ByDesign

}
return nil;
WSSInMemoryRandomAccessStream* stream = [[WSSInMemoryRandomAccessStream make] autorelease];
[UIPasteboard _populateStream:stream withData:[data bytes] withLength:[data length]];
Copy link
Contributor

@rajsesh rajsesh Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is pasteboard working after your change? We talked about it offline - if it is broken, lets open an issue. #Resolved

: m_texture(texture), m_pixelFormat(pixelFormat), m_locked_rect(region) {
int bpr;
m_dataBuffer = static_cast<BYTE*>(m_texture->Lock(&bpr));
m_bytesPerRow = static_cast<size_t>(bpr);
Copy link
Contributor

@rajsesh rajsesh Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would simply call it stride, as that is the terminology used elsewhere. #ByDesign

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With in CG it's mostly bpr.
I'll leave it as is for now.


In reply to: 86919975 [](ancestors = 86919975)

}

~CGIWICBitmapLock() {
m_imageBacking->ReleaseImageData();
m_imageBacking = nullptr;
m_texture->Unlock();
Copy link
Contributor

@rajsesh rajsesh Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set it to NULL to help catch potential double frees. #Resolved

}

~CGIWICBitmap() {
if (m_texture) {
Copy link
Contributor

@rajsesh rajsesh Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can delete null, so replace with delete m_texture; m_texture=nullptr; #Resolved

@@ -252,6 +184,17 @@ struct __CGImage : CoreFoundation::CppBase<__CGImage, __CGImageImpl> {
return _impl.bitmapImageSource;
}

inline void* Data() const {
Microsoft::WRL::ComPtr<IWICBitmapLock> lock;
IWICBitmap* bitmap = dynamic_cast<IWICBitmap*>(_impl.bitmapImageSource.Get());
Copy link
Contributor

@rajsesh rajsesh Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static_cast<> #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as before, i'll update.


In reply to: 86920203 [](ancestors = 86920203)


#import <memory>

class IDisplayTextureImpl : public IDisplayTexture {
Copy link
Contributor

@rajsesh rajsesh Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for unblocking us in the interim. #ByDesign

@msft-Jeyaram
Copy link
Contributor Author

msft-Jeyaram commented Nov 8, 2016

struct __CGImageImpl {

we can now move this into the CGImage.mm file. Yay :) #Pending


Refers to: Frameworks/include/CGImageInternal.h:92 in 20bf8cb. [](commit_id = 20bf8cb, deletion_comment = False)

CGContextRef ret = _CGBitmapContextCreateWithTexture(width, height, scale, tex, &_globallockingBufferInterface);
IDisplayTextureImpl* displayTexture = new IDisplayTextureImpl(tex);
CGImageRef texture =
_CGImageCreateCustomWICImage(displayTexture, GUID_WICPixelFormat32bppPBGRA, height, width); // +1 is taken care by CGContext
Copy link
Contributor Author

@msft-Jeyaram msft-Jeyaram Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GUID_WICPixelFormat32bppPBGRA [](start = 57, length = 29)

Added a comment to indicate this needs to be GUID_WICPixelFormat32bppPBGRA

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worried about this; should it definitely be BGRA and not RGBA?


In reply to: 87028254 [](ancestors = 87028254)

#pragma region CGBitmapContext
struct __CGBitmapContextImpl {
woc::unique_cf<CGImageRef> image;
};

struct __CGBitmapContext : CoreFoundation::CppBase<__CGBitmapContext, __CGBitmapContextImpl, __CGContext> {};
struct __CGBitmapContext : CoreFoundation::CppBase<__CGBitmapContext, __CGBitmapContextImpl, __CGContext> {
inline ComPtr<ID2D1RenderTarget>& RenderTarget() {
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inline ComPtr& RenderTarget() { [](start = 2, length = 52)

We can't do this, unfortunately. It's not virtual, so callers who think they're calling CGContext::RenderTarget will be statically compiled to refer to it (and it may be inlined.)

I think this logic belongs in CGBitmapContextCreate, or a helper, which will allow us to back out this change, and the other SetRenderTarget change. #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talked offline. Moving the creation into Quartz


In reply to: 87046467 [](ancestors = 87046467)

ComPtr<ID2D1RenderTarget> renderTarget;
ComPtr<ID2D1Factory> factory = _GetD2DFactoryInstance();
IWICBitmap* bitmap = dynamic_cast<IWICBitmap*>(_impl.image->ImageSource().Get());
THROW_IF_FAILED(factory->CreateWicBitmapRenderTarget(bitmap, D2D1::RenderTargetProperties(), &renderTarget));
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer not to know about Image's internal methods; look at CGPath with its _CGPathGetGeometry(...) #Resolved

ComPtr<ID2D1RenderTarget> renderTarget;
ComPtr<ID2D1Factory> factory = _GetD2DFactoryInstance();
IWICBitmap* bitmap = dynamic_cast<IWICBitmap*>(_impl.image->ImageSource().Get());
THROW_IF_FAILED(factory->CreateWicBitmapRenderTarget(bitmap, D2D1::RenderTargetProperties(), &renderTarget));
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

THROW_IF_FAILED [](start = 12, length = 15)

No throw here; FAIL_FAST is more appropriate #Resolved

@@ -27,6 +27,8 @@
#import <CoreGraphics/CGGradient.h>
#import "CGColorSpaceInternal.h"
#import "CGContextInternal.h"
#import "D2DWrapper.h"
#import "CACompositor.h"
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CACompositor [](start = 9, length = 12)

Unnecessary include? #Resolved

ComPtr<ID2D1RenderTarget> renderTarget = newImage->Backing()->GetRenderTarget();
renderTarget->SetDpi(96 * scale, 96 * scale);

CGContextRef _CGBitmapContextCreateWithTexture(CGImageRef texture, float scale) {
__CGBitmapContext* context = __CGBitmapContext::CreateInstance(kCFAllocatorDefault);
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even cooler: QuartzCore can do this itself, and call _CGContextCreateWithD2DRenderTarget :) #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given QuartzCore expects a BitMapContext, we still need the image.
But the rendering target it moved to QuartzCore and passed here.


In reply to: 87046864 [](ancestors = 87046864)

}

// Return the data pointer to the Image data.
void* _CGImageObtainImageBytes(CGImageRef image) {
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_CGImageObtainImageBytes [](start = 6, length = 24)

_CGImageObtainImageBytes [](start = 6, length = 24)

nit: Maybe _CGImageGetRawBytes() #Closed

return image->Data();
}

CGImageRef _CGImageCreateCustomWICImage(IDisplayTexture* texture, WICPixelFormatGUID pixelFormat, UINT height, UINT width) {
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_CGImageCreateCustomWICImage [](start = 11, length = 28)

_CGImageCreateCustomWICImage [](start = 11, length = 28)

If QuartzCore is the only one who knows about this, it might be good to move CGIWICBitmap into QuartzCore and provide _CGImageCreateWithWICBitmap

That'll expose a similar API to Context, _CGContextCreateWithD2DRenderTarget #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I thought of self containing it here given it's a derivation of IWICImage., but can move it.


In reply to: 87048740 [](ancestors = 87048740)

return imageRef;
}

CGImageRef _CGImageConvertImageToPixelFormat(CGImageRef image, WICPixelFormatGUID pixelFormat) {
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_CGImageConvertImageToPixelFormat [](start = 11, length = 33)

_CGImageConvertImageToPixelFormat [](start = 11, length = 33)

nit: Rework this name so it has Create in it; Create says "I am returning a new +1 object" #Closed

}

return ret;
return nil;
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nil [](start = 11, length = 3)

nit: nullptr #Resolved

if (__CGContext::RenderTarget() == nullptr) {
ComPtr<ID2D1RenderTarget> renderTarget;
ComPtr<ID2D1Factory> factory = _GetD2DFactoryInstance();
IWICBitmap* bitmap = dynamic_cast<IWICBitmap*>(_impl.image->ImageSource().Get());
Copy link
Contributor

@aballway aballway Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be done all within ComPtr #WontFix

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going away now. And eventually No, we'll be crossing DLL boundaries.


In reply to: 87041192 [](ancestors = 87041192)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, we can cross dll boundaries with ComPtr - what issues do you see there?


In reply to: 87051815 [](ancestors = 87051815,87041192)

struct __CGBitmapContext : CoreFoundation::CppBase<__CGBitmapContext, __CGBitmapContextImpl, __CGContext> {
inline ComPtr<ID2D1RenderTarget>& RenderTarget() {
if (__CGContext::RenderTarget() == nullptr) {
ComPtr<ID2D1RenderTarget> renderTarget;
Copy link
Contributor

@aballway aballway Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: move this closer to use #Resolved

__CGBitmapContext* context = __CGBitmapContext::CreateInstance(kCFAllocatorDefault);
__CGContextInitWithRenderTarget(context, renderTarget.Get());
context->Impl().image.reset(texture); // Consumes +1 reference.
context->RenderTarget()->SetDpi(96 * scale, 96 * scale);
Copy link
Contributor

@aballway aballway Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: pull 96 out into a constant #Resolved

@@ -376,6 +369,54 @@ CGImageRef CGImageCreateWithMaskingColors(CGImageRef image, const CGFloat* compo

#pragma region WIC_HELPERS

DisplayTexture* _CGImageGetDisplayTexture(CGImageRef image) {
RETURN_NULL_IF(!image);
CGIWICBitmap* iwicImg = dynamic_cast<CGIWICBitmap*>(image->ImageSource().Get());
Copy link
Contributor

@aballway aballway Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be keeping these all within ComPtr rather than mucking around with raw pointers #ByDesign

return image->Data();
}

CGImageRef _CGImageCreateCustomWICImage(IDisplayTexture* texture, WICPixelFormatGUID pixelFormat, UINT height, UINT width) {
Copy link
Contributor

@aballway aballway Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: no shouty types #WontFix

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given IWICimage takes in UNIT, nope.


In reply to: 87049503 [](ancestors = 87049503)

return imageRef;
}

CGImageRef _CGImageConvertImageToPixelFormat(CGImageRef image, WICPixelFormatGUID pixelFormat) {
Copy link
Contributor

@aballway aballway Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: change to CreateImageWithPixelFormat to make clear it returns a +1. #Closed

CGImageRef _CGImageConvertImageToPixelFormat(CGImageRef image, WICPixelFormatGUID pixelFormat) {
RETURN_NULL_IF(!image);
if (IsEqualGUID(image->PixelFormat(), pixelFormat)) {
CGImageRetain(image);
Copy link
Contributor

@aballway aballway Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are images immutable? #ByDesign

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on the context. They can be mutable or immutable.
If you access the pixels via a lock, yes they can be mutable. Given this is off the code of CALayer processing, it's expected this way.


In reply to: 87049935 [](ancestors = 87049935)

tex = GetCACompositor()->CreateWritableBitmapTexture32(width, height);
}
DisplayTexture* tex = GetCACompositor()->CreateWritableBitmapTexture32(width, height);
if (!tex) {
Copy link
Contributor

@aballway aballway Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: use macro here #Resolved


CGContextRef ret = _CGBitmapContextCreateWithTexture(width, height, scale, tex, &_globallockingBufferInterface);
IDisplayTextureImpl* displayTexture = new IDisplayTextureImpl(tex);
Copy link
Contributor

@aballway aballway Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrap this in ComPtr/other static thing? #WontFix

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given it's being sent across dll boundaries, rather not


In reply to: 87050706 [](ancestors = 87050706)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also it's not a COM object.


In reply to: 87056633 [](ancestors = 87056633,87050706)

@msft-Jeyaram msft-Jeyaram force-pushed the 02_10_CGBitMapContextAndOrder branch from 8ca8abc to ac3fe1b Compare November 8, 2016 22:19

CGContextRef _CGBitmapContextCreateWithRenderTarget(ID2D1RenderTarget* renderTarget, CGImageRef img) {
RETURN_NULL_IF(!renderTarget);
//TODO: do it for image?
Copy link
Contributor Author

@msft-Jeyaram msft-Jeyaram Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

//TODO: do it for image? [](start = 3, length = 25)

Taken care of #Resolved


context->Impl().image.reset(newImage); // Consumes +1 reference.
__CGContextInitWithRenderTarget(context, renderTarget);
context->SetImage(img);// Consumes +1 reference.
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, we want to CGImageRetain the image they pass us. Do that in SetImage #Resolved

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and then remove the comment here.


In reply to: 87101477 [](ancestors = 87101477)

@@ -211,8 +216,7 @@ CFTypeID CGContextGetTypeID() {

#pragma region Global State - Lifetime
static void __CGContextInitWithRenderTarget(CGContextRef context, ID2D1RenderTarget* renderTarget) {
context->_impl.renderTarget = renderTarget;

context->SetRenderTarget(renderTarget);
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

context->SetRenderTarget(renderTarget); [](start = 4, length = 39)

I still don't think this should be here; let's back out SetRenderTarget and we can land it with a full constructor once develop merges in.

What say you? #Resolved

@@ -28,6 +28,7 @@
#import "CGColorSpaceInternal.h"
#import "CGContextInternal.h"
#import "CGPathInternal.h"
#import <CoreGraphics/D2DWrapper.h>
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<CoreGraphics/D2DWrapper.h> [](start = 8, length = 27)

Private header; consider using "s #ByDesign

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given it's not in the same directory as this file.
use <> as per windows documentation.


In reply to: 87101659 [](ancestors = 87101659)

return imageRef;
}

CGImageRef _CGImageCreateWithPixelFormat(CGImageRef image, WICPixelFormatGUID pixelFormat) {
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_CGImageCreateWithPixelFormat [](start = 11, length = 29)

nit: CreateCopyWithPixelFormat :) #Resolved

RETURN_NULL_IF_FAILED(imageFactory->CreateBitmapFromSource(converter.Get(), WICBitmapCacheOnDemand, &convertedImage));

CGImageRef imageRef = __CGImage::CreateInstance();
imageRef->SetImageSource(convertedImage);
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can replace this with a call to _CGImageCreateWithWICBitmap() #WontFix

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uh I'd rather not increase it by one more call.
This should be fixed when we go constructor based (as well as other places).


In reply to: 87101870 [](ancestors = 87101870)

DisplayTexture* _CGImageGetDisplayTexture(CGImageRef image) {
RETURN_NULL_IF(!image);
CGIWICBitmap* iwicImg = dynamic_cast<CGIWICBitmap*>(image->ImageSource().Get());
RETURN_NULL_IF(!iwicImg);
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this dynamic_cast definitely work for COM things? #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to queryinterface with ID. implementing it.


In reply to: 87101932 [](ancestors = 87101932)

@@ -28,83 +28,15 @@
#import <windows.h>
#import <CGColorSpaceInternal.h>
#import <utility>
#import "CACompositor.h"

Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file can't include CACompositor; quartz links CG #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although it works fine, this was mainly to resolve issues with the IDisplayTexture definition Jared has.
I can see to move it out.


In reply to: 87102053 [](ancestors = 87102053)

// Obtain a direct pointer to the data.
COREGRAPHICS_EXPORT void* _CGImageGetRawBytes(CGImageRef image);

// Obtain the associated DisplayTexture, return null for images that lacks them.
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lacks [](start = 69, length = 5)

nit: lack #Resolved

#import "CGDiscardableImage.h"
#import "CGPNGDecoderImage.h"
#import "CGJPEGDecoderImage.h"
// Create a Custom IWIC Image out of the given texture.
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

texture [](start = 47, length = 7)

nit: comment slightly wrong #Resolved


CGContextRef ret = _CGBitmapContextCreateWithTexture(width, height, scale, tex, &_globallockingBufferInterface);
Microsoft::WRL::ComPtr<IWICBitmap> bitmap = Microsoft::WRL::Make<CGIWICBitmap>(displayTexture.get(), GUID_WICPixelFormat32bppPBGRA, height, width);
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[](start = 1, length = 1)

tabs! #Resolved

#import <memory>

//TODO #1337 - Remove this when Compositor refactoring is complete and ready.
class IDisplayTextureImpl : public IDisplayTexture {
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDisplayTextureImpl [](start = 6, length = 19)

I guess the naming convention for an Impl of an I is CThing #WontFix

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(That is, IThing -> CThing)


In reply to: 87102644 [](ancestors = 87102644)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something that's going away, the reason the naming is so weird is that, first it stands out.
Second there is already DisplayTexture defined.


In reply to: 87102669 [](ancestors = 87102669,87102644)

renderTarget->SetDpi(kWindowsDPI * scale, kWindowsDPI * scale);

displayTexture.release();
return _CGBitmapContextCreateWithRenderTarget(renderTarget.Get(),texture);
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

),t [](start = 71, length = 3)

format this! #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formatter fail.


In reply to: 87102772 [](ancestors = 87102772)

renderTarget->SetDpi(kWindowsDPI * scale, kWindowsDPI * scale);

displayTexture.release();
return _CGBitmapContextCreateWithRenderTarget(renderTarget.Get(),texture);
Copy link

@DHowett-MSFT DHowett-MSFT Nov 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

texture [](start = 73, length = 7)

I don't think texture exists in this scope. #Resolved

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore me, it does.

The names are a little confusing; can you clear them up a bit?


In reply to: 87102962 [](ancestors = 87102962)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going with "image" ?


In reply to: 87103132 [](ancestors = 87103132,87102962)

@@ -28,6 +28,7 @@
#import "CGColorSpaceInternal.h"
#import "CGContextInternal.h"
#import "CGPathInternal.h"
#import <CoreGraphics/D2DWrapper.h>

Copy link
Member

@MSFTFox MSFTFox Nov 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this is unused here. #Resolved

@DHowett-MSFT
Copy link

:shipit:

@msft-Jeyaram msft-Jeyaram changed the title Refactor to use IWICImage and D2D and removal of the old image pattern. Refactor to use CoreGraphics to use IWIC/D2D backing Nov 9, 2016
@msft-Jeyaram msft-Jeyaram changed the title Refactor to use CoreGraphics to use IWIC/D2D backing Refactor CoreGraphics to use IWIC/D2D backing Nov 9, 2016
@msft-Jeyaram msft-Jeyaram changed the title Refactor CoreGraphics to use IWIC/D2D backing Refactor CoreGraphics to use IWIC/D2D Nov 9, 2016
@MSFTFox
Copy link
Member

MSFTFox commented Nov 9, 2016

:shipit:

@DHowett-MSFT
Copy link

Adding @jaredhms.

@jaredhms
Copy link
Contributor

jaredhms commented Nov 9, 2016

@yiyang-msft is added to the review. #Closed

static const wchar_t* TAG = L"CALayer";

static const bool DEBUG_ALL = false;
static const bool DEBUG_VERBOSE = DEBUG_ALL || false;

static const int kWindowsDPI = 96;
Copy link
Contributor

@jaredhms jaredhms Nov 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kWindowsDPI [](start = 17, length = 11)

nit: should be c_windowsDPI, although why are we assuming 96 here? #Resolved


Microsoft::WRL::ComPtr<ID2D1RenderTarget> renderTarget;
RETURN_NULL_IF_FAILED(factory->CreateWicBitmapRenderTarget(customWICBtmap.Get(), D2D1::RenderTargetProperties(), &renderTarget));
renderTarget->SetDpi(kWindowsDPI * scale, kWindowsDPI * scale);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kWindowsDPI [](start = 29, length = 11)

looks like we should query the system for the current DPI?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default DPI for bitmap render targets is 96; scale is handled at a fundamentally different level here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if that's the case, can we please heavily comment as such, and also point to where we do handle DPI?


In reply to: 87294346 [](ancestors = 87294346)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can also pull c_windowsDPI down here where it's used since it's not used anywhere else.


In reply to: 87295048 [](ancestors = 87295048,87294346)

@@ -1420,8 +1445,8 @@ - (void)setContents:(id)pImg {
CGImageRetain(static_cast<CGImageRef>(pImg));
priv->ownsContents = FALSE;

priv->contentsSize.width = float(priv->contents->Backing()->Width());
priv->contentsSize.height = float(priv->contents->Backing()->Height());
priv->contentsSize.width = float(CGImageGetWidth(priv->contents));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

float( [](start = 35, length = 6)

nit: do we actually need to construct a float here?

break;
}
// TODO #1338 - Support via encoded data from IWIC
woc::unique_cf<CGImageRef> imgRef(_CGImageCreateCopyWithPixelFormat(img, GUID_WICPixelFormat32bppPBGRA));
Copy link
Contributor

@jaredhms jaredhms Nov 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+Yi, as he may be interested in this. #Resolved


// Return the data pointer to the Image data.
void* _CGImageGetRawBytes(CGImageRef image) {
RETURN_NULL_IF(!image);
Copy link
Contributor

@jaredhms jaredhms Nov 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you expect to be passed null in any of these methods? if not, we should remove the null checks and get a much easier to debug AV. #Resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be null at some point.
e.g if the context didn't having a backing image, etc.


In reply to: 87296908 [](ancestors = 87296908)


IDisplayTexture* displayTexture;
RETURN_NULL_IF_FAILED(displayTextureAccess->DisplayTexture(&displayTexture));
RETURN_NULL_IF(!displayTexture);
Copy link
Contributor

@jaredhms jaredhms Nov 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the above call succeeds, we shouldn't need to also check for null #Resolved

@@ -281,47 +281,13 @@ + (WSSInMemoryRandomAccessStream*)_populateStream:(WSSInMemoryRandomAccessStream
+ (WSSInMemoryRandomAccessStream*)_grabStreamFromUIImage:(UIImage*)image {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_grabStreamFromUIImage [](start = 34, length = 22)

in WocCatalog, the last test is copy and Paste. please run through that to make sure image copy & paste is still working.

@@ -281,47 +281,13 @@ + (WSSInMemoryRandomAccessStream*)_populateStream:(WSSInMemoryRandomAccessStream
+ (WSSInMemoryRandomAccessStream*)_grabStreamFromUIImage:(UIImage*)image {
Copy link
Contributor

@yiyang-msft yiyang-msft Nov 10, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_grabStreamFromUIImage [](start = 34, length = 22)

i can not find my early comment. Please test this with WoCatalog copy and paste scenario to make sure image copy and paste is still working. Thx #Resolved

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CF is behaving strangely. now i saw earlier comment. close this one.


In reply to: 87309387 [](ancestors = 87309387)

@msft-Jeyaram msft-Jeyaram force-pushed the 02_10_CGBitMapContextAndOrder branch from 61ef1cf to cae3309 Compare November 10, 2016 17:08
@msft-Jeyaram msft-Jeyaram merged commit 6d4e9d0 into microsoft:CGD2D Nov 10, 2016
rajsesh pushed a commit that referenced this pull request Feb 17, 2017
* D2DFactory Wrapper (#1085)

* D2DFactory Wrapper

* Fix path for wrapper includes in project file.

* Moving starboard to mm file.

* Address CR feedback, remove useless code, clean up D2D factories.

* Moving header file to private location

* Factory helper should only create single threaded D2D factories.

* Actually fix the wrapper header location.

* Add the CG/D2D design document. (#1112)

* Implement an ID2D1RenderTarget-backed CGContext (#1126)

There are wide swaths of code wrapped in #if 0 ... #endif blocks; they will be removed and repaired as part of the ongoing work on this branch.

Issues have been logged for many TODOs, but the rest will be removed as part of the ongoing work on this branch.

Currently broken:

* path rendering
*  shadow
* transparency layers
* bitmap contexts that are not CALayer contexts
* font rendering is left in CGContextCairo.mm and will be moved

This merge is intended to unblock parallel work on CG/Direct2D.

* Add CFCppBase, a helper class for implementing C++ CF types.

* Switch CGContext/CGBitmapContext over to CppBase.

*  Initial implementation of CGPath Using ID2D1Geometries (#1138)

*  Initial implementation of CGPath Using ID2D1Geometries

 This work provides the foundation for creating a CGPath based on
 ID2D1PathGeometry and GeometrySink. A simple implementation for
 adding a simple line, moving the current location to a new point
 and retrieving some basic information from the Geometry sink has
 been added. Isolated unit tests have also been added to ensure
 these APIs are working as intended for these simple scenarios.

* Addressing CR Feedback.

* Reworking the __CGPath struct to use a nested implementation

Also addressed some concerns with the state of geometry objects.

* Fixing re-opening functionality by creating a new path and streaming contents of old path into it.

* Addressing CR Feedback.

* Cleaning up CGPath and removing unused code.

* Refactor into using CFCppBase

* Cleaning up a few things.

* Addressing CR Feedback.

Removing fully qualified names. Using inline helpers
between D2D and CG. Fixing CGPathAddLines which will be
tested more accurately in the future. Removing unnecessary
dealloc method for CGPath base type. Fixing include->import.

*  Addming more helper functions and reverting bad test change.

* Addressing CR Feedback. Fixing Inlines

* Disabling tests that rely on CGPath in CoreText

* CGContext DPI, parameter, stroking & interpolation improvements (#1181)

* Make CGContext display scale-agnostic by propagating the scale into Direct2D's DPI.
  A CGContext rendering to a scaled surface will not apply a scale
  transformation. The scaling logic has been moved into render target
  creation.
  
  Fixes #1180.
* Replace __CGContextDrawGeometry with RenderToCommandList+RenderCommandList.
* Push CG Interpolation mode into Direct2D.
  References #1177.
* Make all CG APIs nullptr-safe.
* Move stroke style caching/computation into drawing state.
* Fix CGContextConcatCTM (math was backwards.)

* Perform major surgery on CGContext.

* Fix improper use of internal functions in CGPath. (#1249)

* Fix calculating exclusion zones based on CGPaths.

* Implementation of CGImage using Windows Imaging Component. (#1185)

- Implementation of CGImage via WIC
- Remove circular dependencies between CGImage and UIImage
- Implement UIImage interms of CGImage
- Fix issues in UIImage
- Increase code quality in UIImage
- Remove libpng depencie of CGImage
- Improvements to result.h Macros for conditional checks
- Improve code quality for existing image interaction
- Added unit tests

* Add support for black and coloured shadows via ID2D1Effect. (#1239)

* Add support for black and coloured shadows via ID2D1Effect. Closes #1237.
* Apply the CTM transform for commandlist, device transform for final draw.
  Shadows project completely ignoring the context flip and any user translation.
  Therefore, we must translate all our drawing commands when we create
  them, but only apply the device scale in the final composition step.
* Implement CGSizeApplyAffineTransform.
* Allow a private consumer to control the shadow projection params.
* Switch all internal interfaces to HR returns.

* Implement the CGContext non-drawing path functions in terms of CGPath. (#1240)

Curiously, CGContext path queries and CopyPath return untransformed units.
Closes #1238.

* Finish Simple line and status CGPath APIs. (#1255)

* Finish Simple line and status CGPath APIs.

Add additional tests to cover these scenarios.

* Addressing CR Feedback. Releasing leaked paths in tests.

* Addressing CR Feedback. Cleaning up nested conditionals and macro usage.

* Addressing CR Feedback.

* Removing unnecessary internal helper function. Adding extra test case for equality of paths with sub shapes.

* Fixing access to internal members of implemtation for CGPath.

* Rework __CGPath as per new encapsulation procedures.

* Adding additional test case for possible sub shapes equality failure.

* Implement drawing CGPaths through CGContext (#1307)

* Implement drawing CGPaths through CGContext

* Fix calls to return an HRESULT.

* Address CR Feedback.

* Fix poor comptr usage and leaks. Return to static initializer model.

* Refine CGContext's user<->device coordinate space boundary (#1324)

CGContext will now strive, wherever possible, to store its internal state in fully-device-transformed units. This transformation includes the device scale (flip+translate from CG to D2D) and the user scale.

To enable this, this pull request also adds the ability to specify that coordinate system a drawn geometry is in: paths will use the premultiplied values, and user-space geometry values will use userspace->device transformation.

This allows us to leverage the Direct2D effect stack without having to apply input and output transformations to the effects, and simplifies shadow rendering (we no longer transform for userspace in the commandlist and then device space when we draw it.)

* Refactor  CoreGraphics to use IWIC/D2D  (#1332)

- Full Implementation of CoreGraphics via IWIC/D2D
- Refactor CoreGraphics

#1299
#1227
#1246
#1292
#1345

* Update CGContext, CGPath and sorta CGImage for the CFCppBase changes. (#1356)

* Disable CTFont.CreatePathForGlyph

* Adapting the WIC factory creator to follow the outlined format in D2DWrapper (#1357)

* Propagate context alpha into brushes for per-primitive draw, not layer

* Add support for clipping (and EO clipping); add support for non-EO fill. (#1368)

* Properly EO- or Winding-fill Geometries.
* Add support for CGContext(EO)?Clip().

Fixes #1269.

* Add CoreGraphics.Drawing UT and a bunch of image rendering tests.

This change set introduces DRAW_TEST and DRAW_TEST_F, as well as a handful of
image drawing test fixtures. Commands rendered to a test's context as part of
its test body will be rasterized and saved in a file named
TestImage.$TESTCASE.$TESTNAME.png

The test driver's ideal interface is multi-modal; it needs to be able to
generate a corpus of reference images on disk, and it needs to be able to diff
them. For this, it needs a custom EntryPoint (included), and the ability to
parse command-line arguments.

The ideal default mode will be one that loads reference images from disk and
fails tests if a number of pixels differ. That work is not yet complete.

Hopefully, the draw tests here will be able to be plugged into another module
that can perhaps render them to screen, or display them as part of a UI-driven
flow for comparison and demoing purposes.

Refs #1271.

* Implementation of CGBitmapContext. (#1371)

Added custom iwic bitmap to support copying, and backed data buffer.
Added colour conversion format check for pixel formats.
Added tests to draw, render and validate changes.
CGImage changed to use OnLoad caching.

* Changing IWIC image loading to on Load rather than on demand. (#1413)

* Simplify geometry casting. (#1428)

* Disable every drawing test manually instead of using exit(0). (#1434)

* Cleaning up internal headers and moving CGImage implementation to source file (#1430)

* Implementation of drawing an Image into context (#1414)

Implement UIKit image drawing via WIC/D2D #1245 
Added unit and semi functional tests for drawing into context and scaling.

* Clean up internal headers; delete CGContextImpl.

* Clean up CoreGraphics' public headers.

This moves most of the types out of CoreGraphicsExport.

* Automatically generate greenline images for tests and provide for test failure. (#1438)

CoreGraphics.Drawing.UnitTests can now be invoked in one of two modes, mediated by command line flags:

* `--compare[=/path/to/reference/folder]` (_default mode_) compare all rendered images against their baselines, failing the test if any images differ by even a single pixel.
* `--generate [--out=/path/to/output/directory]` generate output images only (do not run comparisons.)

A failing test will emit a brightly-colored diff image to `Greenlines.TestImage.CASE.TEST.png` in the _output directory_, and attach attributes to the gtest output XML data specifying where to find the images. A compatible test runner can load these images and display them side-by-side.

**Open Questions/Concerns**
* I do not like the design of `rgba/bgraPixels`.
* I do not take stride into account; if the image is width-padded, the tests will ikely fail.
* The reference platform loads images in RGBA, and we load them in BGRA. This is not an incompatibility, but it does make manual buffer manipulation dicey.
  * The fix here is to render the image into a NEW context, but that presents a few issues of its own:
    * We must trust our DrawImage function
    * We must further validate bitmap context, and trust our bitmap context as an integral part of test execution.
* All tests will be disabled as of the merge of #1434. We can re-enable them and reintroduce reference images after build validation.

Closes #1271.

* remove export of internal function (#1458)

* Fix internal and Objective-C use in CoreGraphics.DrawingTests.

Fixed #1448.

* Use CopyTo(p) instead of *p=Get(). Fixes #1453.

* In CGImageDestination, never pair a Get with a Release.

* *DO NOT* rely on the value of uninitialized memory.

* zero out memory for backing buffer

* Implement Arcs using D2D (#1384)

* Implement arcs and curves in CGPath using D2D

* Implement transformations in terms of D2D simplify.

* Update curves, test app with Transformation options.

* Fixing UI and other things.

* Adding comments on arc math and updating cpputils

* Use CGAffineTransform equality function instead of defining our own.

* Fix const getter functions, reorder out pointer arguments

* Fix failing coordinate tests due to stomped equality operator.

* Re-Integration from develop->CGD2D

- Removal of bridged IDisplayTexture #1337
- Getting it to build
- Proper usage of the IDisplayTexture
- Tests validated
- Usage of proper colour format
- Move image files to data folder and change tests to adapt.

* [CGD2D] Add support for Transparency Layers. (#1496)

This changeset introduces support for transparency layers. Transparency layers serve as render targets that are composed down to the backing surface in one fell swoop.

To make way for this, CGContext was mildly refactored:
* Existing private (denoted by `__CGContextX`) methods were moved into `__CGContext` the class as `__CGContext::X`.
* Graphics state manipulation was promoted to `__CGContext`.
* Some methods were promoted to drawing state methods (clipping, draw decision)
* `__CGContextLayer`, a class that tracks a stack of drawing states and their destination buffers, was introduced.
* CGContext's render target setup was moved into its constructor.
* `globalAlpha` was reintroduced, as sometimes per-primitive alpha is just not enough. *Such as: layers are composed down all at once using the alpha set at the time the context was created.*

Deficiencies:
* Clipped layers are implemented in terms of a baseline clipping state applied to the layer. All primitives are drawn through a Direct2D **PushLayer** and **PopLayer** pair.
* Alpha-composited layers are implemented in terms of the same.
* There is some dodgy math witnessed on the reference platform that grows shadowed layers by some combination of shadow offset and width; an attempt was made to mimic this.
* Minor layering violations that pass a `__CGContext` to a `CGContextXxx()` public function by way of **this**.

Fixes #1427, #584.

* Implement CGPathApply (#1507)

* CGPathApply

* Curve Apply Test Page

* Update tests, address CR feedback, move geometry sink to individual file.

* Addressing CR Feedback.

* Fix no-op on cgpathapply when path is null.

* Address CR Feedback

* Single element point arrays are now just a variable

* Ignoring clang warnings on ARM builds for WRL helpers.

* Replace lost ID from last commit.

* Remove bitmap context hack from NSTextContainer

* Fix Affine Transform in CGPath (#1550)

* Affine Transform

* Remove excess com pointer usage from getters.

* Update API status.

* Enable Path Tests + Reference Images

* Disabled AddEllipseInRect test until CGContextSetStrokeColor is supported.

* Add support for copying subregions from CGIWICBitmap.

References #1379.

* Convert CGBitmapContext's image on output (if data isn't provided).

* Convert ImageIO to use CGImage's WIC internals directly.

Additionally, clean up some EXPECT/ASSERT/_MSG in ImageIO Tests.

Fixes #1287.

* Tidy CGImage's list of supported pixel and rendering formats.

Add some more bitmap format tests, and adjust the rest of the tests to
match.

* Fix CoreGraphics.Drawing's image loader & premultiplied alpha.

* The unpremultiplier here matches the algorithm used in WIC.
* A test image has been added that will load unpremultiplied, but render
  premultiplied.

* Add support+tests for clipping context rendering to an image mask. (#1528)

This pull request adds support for clipping rendering into a context by an image or an image mask in terms of Direct2D opacity brushes.

An image mask is a grayscale image whose pixel values range from 0 to 100%, and those values are taken as inverse alpha. That is: a fully black image (px=0.0) will be rendered through at alpha 1.0; a fully white pixel will be at alpha 0.0 and values between the two will be interpolated appropriately.

Masks can be stacked. This is implemented in terms of a double composite operation; the two opacity brushes are combined and used to draw a black region into a new image. The new image will serve as the final bitmap backing the new opacity brush.

Since Direct2D does not support b/w masks natively, an effort was undertaken to translate them into alpha channel masks.

Black/white masks do, unfortunately, not work with CGBitmapContext as-is. We cannot render an image into a 1-component colorspace bitmap. This requires that this pull request be merged after #1529.

Fixes #1421. Provides a base implementation for #1425.

* Add support for CGImageCreateWithMask. (#1555)

Fixes #1425.

* Store CGContext's text position in its text matrix. (#1580)

* Implementation of Tiled Images + tests (#1542)

Implementation of Tiled Images + tests #1417

* Implementation of fill and stroke pattern brushes and tests #1422

* Implementation of set stroke and fill methods #1422
refactor existing code to use common functions.

* Implementation of Linear gradients with full optional support  (#1416)

* Support opacity and interpolation for Drawing Images (#1557)

* Add support for opacity and interpolation for drawing images #1556

* Reintegrate CoreGraphics and Accelerate.framework. (#1680)

Fix some dodgy memory management in Accelerate.

* Fix Accelerate.UnitTests. Fixes #1285.

* Fix (and update) UIGraphicsFunctions. (#1681)

Fixes #1642.

* Do not use UIColor in CoreText!

* Fix CGImage to not copy CGDataProvider. Fix CGDataProvider in vImage.

* CoreImage:Implementation of CIImage using CGImage + test (#1625)

* CoreImage:Implementation of CIImage using CGImage + test

* Proper annotations for implemented methods (#1719)

* Implementation of JPEG & PNG representation and tests

* #1338 Adding support to copy images to/from clipboard

* Add woc::AutoCF<T>. It's like AutoId<T> for CFTypes.

Just like AutoId<T>, it takes a lifetime trait template: CFLifetimeRetain
for CFRetain/CFRelease, and CFLifetimeUnsafe for straight assignment.

It builds upon and replaces woc::unique_cf<T>.
 * It is copyable (and can share ownership)
 * AutoCF<T> can be passed anywhere T* is required.
 * It has a fully-loaded operator& so you can pass it wherever
   a T** is required. The old value will be released.
 * It has counterparts in StrongCF and UnsafeCF, just like StrongId
   and UnsafeId.

By default, a StrongCF will *share ownership* of a CFType.
To transfer ownership, construct it with std::move(cf) or use
woc::MakeStrongCF<T>(CFCreateXxx(...)).

As a migration measure, woc::unique_cf is still provided, though it is
now based on StrongCF. It retains its "transfer ownership on construct"
semantics and provides a few shim methods to adapt it to the
AutoCF/AutoID world (release -> detach, reset -> attach).

(cherry picked from commit a64f482)

* Fix fallout from the merge of #1692.

* Migrate the text drawing code from Cairo to CGD2D.

* Fix the default fill/stroke color values from the reference platform.

* #1733 CGContextClearRect: Support to clear rect if clipping is not set (#1743)

* Fix our WIC<->CG color format table again.

Fixes #1694.

* Work around #1769 by doing the DPI calculation ourselves.

* Fix Figure Creation in CGPath (#1738)

* Fix Figure Creation in CGPath

* Fix private class member naming.

*  Merge with CGD2D

* Check for null geometry on figure end calls

* Plug memory leak in __DWriteTextLayoutApplyFont (#1788)

Fixes #1766

* Fixing ApiAnalyzer errors. (#1794)

* NSTextContainer handle exclusion zones extending outside of area (#1792)

Fixes #1779

* getNetworkConnectivityLevel can throw under some circumstances.  Handle (#1795)

* getNetworkConnectivityLevel can throw under some circumstances.  Handle
these and treat the connection status as 'not connected'.

* Fix leak in NSRunLoop _statesForMode: helper (#1793)

* Fix leak in NSRunLoop _statesForMode: helper

* just use autorelease for helper; remove additional unused method from NSRunLoop (which would double release if called)

* SC callbacks must by default happen on the main thread unless the app (#1801)

specifies a different queue.  This fixes a crash in reachability sample.

* Fix drawing tests on OSX (#1815)

Need to be explicit about stealing the deltaImage when doing a move of our ImageDelta

Fixes #1805

* UX Functional test pattern - exercising sample app's UIViewController within a functional test (#1771)

CHANGES:
1. Created a new XAMLCatalog UIViewController with 2 controls (slider, UITextField) to manipulate a UIButton's label
2. This UIViewController's exposes a public UIButton property that can be manipulated from a functional test (UIButtonTests)
3. Created UX helper class, ViewControllerTestHelper, to display visuals using pushVC/dismissVC
4. Created UX helper class, XamlEventSubscription, to register/unregister XAML property change events
5. Updated FunctionalTest VCXPROJ to move external VCs into its own folder

TODO:
1. Migrate NSCondition to Win32 event mechanism

* CoreText Performance: Call ID2D1RenderTarget::BeginDraw()/EndDraw() f… (#1705)

* CoreText Performance: Call ID2D1RenderTarget::BeginDraw()/EndDraw() fewer times

Fixes #1620

* - Added Begin/EndDraw pairs to a few more places
- Mitigated an issue with cairo where ID2D1RenderTarget would sometimes cache a before state during begin draw,
  and wipe out any changes cairo made, breaking APIs like CGContextFillRect.
- Changed implementation/naming of the 'escape the current begin/end draw stack' functions

(cherry picked from commit d5a86b9)

* Merge #1705 to CGD2D
 - Add PushBeginDraw/PopEndDraw pairs to UISegment, UIImage
   (not on develop since this likely would've actually hurt performance there)
 - Add Escape/Unescape pairs to CGContext areas where the target is changed

Fixes #1635

cr feedback

cr feedback

(cherry picked from commit 0ac5491)

* Remove Cairo and unused dependencies (#1797)

Fixes #1455

* [CGD2D] Render buffer-shared G8 images as A8. (#1804)

This is riddled with caveats, many of which are documented in the code.

A first pass attempt was made to implement a format converter that would run
per-primitive. It's expensive, but it did get the job done.

Unfortunately, asking WIC to convert a PRGBA buffer to a G8 buffer causes it to
discard all alpha data -- even if premultiplied, the luminance of
partially-transparent pixels is not appropriately reduced in the final G8 image.
This impacts alpha-heavy uses such as grayscale font rendering.

The A8 implementation was chosen for maximal compatibiltiy with Cocos2D. Cocos2D
renders white (!) text into a "grayscale" buffer that it then passes off to
OpenGLES as a `GL_ALPHA8` buffer. Hah.

The A8 "hack" also represents what we currently have on the develop branch.

Fixes #1747.

* Use custom font for stable version and copyright (#1799)

Fixes #1798

* Change parameterized test to use custom font (thanks Dustin :D)

* Initialize m_lastPoint; fixes intermittent test failure.

* Porting ObjectiveC language services VSIX to VS2017 (#1745)

* Make sure our touch/point conversion works in middleware (C#-hosted, etc.) scenarios.  Controls that are placed within arbitrary Xaml scenes don't have a superview chain up to a valid UIWindow, so touch point conversion is failing.  The fix is to - in middleware scenarios - use the app's main UIWindow for any UIView that doesn't have a superview. (#1821)

Fixes #1818.

* Fix various Uikit memory leaks (#1803)

* Fixing some UIKit/WinRT projections memory leaks.  Any time we allocate a WinRT projected object via make*, we are responsible for freeing it.

* Fixing leak in Autolayout and its usage of ClSlackVariables.

* Updating libcassowary build output with memory leak fix.

* Incorporating CR feedback.

* Allow _UIPopupViewController to present itself in middleware scenarios. (#1832)

A recent fix/change to UIViewController (75effb9) regressed one of our middleware scenarios. UIViewController now makes sure that one is presenting over a currently-visible ViewController. However, in middleware scenarios, that won't hold true, so we must loosen the check in such cases.

Fixes #1831.

* Fix additional leaks in UIKit (#1789)

* Fix additional leaks in UIKit

* just add autorelease to paragraphStyle helper

* address CR (prefer local StrongId to adding a bare release in UIDatePicker; add ARC enabled assertions). fix additional leaks in UITabBarController.

* ObjC2Winmd: Support for async delegates with multiple parameters (#1833)

* Fix a missed endianness flip in #1748.

Fixes #1837.

* Fix various leaks in Foundation (#1834)

Thanks to @ehren.

* Migrate foundation tests out of woccatalog (#1826)

Moves Foundation Tests, which includes task_info, URL Session, and UserDefaults, and moves them to a new test app Foundation-Dev in tests/testapps

Fixes #1577

* Migrate foundation tests out of woccatalog

* Even more relative path

* Updated GLKitComplex sample project with missing textures. (#1842)

* Add data files to xcodeproject

* Updated glkit project with missing textures.  Fixes #1840.

* Fixing Github issue 1602 and 1689 - sizeThatFits and adjustFontSizeToFitWidth does not work on UILabel

* Revert "Redo locking and ref counting in NSOperationQueue to be much safer. A… (#1676)"

This reverts commit 1db8c66.

* Revert "Fix various leaks in Foundation (#1834)"

This reverts commit 3a65494.

* Fix #1827 by flipping the context *properly* in UIImage draw.

* Reimplement CGContextDrawImage in terms of _CGContextDrawImageRect.

This fixes the heavy drawing overhead on 9patch images, which used to
apply a context-global clip and draw the image in full nine separate
times.

Now we get to use D2D's native image region subsetting support!

* Created UX test helper class and simplified the tests using the new UX pattern (#1855)

* Created UX test helper class and simplified the tests using the new UX pattern

CHANGES:
1. Created UXEvent class, wrapping NSCondition, and UIColor and WUXMSolidBrush comparison method
2. Added more controls to manipulate a UIButton via XAMLCatalog's viewcontroller
3. Applied new UX test pattern to CALayerAppearance tests

Fixes #1764, #1757

* Fix CGPathEqualToPath Implementation (#1813)

* Fix CGPathEqualToPath

* Address naming feedback and coding conventions.

* Address CR Feedback.

* Fix overuse of m_ and provide more proper names for parameters

* Fix islandwood news crash in article view when panning (#1857)

* Some improvements to RETURN_RESULT_* macros (#1862)

* Some improvements to RETURN_RESULT_* macros

* some nit picking

* Use _CGContextPushBegin/PopEndDraw for Drawing Tests (#1870)

* Use _CGContextPushBegin/PopEndDraw for Drawing Tests
 - Since we generally expect real use-cases to use these functions for perf purposes,
   we should also validate that our drawing is correct when using them.
 - Fixed a stray raw ->BeginDraw() ->EndDraw() in CGContext.mm that was missed
   and could cause crashes if used under PushBegin/PopEndDraw

Fixes #1869

* better format a comment

* Adding macros to enchance return and failure checks. (#1871)

* NSURLSession should throw for creating tasks with nil request or resume data (#1860)

Fixes #1844

* Check for nil before trying to resume

* CR feedback

* Fix starting position of arc in bezierPathWithArcCenter (#1864)

* Fixing more UIKit memory leaks (#1863)

* Fixing leak in UIKit.Xaml controls, and a leak in UIButton.

* Adding UIButton memory leak tests.

* Switching to fancy new event helper.

* Add a slight delay after freeing the UIBUtton to prevent a very intermittent test failure (failed twice out of 500 times).

* Switching to StrongId for VC.

* Incorporating CR feedback.

* Fix various leaks in Foundation (#1873)

Fixes leaks in NSLog and internal logging funcs, NSString and NSMutableString leaks,
and an NSTimer leak.

* Remove some dead code from bff7cce.

* If the user provides bitmap data, a bitmap context must copy it out.

* [vImage] Don't hire a bitmap context to do our dirty work.

Converting an arbitrary buffer of bytes into an image should be handled
by CGImage. Using CGBitmapContext and its rather more limited set of
formats is bound to fail more often.

* Fix the Accelerate samples to use 32bpp images & proper byte ordering.

* Fix a missed swap from the format table introduced in 2122f2a.

* Winmd2ObjC update: Fixed inconsistencies with create method and added annotations. (#1883)

* Enable vertical pixel-snapping when drawing glyph runs (#1890)

- Devices with vertical antialiasing would render text as blurry if rendered on a fractional vertical coordinate.
   - CGContext functions that draw glyphs do not necessarily use coordinates from our custom text renderer,
     which already has pixel snapping enabled.
   - As such, manually round the y-translation in CGContext::DrawGlyphRun()
 - Updated reference images for two drawing tests dealing with line height.

 Fixes #1594

* Remove EbrCenterTextInRectVertically (#1882)

Changes UITabBarButton to directly center text vertically in drawRect:
Removes dead code from UITextView-sizeThatFits:

Fixes #1812

* Change targets less in CGContext (#1878)

* Change targets less in CGContext
 - CGContext previously changed targets for all draw primitive functions.
   Since changing targets causes an immediate flush, this significantly negatively impacted performance.
   Changed implementation to only change targets when needed (when shadows are enabled)
 - Added drawing tests for a few edge cases regarding shadows and clipping.
 - Removed unnecessary Escape/Unescape functions - these were not necessary to change targets as previously surmised.

Fixes #1810

*  - Enabled all shadow tests, using our current output (as opposed to reference platform) as reference images
 - Make the reversion of transform to the identity matrix safer
 - Misc cleanup

* CR feedback

* Rewrite portions of EbrFile handling to use UTF16  (#1891)


* Rewrite path mapper to simplify code and support UTF16 path names.
* Rewrite Ebr file apis to use new path mapper.
* Remove dead code.
* fixed unit tests to build after refactor.
* Add NSFileManager test to use special characters.
* EbrGet/SetWritablePath are now IwGet/SetWritablePath, and support
UTF-16.

Fixes #1875

* Updating functionaltest.ps1 so it works in VSTS. (#1896)

* Disabling some NSDecimal subtraction tests on OSX (#1908)

* Update NSURLSessionConfiguration defaults to support OSX 10.12 (#1905)

#1905

* Objc2Winmd binary update:  (#1913)

* Objc2Winmd binary update: Fixed memory leak issues with IAsyncOperation implementation

* ObjC2Winmd binary update: Removed unnecessary comments

* Add benchmarking test project and add text drawing benchmark tests (#1876)

Creates a new test project Benchmark in the Unit Test group, which leverages GTest to run automated benchmark tests. Simple tests can be done with the TEST_BENCHMARK macro, or more complex ones can be used by creating classes to do setup and teardown so only specific parts of code are measured.

* Turning of clang modules. (#1914)

* Moving windows specific archival test(BackwardsCompatibilityWithOldWinObjCArchives) to windows only unit tests (#1907)

* This change implement UILabel minimumScale (#1918)

* implement UILabel minimumScaleFactor

* revert unncessary change to diagnose #1894

* CR comments

* comments

* SetTempFolder() should take wchar_t instead of char so that we don't (#1916)

* SetTempFolder() should take wchar_t instead of char so that we don't
lose encoding information. Fixes #1915

* Update usage of path names to UTF8 instead of CString

* CR feedback

* Update Implementation of NSURL.deletingLastPathExtension to OSX 10.12 (#1906)

* Improve performance in __CF_IsBridgedObject/__CF_IsCFObject (#1923)

* Improve performance in __CF_IsBridgedObject/__CF_IsCFObject
 - __CF_IsCFObject() calls __CF_IsBridgedObject()
 - Previously, __CF_IsBridgedObject() would do an O(n^2) comparison against the entire runtime class table.
   (O(n) traversal of table * O(n) check of inheritance tree)
 - These two functions are used in CF memory management functions, such as CFRetain/Release,
   and due to their prevalence, took up substantial portions of CPU time.
 - Changed bridged classes to adopt an empty 'bridged object' protocol when they are bridged/added to the class table.
   This protocol can be quickly checked against, and obviates the need to traverse the table.
 - Removed some redundant _cfisa checks in _CF_IsCFObject

Fixes #1490

*  - Remove use of objective-C

*  - Also handle NSCFType

* Switch our D2D factory to be multithreaded. (#1911)

Fixes #1895.

* Use block scope thread_local static for NSProgress progress stack (#1912)

* Use block scope thread_local static for NSProgress progress stack:

Works around issue with file_scope thread_local in current clang. Leak check unit test added.

* cr feedback: collapse initialization

* switch to auto and return type deduction

* Reintroduce unique_cf's move ctor/assignment.

* Enabling some image drawing tests, moving image drawing to a separate… (#1605)

* Enabling some image drawing tests, moving image drawing to a separate file and updating some image file names

* Fix bug in sizeWithFont (#1917)

NSString+UIKitAdditions sizeWithFont:constrainedToSize: should return the height that the text requires rather than the height of the text that can actually fit in the region that CTFramesetterSuggestFrameSizeWithConstraints returns.

* Framework changes as a prestep towards supporting TAEF tests.

* Add a common test static lib and move all tests to use TAEF under the covers

* Small fixes in UTs for debug.

* CoreAnimationTest update - disable unsupported CALayer controls; adds a header and footer table entry; affine transformations update (#1874)

* CoreAnimationTest update - disable unsupported CALayer controls; adds a header and footer table entry; affine transformations update

CHANGES:
1. Supports the enabling/disabling of layer property controls (greyed out if disabled)
2. Custom table view cells for header and footer added - view and number of layers
3. Affine transformations are now applied collectively, 3D transformation still require it to be centered at origin
4. Cosmetic updates and autolayout corrections - IslandWood autolayout still has some quirks (see CGRect- and CGPoint- cells)
5. All specialized layers extracted from external sources are marked as "not supported" even if render partially

Fixes #1598

* Code review feedback

* Change test output location

* Fix GitHub CI build status reporting

* Fix the Unit Test build break on OS X.

Fixes #1941.

* Augment the drawing tests with TAEF-specific behaviour.

* Fix interoperability with TAEF setup/teardown.
* Add a TAEF entrypoint and clear the win32 stuff out of the OS X one.

* Move UIKit.Xaml DependencyProperty registration out of UIKit.Layer's constructor. (#1949)

Fixes #1930.

* This change includes the addition of a few new features to UIButton. (#1920)

* This change includes the addition of a few new features to UIButton.  Some functionality deviates from the reference platform, but we feel that it aligns more closely with the default look and feel of Xaml buttons on Windows because buttons 'look' pressed in more cases with these changes, and there are straightforward ways to opt out of this behavior if it's not desired.

**adjustsImageWhenDisabled/adjustsImageWhenHighlighted**:
We're adding WinObjC-specific support for adjustsImageWhenDisabled and adjustsImageWhenHighlighted.  On the reference platform, this tinting/darkening behavior is ONLY applied to the button's background an foreground images, but on our platform, the tintening/darkening is applied to the entire button's bounds (including its background color), but NOT to its label text.  The primary justification for this approach is that there's not a straighforward way to tint Xaml Images on RS1, yet this approach also helps us implement simple SystemButton support and it makes UIButtons appear a bit more 'windows-like' in many cases, since they show more distinct pressed behavior.  The behavior is as follows; if adjustsImageWhenDisabled is set to YES, and if no UIControlStateDisabled properties are set on the button, then the entire button contents (aside from its label) receives a lightening effect.  Similar behavior is implemented for adjustsImageWhenHighlighted.  The way to opt-out of this behavior is to either set a single UIControlStateDisabled/UIControlStateHighlighted property, or to set adjustsImageWhenDisabled/adjustsImageWhenHighlighted to NO.

**SystemButton (aka buttonWithType)**:
We're adding support for UIButtonTypeSystem, which behaves as follows:

	- Default background is white.
	- Receives a default text color of (blue/green) [UIColor colorWithRed:0.0f green:0.47843137f blue:1.0f alpha:1.0f] which applies to all states (unless set otherwise)
	- Default to UIColor lightTextColor for disabled titleLabelColor

**SystemButton - Deviations from the Reference Platform**:
	- When selected, the entire label background turns the default text color (blue/green) [UIColor colorWithRed:0.0f green:0.47843137f blue:1.0f alpha:1.0f], and the text color is changed to white.  This seems like a corner case that we're not implementing until we need to for a customer.

	- When highlighted, the titleLabel contents (its text and any sublayer content) are tinted to a darker/greyed out version of the normal state.
		- Instead of this behavior, we're piggy-backing off of our adjustsImageWhenHighlighted implementation to avoid needing to do this extra work.  The button *looks* highlighted, so we don't have to change the text color.

	- On the reference platform, when disabled, text is grey by default, UNLESS any custom normal or disabled text colors are set.  On our platform, we DEFAULT to disabled to grey text and then you can change it, but changing the normal color won't affect the default color (for the sake of simplicity).

Scrubbed Annotations:
All UIButton annotations have been scrubbed and updated with 'NotInPlan' status as needed.

Fixes #1442
Fixes #1885
Fixes #1671
Fixes #1671

Fixes VSO 10145069.
Fixes VSO 9533114.

* Adding comments + clang-format.

* Incorporating CR feedback.

* Fixing up UIButton tests.

* Partial revert of 8bbd30f (#1957)

* Partial revert of 8bbd30f

* Fixing lab tests.  Also combinining tests into 1 common test. (#1951)

* Fixing lab tests.  Also combinining tests into 1 common test.

* CR Feedback.

* CR feedback

* Projection binary update: Fixed ARC issues caused by names starting with new/copy/alloc

* Projections binary update: fixed annotations for non-object types

* Working around #1965 in UIImageSetLayerContents. (#1967)

Fixes #1962.

* Adding support for borders to UILabel and UIButton (via CALayer and the CoreAnimation/UIKit composition layer).  Note that we still don't have border support on basic CALayers, because we haven't needed to add them yet, but the plumbing is in now place to add them when needed. (#1956)

Fixes #1884.

* Supporting gesture subclassing and firing delegates for supporting gestures concurrent firing negotiations. (#1909)

* Supporting gesture subclassing and firing delegates for negativating concurrent firing

* Comments

* Fix some regressions

* separate the gesture processing code into its own class and adding initial tests

* CR comments

* Comments

* comments

* delete UIGestureRecognizerDelegate.h which causes protocol forward usage which av the tests

* Add support for all CGTextDrawingModes (#1933)

Several changes have been added to address #1933 and #1935

CGContextDrawGlyphRun has been changed to _CGContextDrawGlyphRuns and __CGContext::DrawGlyphRun -> __CGContext::DrawGlyphsRuns, which takes a dummy struct GlyphRunData, which holds the DWRITE_GLYPH_RUN, relative position of the glyph run (to the text position), and attributes of the glyph run (fill color, etc.).

Text drawing methods such as CTFrameDraw now accumulate an array of GlyphRunDatas and pass them to _CGContextDrawGlyphRuns, which in turn calls context->DrawGlyphRuns.

To batch all run drawing for clipping/stroking into the same geometry, the runs have to be drawn with the same transformation, so position has to be given (hence relative position in GlyphRunData). The position is transformed by the inverse of the text transform, so when the glyph is drawn and transformed by the real text transform it will have the correct position. This has the added benefit of allowing us to draw a glyph run which has a transformed text matrix all together, rather than glyph-by-glyph as we did previously.

Because text drawing is being batched, attributes which are handled at draw time on a run-per-run basis such as fill color need to be done in DrawGlyphRuns. The attribute names are defined in CoreText, though all of them are just CoreGraphics attributes, so local values have been added to CGContext.mm and exported for the CT/UIKit versions as CG.

Images have been updates since changing this seems to have enabled antialiasing to some degree on several tests.

Fixes #1933
Fixes #1935

* Fixing naming of UIKit.Label helper method: TextBox->TextBlock. (#1970)

* Add support for colored and non-colored Patterns (#1952)

* Add support for coloured and non-colored Patterns
* Enables proper anchoring for patterns

* Avoid D2D1Group fill mode conversion for CGPath. (#1954)

* Avoid D2D1Group fill mode conversion for CGPath and other simple geometries. Fill mode conversion removed from CGContext.

* Remove unnecessary check for proper fill mode since only one fill mode will ever be converted to.

* Parameterized test for fill modes with embedded circles with alternating arc directions.

* Fix Fill/Stroke tests and remove redundant tests.

* Fix relative project path

* Updating version for 1702 release
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants