Skip to content

Commit

Permalink
Merge remote-tracking branch 'github/develop' into github-CGD2D
Browse files Browse the repository at this point in the history
Conflicts:
	Frameworks/CoreGraphics/CGImage.mm
	Frameworks/CoreText/CTFramesetter.mm
	Frameworks/ImageIO/CGImageDestination.mm
	tests/UnitTests/CoreGraphics.drawing/CGContextDrawingTests.cpp
	tests/unittests/CoreGraphics.Drawing/CGPathDrawingTests.cpp
	tests/unittests/CoreGraphics.drawing/ImageComparison.cpp
  • Loading branch information
DHowett committed Jan 18, 2017
2 parents 0b0e096 + 2f64e60 commit d1b386b
Show file tree
Hide file tree
Showing 92 changed files with 1,643 additions and 720 deletions.
25 changes: 9 additions & 16 deletions Frameworks/CoreGraphics/CGImage.mm
Original file line number Diff line number Diff line change
Expand Up @@ -358,10 +358,10 @@ CGDataProviderRef CGImageGetDataProvider(CGImageRef img) {

RETURN_NULL_IF_FAILED(img->ImageSource()->CopyPixels(nullptr, stride, size, buffer.get()));

woc::unique_cf<CFDataRef> data{ CFDataCreateWithBytesNoCopy(nullptr, buffer.release(), size, kCFAllocatorDefault) };
CGDataProviderRef ret = CGDataProviderCreateWithCFData(data.get());
CFAutorelease(ret);
return ret;
CGDataProviderRef dataProvider =
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 @@ -533,13 +533,8 @@ CGImageRef CGImageCreateWithMask(CGImageRef image, CGImageRef mask) {
size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);

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

CGRect rect{
Expand Down Expand Up @@ -809,14 +804,14 @@ static void __InvertMemcpy(void* dest, const void* src, size_t len) {
uint32_t* d32 = (uint32_t*)dest;
const uint32_t* s32 = (const uint32_t*)src;

for(; len >= 4; len -= 4) {
for (; len >= 4; len -= 4) {
*d32++ = ~*s32++;
}

uint8_t* d8 = (uint8_t*)d32;
const uint8_t* s8 = (const uint8_t*)s32;

for(; len > 0; --len) {
for (; len > 0; --len) {
*d8++ = ~*s8++;
}
}
Expand Down Expand Up @@ -873,9 +868,7 @@ static HRESULT __CGImageMaskConvertToWICAlphaBitmap(CGImageRef image, IWICBitmap
} else {
// stride or length (likely both) differ
uint8_t* destEnd = alpha8Data + alpha8Len;
for(uint8_t *src = gray8Data, *dest = alpha8Data;
dest < destEnd;
src += gray8Stride, dest += alpha8Stride) {
for (uint8_t *src = gray8Data, *dest = alpha8Data; dest < destEnd; src += gray8Stride, dest += alpha8Stride) {
__InvertMemcpy(dest, src, gray8Stride);
}
}
Expand Down
71 changes: 30 additions & 41 deletions Frameworks/CoreText/CTFramesetter.mm
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,26 @@
#import "CGPathInternal.h"
#import "DWriteWrapper_CoreText.h"

using namespace std;

@implementation _CTFramesetter : NSObject
@end

static _CTFrame* __CreateFrame(_CTFramesetter* framesetter, CGRect frameRect, CFRange range) {
RETURN_NULL_IF(framesetter == nil);
/**
@Status Interoperable
*/
CTFramesetterRef CTFramesetterCreateWithAttributedString(CFAttributedStringRef string) {
_CTFramesetter* ret = [_CTFramesetter alloc];
ret->_typesetter = static_cast<_CTTypesetter*>(CTTypesetterCreateWithAttributedString(string));
return static_cast<CTFramesetterRef>(ret);
}

/**
@Status Caveat
@Notes frameAttributes parameter ignored
*/
CTFrameRef CTFramesetterCreateFrame(CTFramesetterRef framesetterRef, CFRange range, CGPathRef path, CFDictionaryRef frameAttributes) {
RETURN_NULL_IF(framesetterRef == nil || path == nullptr);
CGRect frameRect = CGPathGetBoundingBox(path);
_CTFramesetter* framesetter = static_cast<_CTFramesetter*>(framesetterRef);

// Call _DWriteWrapper to get _CTLine object list that makes up this frame
_CTTypesetter* typesetter = static_cast<_CTTypesetter*>(framesetter->_typesetter);
Expand All @@ -36,10 +49,12 @@ @implementation _CTFramesetter : NSObject
}

StrongId<_CTFrame> ret = _DWriteGetFrame(static_cast<CFAttributedStringRef>(typesetter->_attributedString.get()), range, frameRect);
ret->_path.reset(CGPathRetain(path));
ret->_frameRect.origin = frameRect.origin;

// Trying to access attributes without any text will throw an error
if (range.length <= 0L) {
return ret.detach();
return static_cast<CTFrameRef>(ret.detach());
}

CTParagraphStyleRef settings =
Expand All @@ -48,7 +63,7 @@ @implementation _CTFramesetter : NSObject
effectiveRange:nullptr]);

if (settings == nullptr) {
return ret.detach();
return static_cast<CTFrameRef>(ret.detach());
}

// DWrite only gives manual control of lineheight when it is constant through a frame
Expand Down Expand Up @@ -87,30 +102,7 @@ @implementation _CTFramesetter : NSObject
}
}

return ret.detach();
}

/**
@Status Interoperable
*/
CTFramesetterRef CTFramesetterCreateWithAttributedString(CFAttributedStringRef string) {
_CTFramesetter* ret = [_CTFramesetter alloc];
ret->_typesetter = static_cast<_CTTypesetter*>(CTTypesetterCreateWithAttributedString(string));
return static_cast<CTFramesetterRef>(ret);
}

/**
@Status Caveat
@Notes frameAttributes parameter ignored
*/
CTFrameRef CTFramesetterCreateFrame(CTFramesetterRef framesetter, CFRange stringRange, CGPathRef path, CFDictionaryRef frameAttributes) {
CGRect containingRect = CGPathGetBoundingBox(path);

_CTFrame* ret = __CreateFrame(static_cast<_CTFramesetter*>(framesetter), containingRect, stringRange);
ret->_path.reset(CGPathRetain(path));
ret->_frameRect.origin = containingRect.origin;

return static_cast<CTFrameRef>(ret);
return static_cast<CTFrameRef>(ret.detach());
}

/**
Expand All @@ -122,23 +114,20 @@ CTTypesetterRef CTFramesetterGetTypesetter(CTFramesetterRef framesetter) {
}

/**
@Status Interoperable
@Status Caveat
@Notes frameAttributes parameter ignored
@Notes
*/
CGSize CTFramesetterSuggestFrameSizeWithConstraints(
CTFramesetterRef framesetter, CFRange stringRange, CFDictionaryRef frameAttributes, CGSize constraints, CFRange* fitRange) {
CGRect frameSize = CGRectZero;
frameSize.size = constraints;

_CTFrame* frame = __CreateFrame(static_cast<_CTFramesetter*>(framesetter), frameSize, stringRange);
CGSize ret = frame ? frame->_frameRect.size : CGSizeZero;

if (fitRange) {
*fitRange = CTFrameGetVisibleStringRange(static_cast<CTFrameRef>(frame));
if (framesetter == nil) {
return CGSizeZero;
}

[frame release];
return ret;
CFAttributedStringRef string =
static_cast<CFAttributedStringRef>(static_cast<_CTFramesetter*>(framesetter)->_typesetter->_attributedString.get());

return _DWriteGetFrameSize(string, stringRange, constraints, fitRange);
}

/**
Expand Down
1 change: 1 addition & 0 deletions Frameworks/CoreText/DWriteWrapper_CoreText.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ struct _DWriteGlyphRunDetails {

bool _CloneDWriteGlyphRun(_In_ DWRITE_GLYPH_RUN const* src, _Outptr_ DWRITE_GLYPH_RUN* dest);

CGSize _DWriteGetFrameSize(CFAttributedStringRef string, CFRange range, CGSize maxSize, CFRange* fitRange);
_CTFrame* _DWriteGetFrame(CFAttributedStringRef string, CFRange range, CGRect frameSize);
_CTLine* _DWriteGetLine(CFAttributedStringRef string);

Expand Down
58 changes: 58 additions & 0 deletions Frameworks/CoreText/DWriteWrapper_CoreText.mm
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#import <StringHelpers.h>
#import <vector>
#import <iterator>
#import <numeric>

using namespace std;
using namespace Microsoft::WRL;
Expand Down Expand Up @@ -522,4 +523,61 @@ HRESULT STDMETHODCALLTYPE GetPixelsPerDip(_In_opt_ void* clientDrawingContext, _
}

return frame;
}

static CGSize _DWriteGetFrameSize(CFAttributedStringRef string, CFRange range, CGSize maxSize, CFRange* fitRange) {
CGSize ret = CGSizeZero;

// Treat range.length of 0 as unlimited length
if (range.length == 0L) {
range.length = CFAttributedStringGetLength(string) - range.location;
}

// No text to draw, just return CGSizeZero
if (!string || range.length <= 0L) {
return ret;
}

ComPtr<IDWriteTextLayout> textLayout;
if (FAILED(__DWriteTextLayoutCreate(string, range, { CGPointZero, maxSize }, &textLayout))) {
return ret;
}

DWRITE_TEXT_METRICS textMetrics;
if (FAILED(textLayout->GetMetrics(&textMetrics))) {
return ret;
}

// TODO:: find more precise value than 1.0 to increase width by to fully enclose frame
ret.width = std::min(maxSize.width, textMetrics.widthIncludingTrailingWhitespace + 1.0f);
ret.height = std::min(maxSize.height, textMetrics.height);

if (fitRange) {
*fitRange = { range.location, 0L };
uint32_t lineCount = 0;

// Should return E_NOT_SUFFICIENT_BUFFER and popluate lineCount
if (textLayout->GetLineMetrics(nullptr, 0, &lineCount) != E_NOT_SUFFICIENT_BUFFER) {
return ret;
}

std::vector<DWRITE_LINE_METRICS> metrics(lineCount);
if (FAILED(textLayout->GetLineMetrics(metrics.data(), lineCount, &lineCount))) {
return ret;
}

float totalHeight = 0;
CFIndex endPos = range.location;
for (auto metric : metrics) {
totalHeight += metric.baseline;
if (totalHeight > ret.height) {
break;
}
endPos += metric.length;
}

fitRange->length = endPos;
}

return ret;
}
11 changes: 10 additions & 1 deletion Frameworks/Foundation/NSCFArray.mm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//******************************************************************************
//
// Copyright (c) 2016 Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
Expand Down Expand Up @@ -106,6 +106,7 @@ - (void)removeLastObject {

- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(NSObject*)obj {
BRIDGED_THROW_IF_IMMUTABLE(_CFArrayIsMutable, CFArrayRef);
NS_COLLECTION_THROW_IF_NULL_REASON(obj, [NSString stringWithFormat:@"*** %@ object cannot be nil", NSStringFromSelector(_cmd)]);
// Fastpath
CFRange range;
range.location = index;
Expand All @@ -115,6 +116,13 @@ - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(NSObject*)obj {

- (void)insertObject:(NSObject*)objAddr atIndex:(NSUInteger)index {
BRIDGED_THROW_IF_IMMUTABLE(_CFArrayIsMutable, CFArrayRef);
NS_COLLECTION_THROW_IF_NULL_REASON(objAddr, [NSString stringWithFormat:@"*** %@ object cannot be nil", NSStringFromSelector(_cmd)]);
if (objAddr == nil) {
@throw [NSException exceptionWithName:NSInvalidArgumentException
reason:[NSString stringWithFormat:@"*** %@ object cannot be nil", NSStringFromSelector(_cmd)]
userInfo:nil];
}

CFArrayInsertValueAtIndex(static_cast<CFMutableArrayRef>(self), index, reinterpret_cast<const void*>(objAddr));
}

Expand All @@ -125,6 +133,7 @@ - (void)removeAllObjects {

- (void)addObject:(NSObject*)objAddr {
BRIDGED_THROW_IF_IMMUTABLE(_CFArrayIsMutable, CFArrayRef);
NS_COLLECTION_THROW_IF_NULL_REASON(objAddr, [NSString stringWithFormat:@"*** %@ object cannot be nil", NSStringFromSelector(_cmd)]);
CFArrayAppendValue((CFMutableArrayRef)self, (const void*)objAddr);
}

Expand Down
17 changes: 11 additions & 6 deletions Frameworks/Foundation/NSCFAttributedString.mm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//******************************************************************************
//
// Copyright (c) 2016 Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
Expand All @@ -19,6 +19,7 @@
#import <Foundation/NSMutableAttributedString.h>
#import "NSCFAttributedString.h"
#import "CFFoundationInternal.h"
#import "NSCFCollectionSupport.h"

#import <algorithm>

Expand All @@ -35,8 +36,10 @@ - (_Nullable instancetype)init {
}

- (_Nullable instancetype)initWithAttributedString:(NSAttributedString*)string {
return reinterpret_cast<NSAttributedStringPrototype*>(static_cast<NSAttributedString*>(
CFAttributedStringCreateWithSubstring(kCFAllocatorDefault, static_cast<CFAttributedStringRef>(string), CFRange{ 0, [string length] })));
return reinterpret_cast<NSAttributedStringPrototype*>(
static_cast<NSAttributedString*>(CFAttributedStringCreateWithSubstring(kCFAllocatorDefault,
static_cast<CFAttributedStringRef>(string),
CFRange{ 0, [string length] })));
}

- (_Nullable instancetype)initWithString:(NSString*)string attributes:(NSDictionary*)attributes {
Expand All @@ -58,11 +61,13 @@ - (_Nullable instancetype)init {
}

- (_Nullable instancetype)initWithAttributedString:(NSAttributedString*)string {
return reinterpret_cast<NSMutableAttributedStringPrototype*>(CFAttributedStringCreateMutableCopy(kCFAllocatorDefault, 0, static_cast<CFAttributedStringRef>(string)));
return reinterpret_cast<NSMutableAttributedStringPrototype*>(
CFAttributedStringCreateMutableCopy(kCFAllocatorDefault, 0, static_cast<CFAttributedStringRef>(string)));
}

- (_Nullable instancetype)initWithString:(NSString*)string attributes:(NSDictionary*)attributes {
NSMutableAttributedString* attributedString = static_cast<NSMutableAttributedString*>(CFAttributedStringCreateMutable(kCFAllocatorDefault, 0));
NSMutableAttributedString* attributedString =
static_cast<NSMutableAttributedString*>(CFAttributedStringCreateMutable(kCFAllocatorDefault, 0));
CFAttributedStringReplaceString(static_cast<CFMutableAttributedStringRef>(attributedString),
CFRange{ 0, 0 },
static_cast<CFStringRef>(string));
Expand Down Expand Up @@ -108,7 +113,7 @@ - (NSMutableString*)mutableString {
- (void)addAttribute:(NSString*)name value:(id)value range:(NSRange)range {
BRIDGED_THROW_IF_IMMUTABLE(_CFAttributedStringIsMutable, CFAttributedStringRef);
THROW_NS_IF_FALSE(E_BOUNDS, ((range.location + range.length) <= [self length]));

NS_COLLECTION_THROW_IF_NULL_REASON(value, [NSString stringWithFormat:@"*** %@ nil value", NSStringFromSelector(_cmd)]);
CFAttributedStringSetAttribute(reinterpret_cast<CFMutableAttributedStringRef>(self),
*reinterpret_cast<CFRange*>(&range),
(__bridge CFStringRef)name,
Expand Down
17 changes: 15 additions & 2 deletions Frameworks/Foundation/NSCFCollectionSupport.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//******************************************************************************
//
// Copyright (c) 2016 Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
Expand All @@ -25,4 +25,17 @@ const void* _NSCFCallbackRetain(CFAllocatorRef allocator, const void* value);
void _NSCFCallbackRelease(CFAllocatorRef allocator, const void* value);
CFStringRef _NSCFCallbackCopyDescription(const void* value);
Boolean _NSCFCallbackEquals(const void* value1, const void* value2);
CFHashCode _NSCFCallbackHash(const void* value);
CFHashCode _NSCFCallbackHash(const void* value);

#ifdef __OBJC__
#include <Foundation/NSException.h>

// Helper macro for NSCF collections to use CF counterparts that don't throw when trying to insert nil
#define NS_COLLECTION_THROW_IF_NULL_REASON(VALUE, ...) \
do { \
if (VALUE == nil) { \
@throw [NSException exceptionWithName:NSInvalidArgumentException reason:(__VA_ARGS__) userInfo:nil]; \
} \
} while (false)

#endif // __OBJC__
5 changes: 4 additions & 1 deletion Frameworks/Foundation/NSCFDictionary.mm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//******************************************************************************
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
Expand Down Expand Up @@ -112,6 +112,9 @@ - (NSEnumerator*)keyEnumerator {

- (void)setObject:(id)object forKey:(id)key {
BRIDGED_THROW_IF_IMMUTABLE(_CFDictionaryIsMutable, CFDictionaryRef);
NS_COLLECTION_THROW_IF_NULL_REASON(object,
[NSString
stringWithFormat:@"*** %@ object cannot be nil (key: %@)", NSStringFromSelector(_cmd), key]);
CFDictionarySetValue((CFMutableDictionaryRef)self, (const void*)key, (void*)object);
}

Expand Down
Loading

0 comments on commit d1b386b

Please sign in to comment.