Fixed: <rdar://problem/3937663> repro assertion failure and crash dragging image...
[WebKit-https.git] / WebKit / WebCoreSupport.subproj / WebImageRendererFactory.m
1 /*
2  * Copyright (C) 2002 Apple Computer, 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 COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #import <WebKit/WebImageRendererFactory.h>
27 #import <WebKit/WebImageRenderer.h>
28
29 #import <WebKit/WebAssertions.h>
30 #import <Foundation/NSURLFileTypeMappings.h>
31
32 #import <CoreGraphics/CGContextPrivate.h>
33
34 @implementation WebImageRendererFactory
35
36 + (void)createSharedFactory
37 {
38     if (![self sharedFactory]) {
39         [[[self alloc] init] release];
40     }
41     ASSERT([[self sharedFactory] isKindOfClass:self]);
42 }
43
44 + (WebImageRendererFactory *)sharedFactory
45 {
46     return (WebImageRendererFactory *)[super sharedFactory];
47 }
48
49 - (id <WebCoreImageRenderer>)imageRendererWithMIMEType:(NSString *)MIMEType
50 {
51     WebImageRenderer *imageRenderer = [[WebImageRenderer alloc] initWithMIMEType:MIMEType];
52
53 #ifndef USE_CGIMAGEREF
54     NSImage *image = [imageRenderer image];
55
56     if (![MIMEType isEqual:@"application/pdf"]) {
57         NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initForIncrementalLoad];
58         [image addRepresentation:rep];
59         [rep autorelease];
60     }
61
62     [image setFlipped:YES];
63     
64     // Turn the default caching mode back on when the image has completed load.
65     // Caching intermediate progressive representations causes problems for
66     // progressive loads.  We also rely on the NSBitmapImageRep surviving during
67     // incremental loads.  See 3165631 and 3262592.
68     [image setCacheMode: NSImageCacheNever];
69
70     [image setScalesWhenResized:NO];
71 #endif
72         
73     return [imageRenderer autorelease];
74 }
75
76 - (id <WebCoreImageRenderer>)imageRenderer
77 {
78     return [self imageRendererWithMIMEType:nil];
79 }
80
81 - (id <WebCoreImageRenderer>)imageRendererWithData:(NSData*)data MIMEType:(NSString *)MIMEType
82 {
83     WebImageRenderer *imageRenderer = [[WebImageRenderer alloc] initWithData:data MIMEType:MIMEType];
84
85 #ifndef USE_CGIMAGEREF
86     NSImage *image = [imageRenderer image];
87
88     NSArray *reps = [image representations];
89     if ([reps count] == 0){
90         [imageRenderer release];
91         return nil;
92     }
93     
94     // Force the image to use the pixel size and ignore the dpi.
95     [image setScalesWhenResized:NO];
96     if ([reps count] > 0){
97         NSImageRep *rep = [reps objectAtIndex:0];
98         [rep setSize:NSMakeSize([rep pixelsWide], [rep pixelsHigh])];
99         if ([imageRenderer frameCount] > 1)
100             [imageRenderer setOriginalData:data];
101     }
102     
103     [image setFlipped:YES];
104 #endif
105
106     return [imageRenderer autorelease];
107 }
108
109 - (id <WebCoreImageRenderer>)imageRendererWithBytes:(const void *)bytes length:(unsigned)length MIMEType:(NSString *)MIMEType
110 {
111     NSData *data = [[NSData alloc] initWithBytes:(void *)bytes length:length];
112     WebImageRenderer *imageRenderer = [self imageRendererWithData:data MIMEType:MIMEType];
113     [data autorelease];
114     return imageRenderer;
115 }
116
117 - (id <WebCoreImageRenderer>)imageRendererWithBytes:(const void *)bytes length:(unsigned)length
118 {
119     return [self imageRendererWithBytes:bytes length:length MIMEType:nil];
120 }
121
122 - (id <WebCoreImageRenderer>)imageRendererWithSize:(NSSize)s
123 {
124     WebImageRenderer *imageRenderer = [[[WebImageRenderer alloc] initWithSize:s] autorelease];
125 #ifndef USE_CGIMAGEREF
126     [[imageRenderer image] setScalesWhenResized:NO];
127 #endif
128     return imageRenderer;
129 }
130
131 - (id <WebCoreImageRenderer>)imageRendererWithName:(NSString *)name
132 {
133     WebImageRenderer *imageRenderer = [[[WebImageRenderer alloc] initWithContentsOfFile:name] autorelease];
134 #ifndef USE_CGIMAGEREF
135     [[imageRenderer image] setScalesWhenResized:NO];
136     [[imageRenderer image] setFlipped:YES];
137 #endif
138     return imageRenderer;
139 }
140
141 struct CompositeOperator
142 {
143     NSString *name;
144     CGCompositeOperation value;
145 };
146
147 #define NUM_COMPOSITE_OPERATORS 14
148 struct CompositeOperator CGCompositeOperations[NUM_COMPOSITE_OPERATORS] = {
149     { @"clear", kCGCompositeClear },
150     { @"copy", kCGCompositeCopy },
151     { @"source-over", kCGCompositeSover },
152     { @"source-in", kCGCompositeSin },
153     { @"source-out", kCGCompositeSout },
154     { @"source-atop", kCGCompositeSatop },
155     { @"destination-over", kCGCompositeDover },
156     { @"destination-in", kCGCompositeDin },
157     { @"destination-out", kCGCompositeDout },
158     { @"destination-atop", kCGCompositeDatop },
159     { @"xor", kCGCompositeXor },
160     { @"darker", kCGCompositePlusd },
161     { @"highlight", kCGCompositePlusl },
162     { @"lighter", kCGCompositePlusl }    // Per AppKit
163 };
164
165 - (int)CGCompositeOperationInContext:(CGContextRef)context
166 {
167     CGCompositeOperation op = CGContextGetCompositeOperation (context);
168     return (int)op;
169 }
170
171 - (void)setCGCompositeOperation:(int)op inContext:(CGContextRef)context
172 {
173     CGContextSetCompositeOperation(context, (CGCompositeOperation)op);
174 }
175
176 - (void)setCGCompositeOperationFromString:(NSString *)operatorString inContext:(CGContextRef)context
177 {
178     CGCompositeOperation op = kCGCompositeSover;
179     
180     if (operatorString) {
181         int i;
182         
183         for (i = 0; i < NUM_COMPOSITE_OPERATORS; i++) {
184             if ([operatorString caseInsensitiveCompare:CGCompositeOperations[i].name] == NSOrderedSame) {
185                 op = CGCompositeOperations[i].value;
186                 break;
187             }
188         }
189     }
190     
191     CGContextSetCompositeOperation(context, op);
192 }
193
194
195 - (NSArray *)supportedMIMETypes
196 {
197     static NSArray *imageMIMETypes = nil;
198
199     if (imageMIMETypes == nil) {
200         NSEnumerator *enumerator = [[NSImage imageFileTypes] objectEnumerator];
201         NSURLFileTypeMappings *mappings = [NSURLFileTypeMappings sharedMappings];
202         NSMutableSet *mimes = [NSMutableSet set];
203         NSString *type;
204
205         while ((type = [enumerator nextObject]) != nil) {
206             NSString *mime = [mappings MIMETypeForExtension:type];
207             if (mime != nil && ![mime isEqualToString:@"application/octet-stream"]) {
208                 [mimes addObject:mime];
209             }
210         }
211
212         // image/pjpeg is the MIME type for progressive jpeg. These files have the jpg file extension.
213         // This is workaround of NSURLFileTypeMappings's limitation of only providing 1 MIME type for an extension.
214         [mimes addObject:@"image/pjpeg"];
215         
216         imageMIMETypes = [[mimes allObjects] retain];
217     }
218
219     return imageMIMETypes;
220 }
221
222
223 @end