Unreviewed, rolling out r191902.
[WebKit-https.git] / Source / WebCore / platform / ios / wak / WKGraphics.mm
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2009 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "WKGraphics.h"
28
29 #if PLATFORM(IOS)
30
31 #import "CoreGraphicsSPI.h"
32 #import "FontCascade.h"
33 #import "WebCoreSystemInterface.h"
34 #import "WebCoreThread.h"
35 #import <ImageIO/ImageIO.h>
36 #import <wtf/StdLibExtras.h>
37
38 using namespace WebCore;
39
40 static inline void _FillRectsUsingOperation(CGContextRef context, const CGRect* rects, int count, CGCompositeOperation op)
41 {
42     int i;
43     CGRect *integralRects = reinterpret_cast<CGRect *>(alloca(sizeof(CGRect) * count));
44     
45     assert (integralRects);
46     
47     for (i = 0; i < count; i++) {
48         integralRects[i] = CGRectApplyAffineTransform (rects[i], CGContextGetCTM(context));
49         integralRects[i] = CGRectIntegral (integralRects[i]);
50         integralRects[i] = CGRectApplyAffineTransform (integralRects[i], CGAffineTransformInvert(CGContextGetCTM(context)));
51     }
52     CGCompositeOperation oldOp = CGContextGetCompositeOperation(context);
53     CGContextSetCompositeOperation(context, op);
54     CGContextFillRects(context, integralRects, count);
55     CGContextSetCompositeOperation(context, oldOp);
56 }
57
58 static inline void _FillRectUsingOperation(CGContextRef context, CGRect rect, CGCompositeOperation op)
59 {
60     if (rect.size.width > 0 && rect.size.height > 0) {
61         _FillRectsUsingOperation (context, &rect, 1, op);
62     }
63 }
64
65 void WKRectFill(CGContextRef context, CGRect aRect)
66 {
67     if (aRect.size.width > 0 && aRect.size.height > 0) {
68         CGContextSaveGState(context);
69         _FillRectUsingOperation(context, aRect, kCGCompositeCopy);
70         CGContextRestoreGState(context);
71     }
72 }
73
74 void WKRectFillUsingOperation(CGContextRef context, CGRect aRect, WKCompositeOperation compositeOperation)
75 {
76     COMPILE_ASSERT(sizeof(WKCompositeOperation) == sizeof(CGCompositeOperation), "WKCompositeOperation must be the same size as CGCompositeOperation.");
77     if (aRect.size.width > 0 && aRect.size.height > 0.0) {
78         CGContextSaveGState(context);
79         _FillRectUsingOperation(context, aRect, static_cast<CGCompositeOperation>(compositeOperation));
80         CGContextRestoreGState(context);
81     }
82 }
83
84 void WKSetCurrentGraphicsContext(CGContextRef context)
85 {
86     WebThreadContext* threadContext =  WebThreadCurrentContext();
87     threadContext->currentCGContext = context;
88 }
89
90 CGContextRef WKGetCurrentGraphicsContext(void)
91 {
92     WebThreadContext* threadContext =  WebThreadCurrentContext();
93     return threadContext->currentCGContext;
94 }
95
96 static NSString *imageResourcePath(const char* imageFile, unsigned scaleFactor)
97 {
98     NSString *fileName = scaleFactor == 1 ? [NSString stringWithUTF8String:imageFile] : [NSString stringWithFormat:@"%s@%dx", imageFile, scaleFactor];
99 #if PLATFORM(IOS_SIMULATOR)
100     NSBundle *bundle = [NSBundle bundleWithIdentifier:@"com.apple.WebCore"];
101     return [bundle pathForResource:fileName ofType:@"png"];
102 #else
103     // Workaround for <rdar://problem/7780665> CFBundleCopyResourceURL takes a long time on iPhone 3G.
104     NSString *imageDirectory = @"/System/Library/PrivateFrameworks/WebCore.framework";
105     return [NSString stringWithFormat:@"%@/%@.png", imageDirectory, fileName];
106 #endif
107 }
108
109 CGImageRef WKGraphicsCreateImageFromBundleWithName(const char *image_file)
110 {
111     if (!image_file)
112         return NULL;
113
114     CGImageRef image = nullptr;
115     NSData *imageData = nullptr;
116     for (unsigned scaleFactor = wkGetScreenScaleFactor(); scaleFactor > 0; --scaleFactor) {
117         imageData = [NSData dataWithContentsOfFile:imageResourcePath(image_file, scaleFactor)];
118         ASSERT(scaleFactor != wkGetScreenScaleFactor() || imageData);
119         if (imageData)
120             break;
121     }
122     
123     if (imageData) {
124         RetainPtr<CGDataProviderRef> dataProvider = adoptCF(CGDataProviderCreateWithCFData(reinterpret_cast<CFDataRef>(imageData)));
125         image = CGImageCreateWithPNGDataProvider(dataProvider.get(), nullptr, NO, kCGRenderingIntentDefault);
126     }
127
128     return image;
129 }
130
131 static void WKDrawPatternBitmap(void *info, CGContextRef c) 
132 {
133     CGImageRef image = (CGImageRef)info;
134     CGFloat scale = wkGetScreenScaleFactor();
135     CGContextDrawImage(c, CGRectMake(0, 0, CGImageGetWidth(image) / scale, CGImageGetHeight(image) / scale), image);    
136 }
137
138 static void WKReleasePatternBitmap(void *info) 
139 {
140     CGImageRelease(reinterpret_cast<CGImageRef>(info));
141 }
142
143 static const CGPatternCallbacks WKPatternBitmapCallbacks = 
144 {
145     0, WKDrawPatternBitmap, WKReleasePatternBitmap
146 };
147
148 CGPatternRef WKCreatePatternFromCGImage(CGImageRef imageRef)
149 {
150     // retain image since it's freed by our callback
151     CGImageRetain(imageRef);
152
153     CGFloat scale = wkGetScreenScaleFactor();
154     return CGPatternCreate((void*)imageRef, CGRectMake(0, 0, CGImageGetWidth(imageRef) / scale, CGImageGetHeight(imageRef) / scale), CGAffineTransformIdentity, CGImageGetWidth(imageRef) / scale, CGImageGetHeight(imageRef) / scale, kCGPatternTilingConstantSpacing, 1 /*isColored*/, &WKPatternBitmapCallbacks);
155 }
156
157 void WKSetPattern(CGContextRef context, CGPatternRef pattern, bool fill, bool stroke) 
158 {
159     if (pattern == NULL)
160         return;
161
162     CGFloat patternAlpha = 1;
163     CGColorSpaceRef colorspace = CGColorSpaceCreatePattern(NULL);
164     if (fill) {
165         CGContextSetFillColorSpace(context, colorspace);
166         CGContextSetFillPattern(context, pattern, &patternAlpha);
167     }
168     if (stroke) {
169         CGContextSetStrokeColorSpace(context, colorspace);
170         CGContextSetStrokePattern(context, pattern, &patternAlpha);
171     }
172     CGColorSpaceRelease(colorspace);
173 }
174
175 #endif // PLATFORM(IOS)