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