Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions Frameworks/AutoLayout/AutoLayout.mm
Original file line number Diff line number Diff line change
Expand Up @@ -473,23 +473,23 @@ - (BOOL)autoLayoutInvalidateContentSize {
if (CGSizeEqualToSize(layoutProperties->_intrinsicContentSize, newContentSize)) {
if (DEBUG_AUTO_LAYOUT_LIGHT) {
TraceVerbose(TAG, L"autoLayoutInvalidateContentSize: Size {%f, %f} didn't change; no need to revalidate constraints; no need to re-layout %hs(0x%p).",
object_getClassName(self),
self,
newContentSize.width,
newContentSize.height);
newContentSize.height,
object_getClassName(self),
self);
}

// No more work left to be done; the size didn't actually change.
return NO;
} else {
if (DEBUG_AUTO_LAYOUT_LIGHT) {
TraceVerbose(TAG, L"autoLayoutInvalidateContentSize: intrinsicContentSize changed from {%f, %f} to {%f, %f}; need to revalidate constraints and re-layout %hs(0x%p).",
object_getClassName(self),
self,
newContentSize.width,
newContentSize.height,
layoutProperties->_intrinsicContentSize.width,
layoutProperties->_intrinsicContentSize.height);
layoutProperties->_intrinsicContentSize.height,
object_getClassName(self),
self);
}

