diff --git a/Core/Externals/DTFoundation b/Core/Externals/DTFoundation index abbad03e3..a76d5a964 160000 --- a/Core/Externals/DTFoundation +++ b/Core/Externals/DTFoundation @@ -1 +1 @@ -Subproject commit abbad03e3464d17bb7b22ce0800fb3c686a77b19 +Subproject commit a76d5a964f94da3a99e76052a34353ff2daff3ae diff --git a/Core/Source/DTCoreTextConstants.h b/Core/Source/DTCoreTextConstants.h index 07f198dc6..0cb4a048a 100644 --- a/Core/Source/DTCoreTextConstants.h +++ b/Core/Source/DTCoreTextConstants.h @@ -70,6 +70,7 @@ extern NSString * const DTHorizontalRuleStyleAttribute; extern NSString * const DTTextBlocksAttribute; extern NSString * const DTFieldAttribute; extern NSString * const DTCustomAttributesAttribute; +extern NSString * const DTAscentMultiplierAttribute; // field constants diff --git a/Core/Source/DTCoreTextConstants.m b/Core/Source/DTCoreTextConstants.m index 9d1bdb3a7..2a9bbd8c0 100644 --- a/Core/Source/DTCoreTextConstants.m +++ b/Core/Source/DTCoreTextConstants.m @@ -43,6 +43,7 @@ NSString * const DTTextBlocksAttribute = @"DTTextBlocks"; NSString * const DTFieldAttribute = @"DTField"; NSString * const DTCustomAttributesAttribute = @"DTCustomAttributes"; +NSString * const DTAscentMultiplierAttribute = @"DTAscentMultiplierAttribute"; // field constants NSString * const DTListPrefixField = @"{listprefix}"; diff --git a/Core/Source/DTCoreTextLayoutFrame.h b/Core/Source/DTCoreTextLayoutFrame.h index 4e27a531d..17b08b0ec 100644 --- a/Core/Source/DTCoreTextLayoutFrame.h +++ b/Core/Source/DTCoreTextLayoutFrame.h @@ -263,6 +263,11 @@ typedef enum */ - (CGPoint)baselineOriginToPositionLine:(DTCoreTextLayoutLine *)line afterLine:(DTCoreTextLayoutLine *)previousLine __attribute__((deprecated("use use -[baselineOriginToPositionLine:afterLine:algorithm:] instead")));; +/** + The ratio to decide when to create a justified line + */ +@property (nonatomic, readwrite) CGFloat justifyRatio; + /** @name Text Attachments */ diff --git a/Core/Source/DTCoreTextLayoutFrame.m b/Core/Source/DTCoreTextLayoutFrame.m index 17eec2277..3a7dce46a 100644 --- a/Core/Source/DTCoreTextLayoutFrame.m +++ b/Core/Source/DTCoreTextLayoutFrame.m @@ -78,6 +78,8 @@ - (id)initWithFrame:(CGRect)frame layouter:(DTCoreTextLayouter *)layouter range: // Strange, should have gotten a valid framesetter return nil; } + + _justifyRatio = 0.6f; } return self; @@ -486,6 +488,7 @@ - (void)_buildLinesWithTypesetter (_numberLinesFitInFrame>0 && _numberLinesFitInFrame==[typesetLines count]+1)); CTLineRef line; + BOOL isHyphenatedString = NO; if (!shouldTruncateLine) { @@ -498,6 +501,7 @@ - (void)_buildLinesWithTypesetter NSRange replaceRange = NSMakeRange(hyphenatedString.length - 1, 1); [hyphenatedString replaceCharactersInRange:replaceRange withString:@"-"]; line = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)hyphenatedString); + isHyphenatedString = YES; } else { @@ -607,14 +611,19 @@ - (void)_buildLinesWithTypesetter BOOL isAtEndOfParagraph = (currentParagraphRange.location+currentParagraphRange.length <= lineRange.location+lineRange.length || [[_attributedStringFragment string] characterAtIndex:lineRange.location+lineRange.length-1]==0x2028); - // only justify if not last line, not
, and if the line width is longer than 60% of the frame + // only justify if not last line, not
, and if the line width is longer than _justifyRatio of the frame // avoids over-stretching - if( !isAtEndOfParagraph && (currentLineWidth > 0.60 * _frame.size.width) ) + if( !isAtEndOfParagraph && (currentLineWidth > _justifyRatio * _frame.size.width) ) { // create a justified line and replace the current one with it CTLineRef justifiedLine = CTLineCreateJustifiedLine(line, 1.0f, availableSpace); - CFRelease(line); - line = justifiedLine; + + // CTLineCreateJustifiedLine sometimes fails if the line ends with 0x00AD (soft hyphen) and contains cyrillic chars + if (justifiedLine) + { + CFRelease(line); + line = justifiedLine; + } } if (isRTL) @@ -633,7 +642,8 @@ - (void)_buildLinesWithTypesetter } // wrap it - DTCoreTextLayoutLine *newLine = [[DTCoreTextLayoutLine alloc] initWithLine:line]; + DTCoreTextLayoutLine *newLine = [[DTCoreTextLayoutLine alloc] initWithLine:line + stringLocationOffset:isHyphenatedString ? lineRange.location : 0]; newLine.writingDirectionIsRightToLeft = isRTL; CFRelease(line); @@ -1205,16 +1215,19 @@ - (void)drawInContext:(CGContextRef)context options:(DTCoreTextLayoutFrameDrawin NSInteger superscriptStyle = [[oneRun.attributes objectForKey:(id)kCTSuperscriptAttributeName] integerValue]; + NSNumber *ascentMultiplier = [oneRun.attributes objectForKey:(id)DTAscentMultiplierAttribute]; + + switch (superscriptStyle) { case 1: { - textPosition.y += oneRun.ascent * 0.47f; + textPosition.y += oneRun.ascent * (ascentMultiplier ? [ascentMultiplier floatValue] : 0.47f); break; } case -1: { - textPosition.y -= oneRun.ascent * 0.25f; + textPosition.y -= oneRun.ascent * (ascentMultiplier ? [ascentMultiplier floatValue] : 0.25f); break; } default: @@ -1663,9 +1676,20 @@ - (void)setTruncationString:(NSAttributedString *)truncationString } } +- (void) setJustifyRatio:(CGFloat)justifyRatio +{ + if( _justifyRatio != justifyRatio ) + { + _justifyRatio = justifyRatio; + // clear lines cache + _lines = nil; + } +} + @synthesize frame = _frame; @synthesize lines = _lines; @synthesize paragraphRanges = _paragraphRanges; @synthesize textBlockHandler = _textBlockHandler; +@synthesize justifyRatio = _justifyRatio; @end diff --git a/Core/Source/DTCoreTextLayoutLine.h b/Core/Source/DTCoreTextLayoutLine.h index fdff142a3..becc63919 100644 --- a/Core/Source/DTCoreTextLayoutLine.h +++ b/Core/Source/DTCoreTextLayoutLine.h @@ -36,6 +36,15 @@ */ - (id)initWithLine:(CTLineRef)line; +/** + Creates a layout line from a given `CTLine` + @param line The Core Text line to wrap + @param stringLocationOffset Offset to modify internal string location to get actual location + @returns A prepared layout line + */ + +- (id)initWithLine:(CTLineRef)line stringLocationOffset:(NSInteger)stringLocationOffset; + /** @name Drawing Layout Lines */ diff --git a/Core/Source/DTCoreTextLayoutLine.m b/Core/Source/DTCoreTextLayoutLine.m index ef0e9890d..a21ff6672 100644 --- a/Core/Source/DTCoreTextLayoutLine.m +++ b/Core/Source/DTCoreTextLayoutLine.m @@ -49,14 +49,21 @@ @implementation DTCoreTextLayoutLine } - (id)initWithLine:(CTLineRef)line +{ + return [self initWithLine:line stringLocationOffset:0]; +} + +- (id)initWithLine:(CTLineRef)line stringLocationOffset:(NSInteger)stringLocationOffset { if ((self = [super init])) { _line = line; CFRetain(_line); - + // writing direction _needsToDetectWritingDirection = YES; + + _stringLocationOffset = stringLocationOffset; } return self; } diff --git a/Core/Source/DTCoreTextParagraphStyle.h b/Core/Source/DTCoreTextParagraphStyle.h index d82d04ac8..b19354a8f 100644 --- a/Core/Source/DTCoreTextParagraphStyle.h +++ b/Core/Source/DTCoreTextParagraphStyle.h @@ -191,7 +191,7 @@ The distance in points from the margin of a text container to the end of lines. */ /** - Text lists containing the paragraph, nested from outermost to innermost, to array. + Text lists containing the paragraph, nested from outermost to innermost. Each text list is a DTCSSListStyle object. */ @property (nonatomic, copy) NSArray *textLists; @@ -202,7 +202,7 @@ The distance in points from the margin of a text container to the end of lines. */ /** - Text lists containing the paragraph, nested from outermost to innermost, to array. + Text blocks containing the paragraph, nested from outermost to innermost, to array. Each text block is a DTTextBlock object. */ @property (nonatomic, copy) NSArray *textBlocks; diff --git a/DTCoreText.podspec b/DTCoreText.podspec index bcf7d839b..2d6470a66 100644 --- a/DTCoreText.podspec +++ b/DTCoreText.podspec @@ -5,9 +5,9 @@ Pod::Spec.new do |spec| spec.license = 'BSD' spec.source = { :git => 'https://github.com/Cocoanetics/DTCoreText.git', :tag => spec.version.to_s } spec.source_files = 'Core/Source/*.{h,m,c}' - spec.dependency 'DTFoundation/Core', '~>1.4.3' - spec.dependency 'DTFoundation/UIKit', '~>1.4.3' - spec.dependency 'DTFoundation/DTHMLParser', '~>1.4.3' + spec.dependency 'DTFoundation/Core', '~>1.4.5' + spec.dependency 'DTFoundation/UIKit', '~>1.4.5' + spec.dependency 'DTFoundation/DTHTMLParser', '~>1.4.5' spec.frameworks = 'MediaPlayer', 'QuartzCore', 'CoreText', 'CoreGraphics', 'ImageIO' spec.requires_arc = true spec.homepage = 'https://github.com/Cocoanetics/DTCoreText' diff --git a/DTCoreText.xcodeproj/project.pbxproj b/DTCoreText.xcodeproj/project.pbxproj index 1f1d0c5d5..6563c7836 100644 --- a/DTCoreText.xcodeproj/project.pbxproj +++ b/DTCoreText.xcodeproj/project.pbxproj @@ -668,6 +668,13 @@ /* End PBXBuildRule section */ /* Begin PBXContainerItemProxy section */ + A70C4FE617AA7E3100000DF5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A7E383AB160DFEA700CF72D6 /* DTFoundation.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = A79D999C1792D1F50082BC06; + remoteInfo = "DTAWS (iOS)"; + }; A70E62F616C253C6009B47BF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = A7E383AB160DFEA700CF72D6 /* DTFoundation.xcodeproj */; @@ -1648,6 +1655,7 @@ A7E383B9160DFEA800CF72D6 /* libDTFoundation.a */, A7B4E2D21686FDB300717707 /* UnitTests.octest */, A7B4E2D41686FDB300717707 /* libDTFoundation_Mac.a */, + A70C4FE717AA7E3100000DF5 /* libDTAWS.a */, A7B4E2D61686FDB300717707 /* libDTHTMLParser_iOS.a */, A7B4E2D81686FDB300717707 /* libDTHTMLParser_Mac.a */, A7B4E2DA1686FDB300717707 /* libDTZipArchive_iOS.a */, @@ -2109,6 +2117,13 @@ /* End PBXProject section */ /* Begin PBXReferenceProxy section */ + A70C4FE717AA7E3100000DF5 /* libDTAWS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libDTAWS.a; + remoteRef = A70C4FE617AA7E3100000DF5 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; A74F6FD316DB9AF600C12307 /* libDTUTI_Mac.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -2878,6 +2893,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_THUMB_SUPPORT = NO; HEADER_SEARCH_PATHS = /usr/include/libxml2; + OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = DTCoreText; PUBLIC_HEADERS_FOLDER_PATH = ../../DTCoreText; SKIP_INSTALL = YES; @@ -2897,6 +2913,7 @@ GCC_PREFIX_HEADER = "Core/DTCoreText-Prefix.pch"; GCC_THUMB_SUPPORT = NO; HEADER_SEARCH_PATHS = /usr/include/libxml2; + OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = DTCoreText; PUBLIC_HEADERS_FOLDER_PATH = ../../DTCoreText; SKIP_INSTALL = YES;