// // MLLabelLayoutManager.m // MLLabel // // Created by molon on 15/6/11. // Copyright (c) 2015年 molon. All rights reserved. // #import "MLLabelLayoutManager.h" @interface MLLabelLayoutManager() @property (nonatomic, assign) CGPoint lastDrawPoint; @end @implementation MLLabelLayoutManager - (void)drawBackgroundForGlyphRange:(NSRange)glyphsToShow atPoint:(CGPoint)origin { self.lastDrawPoint = origin; [super drawBackgroundForGlyphRange:glyphsToShow atPoint:origin]; self.lastDrawPoint = CGPointZero; } - (void)fillBackgroundRectArray:(const CGRect *)rectArray count:(NSUInteger)rectCount forCharacterRange:(NSRange)charRange color:(UIColor *)color { CGContextRef ctx = UIGraphicsGetCurrentContext(); if (!ctx) { [super fillBackgroundRectArray:rectArray count:rectCount forCharacterRange:charRange color:color]; return; } CGContextSaveGState(ctx); { [color setFill]; NSRange glyphRange = [self glyphRangeForCharacterRange:charRange actualCharacterRange:NULL]; CGPoint textOffset = self.lastDrawPoint; NSRange lineRange = NSMakeRange(glyphRange.location, 1); while (NSMaxRange(lineRange)<=NSMaxRange(glyphRange)) { //这里可以防止这行没有用到的区域也绘制上背景色,例如收到word wrap,center alignment影响后每行文字没有占满时候 CGRect lineBounds = [self lineFragmentUsedRectForGlyphAtIndex:lineRange.location effectiveRange:&lineRange]; lineBounds.origin.x += textOffset.x; lineBounds.origin.y += textOffset.y; //找到这行具有背景色文字区域的位置 NSRange glyphRangeInLine = NSIntersectionRange(glyphRange,lineRange); NSRange truncatedGlyphRange = [self truncatedGlyphRangeInLineFragmentForGlyphAtIndex:glyphRangeInLine.location]; if (truncatedGlyphRange.location!=NSNotFound) { //这里的glyphRangeInLine本身可能会带有被省略的区间,而我们下面计算最大行高和最小drawY的实现是不需要考虑省略的区间的,否则也可能计算有误。所以这里我们给过滤掉 NSRange sameRange = NSIntersectionRange(glyphRangeInLine, truncatedGlyphRange); if (sameRange.length>0&&NSMaxRange(sameRange)==NSMaxRange(glyphRangeInLine)) { //我们这里先只处理tail模式的 //而经过测试truncatedGlyphRangeInLineFragmentForGlyphAtIndex暂时只支持NSLineBreakByTruncatingTail模式 //其他两种暂时也不会用,即使用,现在通过TextKit的话也没法获取 glyphRangeInLine = NSMakeRange(glyphRangeInLine.location, sameRange.location-glyphRangeInLine.location); } } if (glyphRangeInLine.length>0) { CGFloat startDrawY = CGFLOAT_MAX; CGFloat maxLineHeight = 0.0f; //找到这行的 背景色区间 的文字的最小Y值和最大的文字高度 for (NSInteger glyphIndex = glyphRangeInLine.location; glyphIndex