]> git.saurik.com Git - winterboard.git/commitdiff
Initial implementation of WBMarkup.
authorJay Freeman (saurik) <saurik@saurik.com>
Mon, 17 Oct 2011 08:33:58 +0000 (08:33 +0000)
committerJay Freeman (saurik) <saurik@saurik.com>
Mon, 17 Oct 2011 08:33:58 +0000 (08:33 +0000)
Library.mm
WBMarkup.h [new file with mode: 0644]
WBMarkup.mm [new file with mode: 0644]
makefile

index cd2e5d07d92d93d380407fa1de61269e050e5d07..b35a2eaae8b1c045ddbc430a2fec289a43deea45 100644 (file)
@@ -103,6 +103,8 @@ bool _itv;
 
 #include <sys/sysctl.h>
 
+#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 (file)
index 0000000..24645e0
--- /dev/null
@@ -0,0 +1,44 @@
+#include <Foundation/Foundation.h>
+#include <CoreGraphics/CoreGraphics.h>
+
+@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 (file)
index 0000000..9550114
--- /dev/null
@@ -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:@"<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];
+    } 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
index ee9252f933d66f7db65868244b43e92f7a124344..28ac0150dad13dc088011fd76af8ef4d6ee9d714 100644 (file)
--- 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