Skip to content

Commit

Permalink
Make CGContext display scale-agnostic by propagating the scale into D…
Browse files Browse the repository at this point in the history
…irect2D'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 microsoft#1180.
  • Loading branch information
DHowett committed Oct 18, 2016
1 parent 0f7de5a commit c0beac7
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 10 deletions.
8 changes: 7 additions & 1 deletion Frameworks/CoreGraphics/CGContext.mm
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,7 @@ static void __CGContextDrawGeometry(CGContextRef context, ID2D1Geometry* geometr
FAIL_FAST_IF_FAILED(renderTarget.As(&deviceContext));

D2D1_SIZE_F targetSize = renderTarget->GetSize();
//D2D1_SIZE_U unscaledTargetSize = renderTarget->GetPixelSize();
ComPtr<ID2D1Image> originalTarget;
deviceContext->GetTarget(&originalTarget);

Expand All @@ -599,6 +600,9 @@ static void __CGContextDrawGeometry(CGContextRef context, ID2D1Geometry* geometr

CGAffineTransform& currentTransform = currentState.transform;
CGAffineTransform transform = CGAffineTransformScale(currentTransform, 1.0, -1.0);
// undo the scale (propagated to DPI)
//transform = CGAffineTransformScale(transform, targetSize.width/(double)unscaledTargetSize.width, targetSize.height/(double)unscaledTargetSize.height);
// undo the slide (slide was in points, must be done after scale is undone)
transform = CGAffineTransformTranslate(transform, 0., targetSize.height);
deviceContext->SetTransform({ transform.a, transform.b, transform.c, transform.d, transform.tx, transform.ty });

Expand Down Expand Up @@ -1434,12 +1438,14 @@ CGImageRef CGBitmapContextGetImage(CGContextRef context) {
return ((__CGBitmapContext*)context)->Impl().image.get();
}

CGContextRef _CGBitmapContextCreateWithTexture(int width, int height, DisplayTexture* texture, DisplayTextureLocking* locking) {
CGContextRef _CGBitmapContextCreateWithTexture(
int width, int height, float scale, DisplayTexture* texture, DisplayTextureLocking* locking) {
CGImageRef newImage = nullptr;
__CGSurfaceInfo surfaceInfo = _CGSurfaceInfoInit(width, height, _ColorARGB);
newImage = new CGGraphicBufferImage(surfaceInfo, texture, locking);

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

__CGBitmapContext* context = __CGBitmapContext::CreateInstance(kCFAllocatorDefault);
__CGContextInitWithRenderTarget(context, renderTarget.Get());
Expand Down
11 changes: 4 additions & 7 deletions Frameworks/QuartzCore/CALayer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -352,14 +352,14 @@ void ReleaseDisplayTexture(DisplayTexture* tex) {

static LockingBufferInterface _globallockingBufferInterface;

CGContextRef CreateLayerContentsBitmapContext32(int width, int height) {
CGContextRef CreateLayerContentsBitmapContext32(int width, int height, float scale) {
DisplayTexture* tex = NULL;

if ([NSThread isMainThread]) {
tex = GetCACompositor()->CreateWritableBitmapTexture32(width, height);
}

CGContextRef ret = _CGBitmapContextCreateWithTexture(width, height, tex, &_globallockingBufferInterface);
CGContextRef ret = _CGBitmapContextCreateWithTexture(width, height, scale, tex, &_globallockingBufferInterface);

if (tex) {
_globallockingBufferInterface.ReleaseDisplayTexture(tex);
Expand Down Expand Up @@ -573,7 +573,7 @@ - (void)display {
// As an optimization, CALayer would use a bitmap context with a solid background colour
// instead of a DisplayTexture. Since bitmap contexts are currently broken as part of #1072,
// we'll fall back to always using the writable bitmap buffer.
drawContext = CreateLayerContentsBitmapContext32(width, height);
drawContext = CreateLayerContentsBitmapContext32(width, height, priv->contentsScale);
priv->drewOpaque = FALSE;
priv->ownsContents = TRUE;
}
Expand Down Expand Up @@ -609,10 +609,7 @@ - (void)display {
}

if (target->Backing()->Height() != 0) {
CGContextTranslateCTM(drawContext, 0, float(target->Backing()->Height()));
}
if (priv->contentsScale != 1.0f) {
CGContextScaleCTM(drawContext, priv->contentsScale, priv->contentsScale);
CGContextTranslateCTM(drawContext, 0, float(target->Backing()->Height())/priv->contentsScale);
}

CGContextScaleCTM(drawContext, 1.0f, -1.0f);
Expand Down
4 changes: 2 additions & 2 deletions Frameworks/QuartzCore/CAShapeLayer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
NSString* const kCALineCapRound = @"kCALineCapRound";
NSString* const kCALineCapSquare = @"kCALineCapSquare";

CGContextRef CreateLayerContentsBitmapContext32(int width, int height);
CGContextRef CreateLayerContentsBitmapContext32(int width, int height, float scale);

@implementation CAShapeLayer {
CGPathRef _path;
Expand Down Expand Up @@ -92,7 +92,7 @@ - (void)layoutSublayers {
int width = (int)(bbox.size.width * scale);
int height = (int)(bbox.size.height * scale);

CGContextRef drawContext = CreateLayerContentsBitmapContext32(width, height);
CGContextRef drawContext = CreateLayerContentsBitmapContext32(width, height, scale);

CGContextTranslateCTM(drawContext, 0, height);
if (scale != 1.0f) {
Expand Down
1 change: 1 addition & 0 deletions Frameworks/include/CGContextInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

COREGRAPHICS_EXPORT CGContextRef _CGBitmapContextCreateWithTexture(int width,
int height,
float scale,
DisplayTexture* texture = NULL,
DisplayTextureLocking* locking = NULL);
COREGRAPHICS_EXPORT CGContextRef _CGBitmapContextCreateWithFormat(int width, int height, __CGSurfaceFormat fmt);
Expand Down

0 comments on commit c0beac7

Please sign in to comment.