From 2de63e6327bc0d8d788881d9bf04132be07b2001 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Mon, 17 Oct 2011 08:33:58 +0000 Subject: [PATCH] Initial implementation of WBMarkup. --- Library.mm | 2 + WBMarkup.h | 44 +++++++++ WBMarkup.mm | 270 ++++++++++++++++++++++++++++++++++++++++++++++++++++ makefile | 4 +- 4 files changed, 318 insertions(+), 2 deletions(-) create mode 100644 WBMarkup.h create mode 100644 WBMarkup.mm diff --git a/Library.mm b/Library.mm index cd2e5d0..b35a2ea 100644 --- a/Library.mm +++ b/Library.mm @@ -103,6 +103,8 @@ bool _itv; #include +#include "WBMarkup.h" + extern "C" void __clear_cache (char *beg, char *end); @protocol WinterBoard diff --git a/WBMarkup.h b/WBMarkup.h new file mode 100644 index 0000000..24645e0 --- /dev/null +++ b/WBMarkup.h @@ -0,0 +1,44 @@ +#include +#include + +@class DOMDocument; +@class DOMElement; + +@class WAKWindow; +@class WebView; + +@interface WBMarkup : NSObject { + /*04*/ WebView *view_; + /*08*/ DOMDocument *document_; + /*0C*/ WAKWindow *window_; + /*10*/ DOMElement *text_; + /*14*/ DOMElement *size_; + /*18*/ CGContextRef context_; + /*1C*/ CGPoint origin_; +} + ++ (BOOL) isSharedMarkupCreated; ++ (WBMarkup *) sharedMarkup; + +- (id) init; +- (void) dealloc; + +- (WebView *) _webView; + +- (void) setStringDrawingOrigin:(CGPoint)origin; +- (void) clearStringDrawingOrigin; + +- (CGSize) sizeOfMarkup:(NSString *)markup forWidth:(float)width; +- (CGSize) sizeOfString:(NSString *)string withStyle:(NSString *)style forWidth:(float)width; + +- (NSString *) _styleFormatString:(NSString *)style; +- (void) _setupWithStyle:(NSString *)style width:(float)width height:(float)height; +- (BOOL) _webPrepareContextForTextDrawing:(BOOL)drawing; + +- (void) drawMarkup:(NSString *)markup atPoint:(CGPoint)point; +- (void) drawMarkup:(NSString *)markup inRect:(CGRect)rect; + +- (void) drawString:(NSString *)string atPoint:(CGPoint)point withStyle:(NSString *)style; +- (void) drawString:(NSString *)string inRect:(CGRect)rect withStyle:(NSString *)style; + +@end diff --git a/WBMarkup.mm b/WBMarkup.mm new file mode 100644 index 0000000..9550114 --- /dev/null +++ b/WBMarkup.mm @@ -0,0 +1,270 @@ +#include "WBMarkup.h" + +@class WKView; + +extern "C" { + void WebThreadLock(); + CGContextRef WKGetCurrentGraphicsContext(); + void WKViewLockFocus(WKView *); + void WKViewUnlockFocus(WKView *); + void WKViewDisplayRect(WKView *, CGRect); +} + +@interface DOMElement : NSObject +- (void) setInnerHTML:(NSString *)value; +- (void) setInnerText:(NSString *)value; +- (void) setAttribute:(NSString *)name value:(NSString *)value; +- (void) removeAttribute:(NSString *)name; +- (DOMElement *) firstChild; +- (void) appendChild:(DOMElement *)child; +- (void) removeChild:(DOMElement *)child; +- (void) setScrollXOffset:(float)x scrollYOffset:(float)y; +@end + +@interface DOMDocument : NSObject +- (DOMElement *) getElementById:(NSString *)id; +@end + +@interface WebPreferences : NSObject +- (id) initWithIdentifier:(NSString *)identifier; +- (void) setPlugInsEnabled:(BOOL)value; +@end + +@interface WebFrameView : NSObject +- (void) setAllowsScrolling:(BOOL)value; +@end + +@interface WebFrame : NSObject +- (WebFrameView *) frameView; +- (void) _setLoadsSynchronously:(BOOL)value; +- (void) loadHTMLString:(NSString *)string baseURL:(id)url; +- (void) forceLayoutAdjustingViewSize:(BOOL)adjust; +- (CGSize) renderedSizeOfNode:(DOMElement *)node constrainedToWidth:(float)width; +- (DOMDocument *) DOMDocument; +@end + +@interface WebView : NSObject +- (id) initWithFrame:(CGRect)frame; +- (WebFrame *) mainFrame; +- (void) setDrawsBackground:(BOOL)value; +- (void) setPreferences:(WebPreferences *)preferences; +- (WKView *) _viewRef; +@end + +@interface WAKWindow : NSObject +- (id) initWithFrame:(CGRect)frame; +- (void) setContentView:(WebView *)view; +@end + +static WBMarkup *SharedMarkup_; + +@implementation WBMarkup + ++ (BOOL) isSharedMarkupCreated { + return SharedMarkup_ != nil; +} + ++ (WBMarkup *) sharedMarkup { + if (SharedMarkup_ == nil) + SharedMarkup_ = [[WBMarkup alloc] init]; + return SharedMarkup_; +} + +- (id) init { + if ((self = [super init]) != nil) { + WebThreadLock(); + + SharedMarkup_ = self; + + view_ = [[WebView alloc] initWithFrame:CGRectMake(0, 0, 640, 5000)]; + [view_ setDrawsBackground:NO]; + + WebPreferences *preferences([[WebPreferences alloc] initWithIdentifier:@"com.apple.webkit.webmarkup"]); + [preferences setPlugInsEnabled:NO]; + [view_ setPreferences:preferences]; + [preferences release]; + + window_ = [[WAKWindow alloc] initWithFrame:CGRectMake(0, 0, 640, 5000)]; + [window_ setContentView:view_]; + + WebFrame *frame([view_ mainFrame]); + [[frame frameView] setAllowsScrolling:NO]; + [frame _setLoadsSynchronously:YES]; + + [frame loadHTMLString:@"
" baseURL:nil]; + } return self; +} + +- (void) dealloc { + [window_ release]; + [view_ release]; + [super dealloc]; +} + +- (WebView *) _webView { + return view_; +} + +- (void) setStringDrawingOrigin:(CGPoint)origin { + origin_ = origin; +} + +- (void) clearStringDrawingOrigin { + origin_ = CGPointZero; +} + +- (CGSize) sizeOfMarkup:(NSString *)markup forWidth:(float)width { + WebThreadLock(); + + if (![self _webPrepareContextForTextDrawing:NO]) + return CGSizeZero; + + [text_ setInnerHTML:markup]; + [text_ removeAttribute:@"style"]; + + NSString *value([[NSString alloc] initWithFormat:[self _styleFormatString:@"width: %.0fpx; height: 5000px"], width]); + [size_ setAttribute:@"style" value:value]; + [value release]; + + [[view_ mainFrame] forceLayoutAdjustingViewSize:YES]; + return [[view_ mainFrame] renderedSizeOfNode:text_ constrainedToWidth:width]; +} + +- (CGSize) sizeOfString:(NSString *)string withStyle:(NSString *)style forWidth:(float)width { + WebThreadLock(); + + if (![self _webPrepareContextForTextDrawing:NO]) + return CGSizeZero; + + [size_ removeChild:[size_ firstChild]]; + + WebFrame *frame([view_ mainFrame]); + + [frame forceLayoutAdjustingViewSize:YES]; + [text_ setInnerText:string]; + [self _setupWithStyle:style width:width height:5000]; + [frame forceLayoutAdjustingViewSize:YES]; + + return [[view_ mainFrame] renderedSizeOfNode:text_ constrainedToWidth:width]; +} + +- (NSString *) _styleFormatString:(NSString *)style { + return style; +} + +- (void) _setupWithStyle:(NSString *)style width:(float)width height:(float)height { + WebThreadLock(); + + if (style != nil && [style length] != 0) + [text_ setAttribute:@"style" value:style]; + else + [text_ removeAttribute:@"style"]; + + NSString *value([[NSString alloc] initWithFormat:[self _styleFormatString:@"width: %.0fpx; height: %.0fpx"], width, height]); + [size_ setAttribute:@"style" value:value]; + [value release]; + + [size_ appendChild:text_]; +} + +- (BOOL) _webPrepareContextForTextDrawing:(BOOL)drawing { + WebThreadLock(); + + if (document_ == nil) { + WebFrame *frame([view_ mainFrame]); + + document_ = [[frame DOMDocument] retain]; + if (document_ == nil) { + NSLog(@"*** ERROR: no DOM document in text-drawing webview"); + return NO; + } + + text_ = [[document_ getElementById:@"text"] retain]; + size_ = [[document_ getElementById:@"size"] retain]; + + if (text_ == nil || size_ == nil) { + NSLog(@"*** ERROR: cannot find DOM element required for text drawing"); + return NO; + } + } + + context_ = NULL; + + if (!drawing) + context_ = NULL; + else { + context_ = WKGetCurrentGraphicsContext(); + if (context_ == NULL) { + NSLog(@"*** ERROR: no CGContext set for drawing"); + return NO; + } + } + + return YES; +} + +- (void) drawMarkup:(NSString *)markup atPoint:(CGPoint)point { + [self drawMarkup:markup inRect:CGRectMake(point.x, point.y, 65535, 65535)]; +} + +- (void) drawMarkup:(NSString *)markup inRect:(CGRect)rect { + WebThreadLock(); + + if (![self _webPrepareContextForTextDrawing:YES]) + return; + + [text_ setInnerHTML:markup]; + [text_ removeAttribute:@"style"]; + + NSString *value([[NSString alloc] initWithFormat:[self _styleFormatString:@"width: %.0fpx; height: %.0fpx"], CGRectGetWidth(rect), CGRectGetHeight(rect)]); + [size_ setAttribute:@"style" value:value]; + [value release]; + + [[view_ mainFrame] forceLayoutAdjustingViewSize:YES]; + + [text_ setScrollXOffset:origin_.x scrollYOffset:origin_.y]; + + WKView *view([view_ _viewRef]); + + CGContextSaveGState(context_); { + CGContextTranslateCTM(context_, rect.origin.x, rect.origin.y); + + WKViewLockFocus(view); { + WKViewDisplayRect(view, CGRectMake(0, 0, rect.origin.x, rect.origin.y)); + } WKViewUnlockFocus(view); + } CGContextRestoreGState(context_); +} + +- (void) drawString:(NSString *)string atPoint:(CGPoint)point withStyle:(NSString *)style { + [self drawString:string inRect:CGRectMake(point.x, point.y, 65535, 65535) withStyle:style]; +} + +- (void) drawString:(NSString *)string inRect:(CGRect)rect withStyle:(NSString *)style { + WebThreadLock(); + + if (![self _webPrepareContextForTextDrawing:YES]) + return; + + [size_ removeChild:[size_ firstChild]]; + + WebFrame *frame([view_ mainFrame]); + + [frame forceLayoutAdjustingViewSize:YES]; + [text_ setInnerText:string]; + [self _setupWithStyle:style width:CGRectGetWidth(rect) height:CGRectGetHeight(rect)]; + [frame forceLayoutAdjustingViewSize:YES]; + + [text_ setScrollXOffset:origin_.x scrollYOffset:origin_.y]; + + WKView *view([view_ _viewRef]); + + CGContextSaveGState(context_); { + CGContextTranslateCTM(context_, rect.origin.x, rect.origin.y); + + WKViewLockFocus(view); { + WKViewDisplayRect(view, CGRectMake(0, 0, rect.size.width, rect.size.height)); + } WKViewUnlockFocus(view); + } CGContextRestoreGState(context_); +} + +@end diff --git a/makefile b/makefile index ee9252f..28ac015 100644 --- a/makefile +++ b/makefile @@ -15,8 +15,8 @@ WinterBoardSettings: Settings.mm makefile $(target)g++ -dynamiclib -g0 -O2 -Wall -o $@ $(filter %.mm,$^) -framework UIKit -framework CoreFoundation -framework Foundation -lobjc -framework CoreGraphics -framework Preferences -F$(PKG_ROOT)/System/Library/PrivateFrameworks ldid -S $@ -WinterBoard.dylib: Library.mm makefile ../mobilesubstrate/substrate.h - $(target)g++ -dynamiclib -g0 -O2 -Wall -o $@ $(filter %.mm,$^) -framework CoreFoundation -framework Foundation -lobjc -I/apl/inc/iPhoneOS-2.0 -framework CoreGraphics -framework ImageIO -framework GraphicsServices -framework Celestial $(substrate) -framework UIKit -F$(PKG_ROOT)/System/Library/PrivateFrameworks +WinterBoard.dylib: Library.mm WBMarkup.mm WBMarkup.h makefile ../mobilesubstrate/substrate.h + $(target)g++ -dynamiclib -g0 -O2 -Wall -o $@ $(filter %.mm,$^) -framework CoreFoundation -framework Foundation -lobjc -I/apl/inc/iPhoneOS-2.0 -framework CoreGraphics -framework ImageIO -framework GraphicsServices -framework Celestial $(substrate) -framework UIKit -framework WebCore -framework WebKit -F$(PKG_ROOT)/System/Library/PrivateFrameworks ldid -S $@ UIImages: UIImages.mm makefile -- 2.45.2