支持图文混排在教程:《Core Text Tutorial for iOS: Making a Magazine App》 中有介绍,我们在解析DOM树遇到图片节点时,则将该内容转成一个空格,随后设置该空格在绘制时,需要我们自己指定宽高相关信息,而宽高信息在图片节点中都有提供。这样,CoreText引擎在绘制时,就会把相关的图片位置留空,之后我们将图片异步下来下来后,使用CoreGraph相关的API将图片再画在界面上,就实现了图文混排功能。
/* Callbacks */staticvoiddeallocCallback(void*ref){[(id)refrelease];}staticCGFloatascentCallback(void*ref){CGFloatheight=[(NSString*)[(NSDictionary*)refobjectForKey:@"height"]floatValue];returnheight/2+[FrameParserConfigsharedInstance].baselineFromMid;}staticCGFloatdescentCallback(void*ref){CGFloatheight=[(NSString*)[(NSDictionary*)refobjectForKey:@"height"]floatValue];returnheight/2-[FrameParserConfigsharedInstance].baselineFromMid;}staticCGFloatwidthCallback(void*ref){return[(NSString*)[(NSDictionary*)refobjectForKey:@"width"]floatValue];}+(void)appendDelegateData:(NSDictionary*)delegateDataToString:(NSMutableAttributedString*)contentString{//render empty space for drawing the image in the text //1CTRunDelegateCallbackscallbacks;callbacks.version=kCTRunDelegateCurrentVersion;callbacks.getAscent=ascentCallback;callbacks.getDescent=descentCallback;callbacks.getWidth=widthCallback;callbacks.dealloc=deallocCallback;CTRunDelegateRefdelegate=CTRunDelegateCreate(&callbacks,delegateData);[delegateDataretain];// Character to use as recommended by kCTRunDelegateAttributeName documentation.// use " " will lead to wrong width in CTFramesetterSuggestFrameSizeWithConstraintsunicharobjectReplacementChar=0xFFFC;NSString*objectReplacementString=[NSStringstringWithCharacters:&objectReplacementCharlength:1];NSDictionary*attributes=[selfgetAttributesWithStyleArray:nil];//try to apply linespacing attributes to this placeholderNSMutableAttributedString*space=[[NSMutableAttributedStringalloc]initWithString:objectReplacementStringattributes:attributes];CFAttributedStringSetAttribute((CFMutableAttributedStringRef)space,CFRangeMake(0,1),kCTRunDelegateAttributeName,delegate);CFRelease(delegate);[contentStringappendAttributedString:space];[spacerelease];}
// test touch point is on link or not+(LinkData*)touchLinkInView:(UIView*)viewatPoint:(CGPoint)pointdata:(CTTableViewCellData*)data{CTFrameReftextFrame=data.ctFrame;CFArrayReflines=CTFrameGetLines(textFrame);if(!lines)returnnil;CFIndexcount=CFArrayGetCount(lines);LinkData*foundLink=nil;CGPointorigins[count];CTFrameGetLineOrigins(textFrame,CFRangeMake(0,0),origins);// CoreText context coordinates are the opposite to UIKit so we flip the boundsCGAffineTransformtransform=CGAffineTransformScale(CGAffineTransformMakeTranslation(0,view.bounds.size.height),1.f,-1.f);for(inti=0;i<count;i++){CGPointlinePoint=origins[i];CTLineRefline=CFArrayGetValueAtIndex(lines,i);CGRectflippedRect=[selfgetLineBounds:linepoint:linePoint];CGRectrect=CGRectApplyAffineTransform(flippedRect,transform);if(CGRectContainsPoint(rect,point)){CGPointrelativePoint=CGPointMake(point.x-CGRectGetMinX(rect),point.y-CGRectGetMinY(rect));CFIndexidx=CTLineGetStringIndexForPosition(line,relativePoint);foundLink=[selflinkAtIndex:idxlinkArray:data.linkArray];returnfoundLink;}}returnnil;}
staticNSString*constkEllipsesCharacter=@"\u2026";CGPathRefpath=CTFrameGetPath(_data.ctFrame);CGRectrect=CGPathGetBoundingBox(path);CFArrayReflines=CTFrameGetLines(_data.ctFrame);CFIndexlineCount=CFArrayGetCount(lines);NSIntegernumberOfLines=MIN(_numberOfLines,lineCount);CGPointlineOrigins[numberOfLines];CTFrameGetLineOrigins(_data.ctFrame,CFRangeMake(0,numberOfLines),lineOrigins);NSAttributedString*attributedString=_data.attributedString;for(CFIndexlineIndex=0;lineIndex<numberOfLines;lineIndex++){CGPointlineOrigin=lineOrigins[lineIndex];lineOrigin.y=self.frame.size.height+(lineOrigin.y-rect.size.height);CGContextSetTextPosition(context,lineOrigin.x,lineOrigin.y);CTLineRefline=CFArrayGetValueAtIndex(lines,lineIndex);BOOLshouldDrawLine=YES;if(lineIndex==numberOfLines-1){CFRangelastLineRange=CTLineGetStringRange(line);if(lastLineRange.location+lastLineRange.length<(CFIndex)attributedString.length){CTLineTruncationTypetruncationType=kCTLineTruncationEnd;NSUIntegertruncationAttributePosition=lastLineRange.location+lastLineRange.length-1;NSDictionary*tokenAttributes=[attributedStringattributesAtIndex:truncationAttributePositioneffectiveRange:NULL];NSAttributedString*tokenString=[[NSAttributedStringalloc]initWithString:kEllipsesCharacterattributes:tokenAttributes];CTLineReftruncationToken=CTLineCreateWithAttributedString((__bridgeCFAttributedStringRef)tokenString);NSMutableAttributedString*truncationString=[[attributedStringattributedSubstringFromRange:NSMakeRange(lastLineRange.location,lastLineRange.length)]mutableCopy];if(lastLineRange.length>0){// Remove any whitespace at the end of the line.unicharlastCharacter=[[truncationStringstring]characterAtIndex:lastLineRange.length-1];if([[NSCharacterSetwhitespaceAndNewlineCharacterSet]characterIsMember:lastCharacter]){[truncationStringdeleteCharactersInRange:NSMakeRange(lastLineRange.length-1,1)];}}[truncationStringappendAttributedString:tokenString];CTLineReftruncationLine=CTLineCreateWithAttributedString((__bridgeCFAttributedStringRef)truncationString);CTLineReftruncatedLine=CTLineCreateTruncatedLine(truncationLine,self.size.width,truncationType,truncationToken);if(!truncatedLine){// If the line is not as wide as the truncationToken, truncatedLine is NULLtruncatedLine=CFRetain(truncationToken);}CFRelease(truncationLine);CFRelease(truncationToken);CTLineDraw(truncatedLine,context);CFRelease(truncatedLine);shouldDrawLine=NO;}}if(shouldDrawLine){CTLineDraw(line,context);}}
没有评论:
发表评论