// Store the new intrinsicContentSize
Expand Down Expand Up @@ -611,6 +611,12 @@ - (UIView*)autolayoutRoot {
- (void)autoLayoutUpdateConstraints {
AutoLayoutProperties* layoutProperties = self._autoLayoutProperties;

if (DEBUG_AUTO_LAYOUT_LIGHT) {
TraceVerbose(TAG, L"autoLayoutUpdateConstraints: %hs(0x%p).",
object_getClassName(self),
self);
}

if (![layoutProperties->_associatedConstraints count]) {
return;
}
Expand Down
13 changes: 13 additions & 0 deletions Frameworks/CoreGraphics/CGContext.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2935,7 +2935,20 @@ CGContextRef CGBitmapContextCreateWithData(void* data,
RETURN_NULL_IF(!height);
RETURN_NULL_IF(!colorSpace);

size_t imputedBitsPerPixel = _CGImageImputeBitsPerPixelFromFormat(colorSpace, bitsPerComponent, bitmapInfo);
size_t bitsPerPixel = ((bytesPerRow / width) << 3);
size_t estimatedBytesPerRow = (imputedBitsPerPixel >> 3) * width;

if (data && estimatedBytesPerRow > bytesPerRow) {
TraceError(TAG, L"Invalid data stride: a %ux%u %ubpp context requires at least a %u-byte stride (requested: %u bytes/row).", width, height, imputedBitsPerPixel, estimatedBytesPerRow, bytesPerRow);
return nullptr;
}

if (!bytesPerRow) { // When data is not provided, we are allowed to use our estimates.
bitsPerPixel = imputedBitsPerPixel;
bytesPerRow = estimatedBytesPerRow;
}

WICPixelFormatGUID requestedPixelFormat;
RETURN_NULL_IF_FAILED(
_CGImageGetWICPixelFormatFromImageProperties(bitsPerComponent, bitsPerPixel, colorSpace, bitmapInfo, &requestedPixelFormat));
Expand Down
73 changes: 52 additions & 21 deletions Frameworks/CoreGraphics/CGImage.mm
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,13 @@

static const wchar_t* TAG = L"CGImage";

// TODO #1124: remove old code
#pragma region OLD_CODE
// This is used by XamlCompositor to flush the DisplayTexture cache.
// TODO GH#2098 look at where we're using the image cache and what we can do to avoid it.
static std::vector<CGImageDestructionListener> _imageDestructionListeners;
COREGRAPHICS_EXPORT void CGImageAddDestructionListener(CGImageDestructionListener listener) {
_imageDestructionListeners.push_back(listener);
}

#pragma endregion OLD_CODE

#pragma region CGImageImplementation

struct __CGImageImpl {
Expand Down Expand Up @@ -225,6 +223,12 @@ inline WICPixelFormatGUID PixelFormat() const {
_impl.renderingIntent = intent;
return *this;
}

~__CGImage() {
for (auto listener : _imageDestructionListeners) {
listener(this);
}
}
};

#pragma endregion CGImageImplementation
Expand Down Expand Up @@ -362,7 +366,9 @@ CGDataProviderRef CGImageGetDataProvider(CGImageRef img) {
RETURN_NULL_IF_FAILED(img->ImageSource()->CopyPixels(nullptr, stride, size, buffer.get()));

CGDataProviderRef dataProvider =
CGDataProviderCreateWithData(nullptr, buffer.release(), size, [](void* info, const void* data, size_t size) { IwFree(const_cast<void*>(data)); });
CGDataProviderCreateWithData(nullptr, buffer.release(), size, [](void* info, const void* data, size_t size) {
IwFree(const_cast<void*>(data));
});
CFAutorelease(dataProvider);
return dataProvider;
}
Expand Down Expand Up @@ -646,6 +652,12 @@ CGImageRef _CGImageCreateCopyWithPixelFormat(CGImageRef image, WICPixelFormatGUI
return imageRef;
}

CGImageRef _CGImageCreateFromDataProvider(CGDataProviderRef provider) {
RETURN_NULL_IF(!provider);
unsigned char* dataBytes = static_cast<unsigned char*>(const_cast<void*>(_CGDataProviderGetData(provider)));
return _CGImageGetImageFromData(dataBytes, _CGDataProviderGetSize(provider));
}

CGImageRef _CGImageGetImageFromData(void* data, int length) {
return _CGImageLoadImageWithWICDecoder(GUID_NULL, data, length);
}
Expand Down Expand Up @@ -710,6 +722,36 @@ CGImageRef _CGImageLoadImageWithWICDecoder(REFGUID decoderCls, void* bytes, int
return nil;
}

size_t _CGImageImputeBitsPerPixelFromFormat(CGColorSpaceRef colorSpace, size_t bitsPerComponent, CGBitmapInfo bitmapInfo) {
unsigned int alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
unsigned int byteOrder = bitmapInfo & kCGBitmapByteOrderMask;

// Try byte order first: The user can specify 32 or 16 directly.
switch (byteOrder) {
case kCGBitmapByteOrder32Little:
case kCGBitmapByteOrder32Big:
return 32;
case kCGBitmapByteOrder16Little:
case kCGBitmapByteOrder16Big:
return 16;
}

// Otherwise, try to figure out how many components there are.
size_t nComponents = CGColorSpaceGetNumberOfComponents(colorSpace);
switch (alphaInfo) {
case kCGImageAlphaNoneSkipFirst:
case kCGImageAlphaPremultipliedFirst:
case kCGImageAlphaFirst:
case kCGImageAlphaNoneSkipLast:
case kCGImageAlphaPremultipliedLast:
case kCGImageAlphaLast:
nComponents += 1;
break;
}

return (bitsPerComponent * nComponents);
}

// CG packed format key
// |Color |bits/px|CGBitmapInfo |
// |-------|-------|---------------|
Expand All @@ -719,7 +761,6 @@ CGImageRef _CGImageLoadImageWithWICDecoder(REFGUID decoderCls, void* bytes, int

HRESULT _CGImageGetWICPixelFormatFromImageProperties(
unsigned int bitsPerComponent, unsigned int bitsPerPixel, CGColorSpaceRef colorSpace, CGBitmapInfo bitmapInfo, GUID* pixelFormat) {

// clang-format off
static std::map<uint32_t, WICPixelFormatGUID> s_CGWICFormatMap{
{ CG_FORMAT_KEY(kCGColorSpaceModelRGB , 24, kCGBitmapByteOrderDefault, kCGImageAlphaNone), GUID_WICPixelFormat24bppRGB },
Expand Down Expand Up @@ -766,23 +807,13 @@ HRESULT _CGImageGetWICPixelFormatFromImageProperties(

RETURN_HR_IF(E_POINTER, !pixelFormat);

CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace);

unsigned int alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
unsigned int byteOrder = bitmapInfo & kCGBitmapByteOrderMask;
unsigned int formatImputedBpp = 0;
switch (byteOrder) {
case kCGBitmapByteOrder32Little:
case kCGBitmapByteOrder32Big:
formatImputedBpp = 32;
break;
case kCGBitmapByteOrder16Little:
case kCGBitmapByteOrder16Big:
formatImputedBpp = 16;
break;
size_t formatImputedBpp = _CGImageImputeBitsPerPixelFromFormat(colorSpace, bitsPerComponent, bitmapInfo);
if (bitsPerPixel == 0) {
bitsPerPixel = formatImputedBpp;
}

if (formatImputedBpp == 0 || formatImputedBpp == bitsPerPixel) {
if (formatImputedBpp == bitsPerPixel) {
CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace);
auto found = s_CGWICFormatMap.find(CG_FORMAT_KEY(colorSpaceModel, bitsPerPixel, bitmapInfo, 0));
if (found != s_CGWICFormatMap.end()) {
*pixelFormat = found->second;
Expand Down
11 changes: 7 additions & 4 deletions Frameworks/GLKit/GLKTexture.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 All @@ -25,6 +25,7 @@
#import <GLKit/GLKitExport.h>
#import <GLKit/GLKTexture.h>
#import "NSLogging.h"
#import "CGImageInternal.h"

static const wchar_t* TAG = L"GLKTexture";

Expand Down Expand Up @@ -277,7 +278,7 @@ @implementation GLKTextureLoader {
*/
+ (GLKTextureInfo*)textureWithContentsOfFile:(NSString*)fname options:(NSDictionary*)opts error:(NSError**)err {
CGDataProviderRef provider = CGDataProviderCreateWithFilename([fname UTF8String]);
CGImageRef img = CGImageCreateWithPNGDataProvider(provider, NULL, NO, kCGRenderingIntentDefault);
CGImageRef img = _CGImageCreateFromDataProvider(provider);

GLKTextureInfo* res = [self textureWithCGImage:img options:opts error:err];

Expand Down Expand Up @@ -395,7 +396,8 @@ + (GLKTextureInfo*)cubeMapWithContentsOfFile:(NSString*)fname options:(NSDiction
if (!provider) {
return nil;
}
CGImageRef img = CGImageCreateWithPNGDataProvider(provider, NULL, NO, kCGRenderingIntentDefault);

CGImageRef img = _CGImageCreateFromDataProvider(provider);
if (!img) {
CGDataProviderRelease(provider);
return nil;
Expand Down Expand Up @@ -541,7 +543,8 @@ + (GLKTextureInfo*)cubeMapWithContentsOfFiles:(NSArray*)fnames options:(NSDictio
curSide++;
continue;
}
CGImageRef img = CGImageCreateWithPNGDataProvider(provider, NULL, NO, kCGRenderingIntentDefault);

CGImageRef img = _CGImageCreateFromDataProvider(provider);
if (!img) {
CGDataProviderRelease(provider);
NSTraceWarning(TAG, @"Unable to create image from cube side texture %@", fn);
Expand Down
22 changes: 14 additions & 8 deletions Frameworks/QuartzCore/CALayer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -427,14 +427,20 @@ - (void)renderInContext:(CGContextRef)ctx {
[priv->delegate drawLayer:self inContext:ctx];
}
} else {
CGRect rect;

rect.origin.x = 0;
rect.origin.y = priv->bounds.size.height * priv->contentsScale;
rect.size.width = priv->bounds.size.width * priv->contentsScale;
rect.size.height = -priv->bounds.size.height * priv->contentsScale;

_CGContextDrawImageRect(ctx, priv->contents, rect, destRect);
// If the layer has cached contents, blit them directly.

// Since the layer was rendered in Quartz referential (ULO) AND the current context
// is assumed to be Quartz referential (ULO), BUT the layer's cached contents
// were captured in a CGImage (CGImage referential, LLO), we have to flip
// the context again before we render it.

// |1 0 0| is the transformation matrix for flipping a rect anchored at 0,0 about its Y midpoint.
// |0 -1 0|
// |0 h 1|
CGContextSaveGState(ctx);
CGContextConcatCTM(ctx, CGAffineTransformMake(1, 0, 0, -1, 0, destRect.size.height));
CGContextDrawImage(ctx, destRect, priv->contents);
CGContextRestoreGState(ctx);
}

// Draw sublayers
Expand Down
Loading