Permalink
Browse files

Merge branch 'master' of https://github.com/Cocoanetics/DTCoreText

  • Loading branch information...
2 parents 3d90bb6 + bcac407 commit 15c0e00bde134ccde07e17b52f038c312c048696 @BrianDoig BrianDoig committed Apr 23, 2012
@@ -219,7 +219,19 @@ - (void)layoutSubviewsInRect:(CGRect)rect
else
{
// individual glyph run
- frameForSubview = oneRun.frame;
+
+ if (attachment)
+ {
+ // frame might be different due to image vertical alignment
+ CGFloat ascender = [attachment ascentForLayout];
+ CGFloat descender = [attachment descentForLayout];
+
+ frameForSubview = CGRectMake(oneRun.frame.origin.x, oneLine.baselineOrigin.y - ascender, oneRun.frame.size.width, ascender+descender);
+ }
+ else
+ {
+ frameForSubview = oneRun.frame;
+ }
}
if (CGRectIsEmpty(frameForSubview))
@@ -660,7 +672,7 @@ - (DTCoreTextLayoutFrame *)layoutFrame
if (_delegateFlags.delegateSupportsNotificationBeforeTextBoxDrawing)
{
- DTAttributedTextContentView *weakself = self;
+ __unsafe_unretained DTAttributedTextContentView *weakself = self;
[_layoutFrame setTextBlockHandler:^(DTTextBlock *textBlock, CGRect frame, CGContextRef context, BOOL *shouldDrawDefaultBackground) {
BOOL result = [weakself->_delegate attributedTextContentView:weakself shouldDrawBackgroundForTextBlock:textBlock frame:frame context:context forLayoutFrame:weakself->_layoutFrame];
@@ -23,4 +23,12 @@
@property (nonatomic, unsafe_unretained) IBOutlet id <DTAttributedTextContentViewDelegate> textDelegate;
+
+/**
+ Scrolls the receiver to the anchor with the given name to the top.
+ @param anchorName The name of the href anchor.
+ @param animated `YES` if the movement should be animated.
+ */
+- (void)scrollToAnchorNamed:(NSString *)anchorName animated:(BOOL)animated;
+
@end
@@ -85,6 +85,25 @@ - (Class)classForContentView
return [DTAttributedTextContentView class];
}
+#pragma mark External Methods
+- (void)scrollToAnchorNamed:(NSString *)anchorName animated:(BOOL)animated
+{
+ NSRange range = [self.contentView.attributedString rangeOfAnchorNamed:anchorName];
+
+ if (range.length != NSNotFound)
+ {
+ // get the line of the first index of the anchor range
+ DTCoreTextLayoutLine *line = [self.contentView.layoutFrame lineContainingIndex:range.location];
+
+ // make sure we don't scroll too far
+ CGFloat maxScrollPos = self.contentSize.height - self.bounds.size.height + self.contentInset.bottom + self.contentInset.top;
+ CGFloat scrollPos = MIN(line.frame.origin.y, maxScrollPos);
+
+ // scroll
+ [self setContentOffset:CGPointMake(0, scrollPos) animated:animated];
+ }
+}
+
#pragma mark Notifications
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
@@ -95,7 +114,6 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
}
}
-
#pragma mark Properties
- (DTAttributedTextContentView *)contentView
{
@@ -28,11 +28,21 @@ @implementation DTCSSStylesheet
+ (DTCSSStylesheet *)defaultStyleSheet
{
- // get the data from the external symbol
- NSData *data = [NSData dataWithBytes:default_css length:default_css_len];
- NSString *cssString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+ static DTCSSStylesheet *defaultDTCSSStylesheet = nil;
+ if (defaultDTCSSStylesheet != nil) {
+ return defaultDTCSSStylesheet;
+ }
- return [[DTCSSStylesheet alloc] initWithStyleBlock:cssString];
+ @synchronized(self) {
+ if (defaultDTCSSStylesheet == nil) {
+ // get the data from the external symbol
+ NSData *data = [NSData dataWithBytes:default_css length:default_css_len];
+ NSString *cssString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+
+ defaultDTCSSStylesheet = [[DTCSSStylesheet alloc] initWithStyleBlock:cssString];
+ }
+ }
+ return defaultDTCSSStylesheet;
}
- (id)initWithStyleBlock:(NSString *)css
@@ -0,0 +1,30 @@
+//
+// DTCompatibility.h
+// DTCoreText
+//
+// Created by Oliver Letterer on 09.04.12.
+// Copyright (c) 2012 Drobnik.com. All rights reserved.
+//
+
+// DTColor is UIColor on iOS, NSColor on Mac
+#if TARGET_OS_IPHONE
+@compatibility_alias DTColor UIColor;
+#else
+@compatibility_alias DTColor NSColor;
+#endif
+
+// DTImage is UIImage on iOS, NSImage on Mac
+#if TARGET_OS_IPHONE
+@compatibility_alias DTImage UIImage;
+#else
+@compatibility_alias DTImage NSImage;
+#endif
+
+// DTEdgeInsets is UIEdgeInsets on iOS, NSEdgeInsets on Mac
+#if TARGET_OS_IPHONE
+#define DTEdgeInsets UIEdgeInsets
+#define DTEdgeInsetsMake(a, b, c, d) UIEdgeInsetsMake(a, b, c, d)
+#else
+#define DTEdgeInsets NSEdgeInsets
+#define DTEdgeInsetsMake(a, b, c, d) NSEdgeInsetsMake(a, b, c, d)
+#endif
@@ -4,34 +4,11 @@
// global constants
#import "DTCoreTextConstants.h"
-
-// DTColor is UIColor on iOS, NSColor on Mac
-#if TARGET_OS_IPHONE
-@compatibility_alias DTColor UIColor;
-#else
-@compatibility_alias DTColor NSColor;
-#endif
+#import "DTCompatibility.h"
#import "DTColor+HTML.h"
-
-// DTImage is UIImage on iOS, NSImage on Mac
-#if TARGET_OS_IPHONE
-@compatibility_alias DTImage UIImage;
-#else
-@compatibility_alias DTImage NSImage;
-#endif
-
#import "DTImage+HTML.h"
-// DTEdgeInsets is UIEdgeInsets on iOS, NSEdgeInsets on Mac
-#if TARGET_OS_IPHONE
-#define DTEdgeInsets UIEdgeInsets
-#define DTEdgeInsetsMake(a, b, c, d) UIEdgeInsetsMake(a, b, c, d)
-#else
-#define DTEdgeInsets NSEdgeInsets
-#define DTEdgeInsetsMake(a, b, c, d) NSEdgeInsetsMake(a, b, c, d)
-#endif
-
// common utilities
#import "CGUtils.h"
@@ -30,6 +30,7 @@ extern NSString *DTDefaultStyleSheet;
extern NSString *DTTextListsAttribute;
extern NSString *DTAttachmentParagraphSpacingAttribute;
extern NSString *DTLinkAttribute;
+extern NSString *DTAnchorAttribute;
extern NSString *DTGUIDAttribute;
extern NSString *DTHeaderLevelAttribute;
extern NSString *DTPreserveNewlinesAttribute;
@@ -27,6 +27,7 @@
NSString *DTTextListsAttribute = @"DTTextLists";
NSString *DTAttachmentParagraphSpacingAttribute = @"DTAttachmentParagraphSpacing";
NSString *DTLinkAttribute = @"DTLink";
+NSString *DTAnchorAttribute = @"DTAnchor";
NSString *DTGUIDAttribute = @"DTGUID";
NSString *DTHeaderLevelAttribute = @"DTHeaderLevel";
NSString *DTPreserveNewlinesAttribute = @"DTPreserveNewlines";
@@ -7,7 +7,10 @@
//
#import "DTCoreTextFontDescriptor.h"
+
+#if TARGET_OS_IPHONE
#import "UIDevice+DTVersion.h"
+#endif
static NSCache *_fontCache = nil;
static NSMutableDictionary *_fontOverrides = nil;
@@ -63,13 +66,15 @@ + (void)initialize
}
}
- // workaround for iOS 5.0 bug: global font cascade table has incorrect bold font for Chinese characters in Chinese locale
+#if TARGET_OS_IPHONE
+ // workaround for iOS 5.x bug: global font cascade table has incorrect bold font for Chinese characters in Chinese locale
DTVersion version = [[UIDevice currentDevice] osVersion];
- if (version.major==5 && version.minor == 0)
+ if (version.major>4)
{
_needsChineseFontCascadeFix = YES;
}
+#endif
}
+ (void)setSmallCapsFontName:(NSString *)fontName forFontFamily:(NSString *)fontFamily bold:(BOOL)bold italic:(BOOL)italic
@@ -975,8 +975,12 @@ - (void)drawInContext:(CGContextRef)context drawImages:(BOOL)drawImages
{
DTImage *image = (id)attachment.contents;
+ // frame might be different due to image vertical alignment
+ CGFloat ascender = [attachment ascentForLayout];
+ CGFloat descender = [attachment descentForLayout];
+
CGPoint origin = oneRun.frame.origin;
- origin.y = self.frame.size.height - origin.y - oneRun.ascent;
+ origin.y = self.frame.size.height - origin.y - ascender - descender;
CGRect flippedRect = CGRectMake(roundf(origin.x), roundf(origin.y), attachment.displaySize.width, attachment.displaySize.height);
CGContextDrawImage(context, flippedRect, image.CGImage);
@@ -42,6 +42,23 @@ + (DTCoreTextParagraphStyle *)defaultParagraphStyle
return [[DTCoreTextParagraphStyle alloc] init];
}
++ (NSString *)niceKeyFromParagraghStyle:(CTParagraphStyleRef)ctParagraphStyle {
+
+ // this is naughty: CTParagraphStyle has a description
+ NSString *key = [(__bridge id)ctParagraphStyle description];
+
+ NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"0x[0123456789abcdef]{1,8}"
+ options:NSRegularExpressionCaseInsensitive
+ error:nil];
+
+ NSString *newKey = [regex stringByReplacingMatchesInString:key
+ options:0
+ range:NSMakeRange(0, [key length])
+ withTemplate:@""];
+
+ return newKey;
+}
+
+ (DTCoreTextParagraphStyle *)paragraphStyleWithCTParagraphStyle:(CTParagraphStyleRef)ctParagraphStyle
{
DTCoreTextParagraphStyle *returnParagraphStyle = NULL;
@@ -58,9 +75,7 @@ + (DTCoreTextParagraphStyle *)paragraphStyleWithCTParagraphStyle:(CTParagraphSty
dispatch_semaphore_wait(selfLock, DISPATCH_TIME_FOREVER);
{
- // this is naughty: CTParagraphStyle has a description
- NSString *key = [(__bridge id)ctParagraphStyle description];
-
+ NSString *key = [self niceKeyFromParagraghStyle:ctParagraphStyle];
returnParagraphStyle = [_paragraphStyleCache objectForKey:key];
if (!returnParagraphStyle)
@@ -419,6 +419,10 @@ - (void)_registerTagStartHandlers
}
currentTag.link = link;
+
+
+ // the name attribute of A becomes an anchor
+ currentTag.anchorName = [currentTag attributeForKey:@"name"];
};
[_tagStartHandlers setObject:[aBlock copy] forKey:@"a"];
@@ -738,6 +742,9 @@ - (void)_registerTagEndHandlers
// because we have multiple paragraph styles per paragraph still, we need to extend towards the begin of the paragraph
NSRange paragraphRange = [[tmpString string] rangeOfParagraphAtIndex:effectiveRange.location];
+ // iOS 4.3 bug: need to remove previous attribute or else CTParagraphStyleRef leaks
+ [tmpString removeAttribute:(id)kCTParagraphStyleAttributeName range:paragraphRange];
+
[tmpString addAttribute:(id)kCTParagraphStyleAttributeName value:CFBridgingRelease(newParagraphStyle) range:paragraphRange];
}
}
@@ -41,6 +41,7 @@ typedef enum
@property (nonatomic, copy) DTCoreTextParagraphStyle *paragraphStyle;
@property (nonatomic, strong) DTTextAttachment *textAttachment;
@property (nonatomic, copy) NSURL *link;
+@property (nonatomic, copy) NSString *anchorName;
@property (nonatomic, strong) DTColor *textColor;
@property (nonatomic, strong) DTColor *backgroundColor;
@property (nonatomic, copy) NSString *tagName;
@@ -29,6 +29,7 @@ @implementation DTHTMLElement
DTTextAttachment *_textAttachment;
DTTextAttachmentVerticalAlignment _textAttachmentAlignment;
NSURL *_link;
+ NSString *_anchorName;
DTColor *_textColor;
DTColor *backgroundColor;
@@ -149,6 +150,12 @@ - (NSDictionary *)attributesDictionary
[tmpDict setObject:_linkGUID forKey:DTGUIDAttribute];
}
+ // add anchor
+ if (_anchorName)
+ {
+ [tmpDict setObject:_anchorName forKey:DTAnchorAttribute];
+ }
+
// add strikout if applicable
if (strikeOut)
{
@@ -899,6 +906,7 @@ - (id)copyWithZone:(NSZone *)zone
newObject.shadows = self.shadows;
newObject.link = self.link; // copy
+ newObject.anchorName = self.anchorName; // copy
newObject.linkGUID = _linkGUID; // transfer the GUID
newObject.preserveNewlines = self.preserveNewlines;
@@ -1010,6 +1018,7 @@ - (void)setLink:(NSURL *)link
@synthesize tagName;
@synthesize text;
@synthesize link = _link;
+@synthesize anchorName = _anchorName;
@synthesize underlineStyle;
@synthesize textAttachment = _textAttachment;
@synthesize tagContentInvisible;
@@ -6,7 +6,7 @@
// Copyright (c) 2012 Drobnik.com. All rights reserved.
//
-#import "DTCoreText.h"
+#import "DTCompatibility.h"
/**
Class that represents a block of text with attributes like padding or a background color.
@@ -7,6 +7,7 @@
//
#import "DTTextBlock.h"
+#import "DTCoreText.h"
@implementation DTTextBlock
{
@@ -65,9 +65,17 @@
- (NSRange)rangeOfTextBlock:(DTTextBlock *)textBlock atIndex:(NSUInteger)location;
/**
- @name Converting to Other Representations
+ Returns the range of the given href anchor.
+
+ @param list The text block.
+ @param anchorName The name of the anchor.
+ @returns The range of the given anchor.
*/
+- (NSRange)rangeOfAnchorNamed:(NSString *)anchorName;
+/**
+ @name Converting to Other Representations
+ */
/**
Encodes the receiver into a generic HTML prepresentation.
Oops, something went wrong.

0 comments on commit 15c0e00

Please sign in to comment.