]> git.saurik.com Git - winterboard.git/blob - WBMarkup.mm
Fix UISound theming on iOS 6.1 (maybe 6.0?).
[winterboard.git] / WBMarkup.mm
1 #include "WBMarkup.h"
2
3 @class WKView;
4
5 extern "C" {
6 void WebThreadLock();
7 CGContextRef WKGetCurrentGraphicsContext();
8 void WKViewLockFocus(WKView *);
9 void WKViewUnlockFocus(WKView *);
10 void WKViewDisplayRect(WKView *, CGRect);
11 }
12
13 @interface DOMElement : NSObject
14 - (void) setInnerHTML:(NSString *)value;
15 - (void) setInnerText:(NSString *)value;
16 - (void) setAttribute:(NSString *)name value:(NSString *)value;
17 - (void) removeAttribute:(NSString *)name;
18 - (DOMElement *) firstChild;
19 - (void) appendChild:(DOMElement *)child;
20 - (void) removeChild:(DOMElement *)child;
21 - (void) setScrollXOffset:(float)x scrollYOffset:(float)y;
22 @end
23
24 @interface DOMDocument : NSObject
25 - (DOMElement *) getElementById:(NSString *)id;
26 @end
27
28 @interface WebPreferences : NSObject
29 - (id) initWithIdentifier:(NSString *)identifier;
30 - (void) setPlugInsEnabled:(BOOL)value;
31 @end
32
33 @interface WebFrameView : NSObject
34 - (void) setAllowsScrolling:(BOOL)value;
35 @end
36
37 @interface WebFrame : NSObject
38 - (WebFrameView *) frameView;
39 - (void) _setLoadsSynchronously:(BOOL)value;
40 - (void) loadHTMLString:(NSString *)string baseURL:(id)url;
41 - (void) forceLayoutAdjustingViewSize:(BOOL)adjust;
42 - (CGSize) renderedSizeOfNode:(DOMElement *)node constrainedToWidth:(float)width;
43 - (DOMDocument *) DOMDocument;
44 @end
45
46 @interface WAKView : NSObject
47 - (void) _drawRect:(CGRect)rect context:(CGContext *)context lockFocus:(bool)focus;
48 @end
49
50 @interface WebView : WAKView
51 - (id) initWithFrame:(CGRect)frame;
52 - (WebFrame *) mainFrame;
53 - (void) setDrawsBackground:(BOOL)value;
54 - (void) setPreferences:(WebPreferences *)preferences;
55 - (WKView *) _viewRef;
56 @end
57
58 @interface WAKWindow : NSObject
59 - (id) initWithFrame:(CGRect)frame;
60 - (void) setContentView:(WebView *)view;
61 @end
62
63 static WBMarkup *SharedMarkup_;
64
65 @implementation WBMarkup
66
67 + (BOOL) isSharedMarkupCreated {
68 return SharedMarkup_ != nil;
69 }
70
71 + (WBMarkup *) sharedMarkup {
72 if (SharedMarkup_ == nil)
73 SharedMarkup_ = [[WBMarkup alloc] init];
74 return SharedMarkup_;
75 }
76
77 - (id) init {
78 if ((self = [super init]) != nil) {
79 WebThreadLock();
80
81 SharedMarkup_ = self;
82
83 view_ = [[WebView alloc] initWithFrame:CGRectMake(0, 0, 640, 5000)];
84 [view_ setDrawsBackground:NO];
85
86 WebPreferences *preferences([[WebPreferences alloc] initWithIdentifier:@"com.apple.webkit.webmarkup"]);
87 [preferences setPlugInsEnabled:NO];
88 [view_ setPreferences:preferences];
89 [preferences release];
90
91 window_ = [[WAKWindow alloc] initWithFrame:CGRectMake(0, 0, 640, 5000)];
92 [window_ setContentView:view_];
93
94 WebFrame *frame([view_ mainFrame]);
95 [[frame frameView] setAllowsScrolling:NO];
96 [frame _setLoadsSynchronously:YES];
97
98 [frame loadHTMLString:@"<html><body style='margin: 0px; word-wrap: break-word; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space'><div id='size'><div id='text'></div></div></body></html>" baseURL:nil];
99 } return self;
100 }
101
102 - (void) dealloc {
103 [window_ release];
104 [view_ release];
105 [super dealloc];
106 }
107
108 - (void) drawRect:(CGRect)rect {
109 [text_ setScrollXOffset:origin_.x scrollYOffset:origin_.y];
110
111 CGRect draw(CGRectMake(0, 0, rect.size.width - rect.origin.x, rect.size.height - rect.origin.y));
112
113 CGContextSaveGState(context_); {
114 CGContextTranslateCTM(context_, rect.origin.x, rect.origin.y);
115
116 if (kCFCoreFoundationVersionNumber > 700)
117 [view_ _drawRect:draw context:context_ lockFocus:YES];
118 else {
119 WKView *view([view_ _viewRef]);
120 WKViewLockFocus(view); {
121 WKViewDisplayRect(view, draw);
122 } WKViewUnlockFocus(view);
123 }
124 } CGContextRestoreGState(context_);
125 }
126
127 - (WebView *) _webView {
128 return view_;
129 }
130
131 - (void) setStringDrawingOrigin:(CGPoint)origin {
132 origin_ = origin;
133 }
134
135 - (void) clearStringDrawingOrigin {
136 origin_ = CGPointZero;
137 }
138
139 - (CGSize) sizeOfMarkup:(NSString *)markup forWidth:(float)width {
140 WebThreadLock();
141
142 if (![self _webPrepareContextForTextDrawing:NO])
143 return CGSizeZero;
144
145 [text_ setInnerHTML:markup];
146 [text_ removeAttribute:@"style"];
147
148 NSString *value([[NSString alloc] initWithFormat:[self _styleFormatString:@"width: %.0fpx; height: 5000px"], width]);
149 [size_ setAttribute:@"style" value:value];
150 [value release];
151
152 [[view_ mainFrame] forceLayoutAdjustingViewSize:YES];
153 return [[view_ mainFrame] renderedSizeOfNode:text_ constrainedToWidth:width];
154 }
155
156 - (CGSize) sizeOfString:(NSString *)string withStyle:(NSString *)style forWidth:(float)width {
157 WebThreadLock();
158
159 if (![self _webPrepareContextForTextDrawing:NO])
160 return CGSizeZero;
161
162 [size_ removeChild:[size_ firstChild]];
163
164 WebFrame *frame([view_ mainFrame]);
165
166 [frame forceLayoutAdjustingViewSize:YES];
167 [text_ setInnerText:string];
168 [self _setupWithStyle:style width:width height:5000];
169 [frame forceLayoutAdjustingViewSize:YES];
170
171 return [[view_ mainFrame] renderedSizeOfNode:text_ constrainedToWidth:width];
172 }
173
174 - (NSString *) _styleFormatString:(NSString *)style {
175 return style;
176 }
177
178 - (void) _setupWithStyle:(NSString *)style width:(float)width height:(float)height {
179 WebThreadLock();
180
181 if (style != nil && [style length] != 0)
182 [text_ setAttribute:@"style" value:style];
183 else
184 [text_ removeAttribute:@"style"];
185
186 NSString *value([[NSString alloc] initWithFormat:[self _styleFormatString:@"width: %.0fpx; height: %.0fpx"], width, height]);
187 [size_ setAttribute:@"style" value:value];
188 [value release];
189
190 [size_ appendChild:text_];
191 }
192
193 - (BOOL) _webPrepareContextForTextDrawing:(BOOL)drawing {
194 WebThreadLock();
195
196 if (document_ == nil) {
197 WebFrame *frame([view_ mainFrame]);
198
199 document_ = [[frame DOMDocument] retain];
200 if (document_ == nil) {
201 NSLog(@"*** ERROR: no DOM document in text-drawing webview");
202 return NO;
203 }
204
205 text_ = [[document_ getElementById:@"text"] retain];
206 size_ = [[document_ getElementById:@"size"] retain];
207
208 if (text_ == nil || size_ == nil) {
209 NSLog(@"*** ERROR: cannot find DOM element required for text drawing");
210 return NO;
211 }
212 }
213
214 context_ = NULL;
215
216 if (!drawing)
217 context_ = NULL;
218 else {
219 context_ = WKGetCurrentGraphicsContext();
220 if (context_ == NULL) {
221 NSLog(@"*** ERROR: no CGContext set for drawing");
222 return NO;
223 }
224 }
225
226 return YES;
227 }
228
229 - (void) drawMarkup:(NSString *)markup atPoint:(CGPoint)point {
230 [self drawMarkup:markup inRect:CGRectMake(point.x, point.y, 65535, 65535)];
231 }
232
233 - (void) drawMarkup:(NSString *)markup inRect:(CGRect)rect {
234 WebThreadLock();
235
236 if (![self _webPrepareContextForTextDrawing:YES])
237 return;
238
239 [text_ setInnerHTML:markup];
240 [text_ removeAttribute:@"style"];
241
242 NSString *value([[NSString alloc] initWithFormat:[self _styleFormatString:@"width: %.0fpx; height: %.0fpx"], CGRectGetWidth(rect), CGRectGetHeight(rect)]);
243 [size_ setAttribute:@"style" value:value];
244 [value release];
245
246 [[view_ mainFrame] forceLayoutAdjustingViewSize:YES];
247
248 [self drawRect:rect];
249 }
250
251 - (void) drawString:(NSString *)string atPoint:(CGPoint)point withStyle:(NSString *)style {
252 [self drawString:string inRect:CGRectMake(point.x, point.y, 65535, 65535) withStyle:style];
253 }
254
255 - (void) drawString:(NSString *)string inRect:(CGRect)rect withStyle:(NSString *)style {
256 WebThreadLock();
257
258 if (![self _webPrepareContextForTextDrawing:YES])
259 return;
260
261 [size_ removeChild:[size_ firstChild]];
262
263 WebFrame *frame([view_ mainFrame]);
264
265 [frame forceLayoutAdjustingViewSize:YES];
266 [text_ setInnerText:string];
267 [self _setupWithStyle:style width:CGRectGetWidth(rect) height:CGRectGetHeight(rect)];
268 [frame forceLayoutAdjustingViewSize:YES];
269
270 [self drawRect:rect];
271 }
272
273 @end