CoreText库中使用CTFramesetter,根据文本内容实现丰富的Frame
2012-03-05 14:45 白山 阅读(3339) 评论(0) 编辑 收藏 举报//textContent:要在Frame中填充的文本内容
CFMutableAttributedStringRef attributeRef = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringReplaceString(attributeRef, CFRangeMake(0, 0), (CFStringRef)textContent);
//设定文本格式
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = { 60/255.0, 60/255.0, 60/255.0, 1.0 };
CGColorRef color = CGColorCreate(colorspace, components);
CGColorSpaceRelease(colorspace);
int count = [textContent length];
CFAttributedStringSetAttribute(attributeRef, CFRangeMake(0, count), kCTForegroundColorAttributeName,color);
CGColorRelease(color);
CTFontRef font = CTFontCreateWithName((CFStringRef)@"Arial", fontSize, nil);
//CTFontRef font = CTFontCreateWithName(CFSTR("Times New Roman"), fontSize, nil);
CFAttributedStringSetAttribute(attributeRef, CFRangeMake(0, count), kCTFontAttributeName,font);
CFRelease(font);
{
//行距
CFIndex theNumberOfSettings = 4;
CTTextAlignment theAlignment = kCTJustifiedTextAlignment;
CTLineBreakMode theBreakMode = kCTLineBreakByCharWrapping;
CGFloat theFirstLineHeadIndent = fontSize*2;
CTParagraphStyleSetting theSettings[4] =
{
{ kCTParagraphStyleSpecifierLineSpacing, sizeof(CGFloat), &lineSpacing},
{ kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment),&theAlignment },
{ kCTParagraphStyleSpecifierLineBreakMode, sizeof(CTLineBreakMode), &theBreakMode },
{ kCTParagraphStyleSpecifierFirstLineHeadIndent, sizeof(CGFloat), &theFirstLineHeadIndent}
};
CTParagraphStyleRef theParagraphRef = CTParagraphStyleCreate(theSettings, theNumberOfSettings);
CFAttributedStringSetAttribute((CFMutableAttributedStringRef)attributeRef, CFRangeMake(0, [textContent length]), kCTParagraphStyleAttributeName, theParagraphRef);
CFRelease(theParagraphRef);
}
//开始绘制
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFMutableAttributedStringRef)attributeRef);
{
CFRange range = CFRangeMake(0, 0);
CFRange curRange = CFRangeMake(0, 0);
CFIndex lastPageLines = 0;
CGPoint preTextPoint = textPoint;
CGRect otherRect;
//获取size的大小以计算最终坐标
{
CGRect textFrame;
textFrame = CGRectMake(preTextPoint.x, preTextPoint.y, ArticleBodyWidth, CGFLOAT_MAX);
[self writeLogFrame:textFrame];
CGMutablePathRef pathRef = CGPathCreateMutable();
CGPathAddRect(pathRef,NULL,textFrame);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, range, pathRef, NULL);
curRange = CTFrameGetVisibleStringRange(frameRef);//读取当前Range,以判断是否完成,to do
lastPageLines += CFArrayGetCount(CTFrameGetLines(frameRef));//获取行数
CFRelease(frameRef);
CGPathRelease(pathRef);
textPoint = CGPointMake(textPoint.x, textPoint.y+ lastPageLines*(fontSize+lineSpacing)+5);
otherRect = CGRectMake(textPoint.x, textPoint.y, ArticleBodyWidth, textPoint.y);
}
//开始执行绘制,组合
{
CFRange range = CFRangeMake(0, 0);
CFRange curRange = CFRangeMake(0, 0);
CFIndex lastPageLines = 0;
CGRect textFrame;
textFrame = CGRectMake(preTextPoint.x, preTextPoint.y, otherRect.size.width, otherRect.size.height);
[self writeLogFrame:textFrame];
CGMutablePathRef pathRef = CGPathCreateMutable();
CGPathAddRect(pathRef,NULL,textFrame);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, range, pathRef, NULL);
//frameArray中存储所有完成的frame
CFArrayAppendValue(frameArray, frameRef);
curRange = CTFrameGetVisibleStringRange(frameRef);
lastPageLines += CFArrayGetCount(CTFrameGetLines(frameRef));
textPoint = CGPointMake(textPoint.x, preTextPoint.y + lastPageLines*(fontSize+lineSpacing)+5);
CFRelease(frameRef);
CGPathRelease(pathRef);
}
}
CFRelease(framesetter);
CFRelease(attributeRef);
完成frame在内存中的设置后,开始进行绘制。
注意:
CTFramesetterRef中的坐标和objc的UI坐标相反,需要在执行绘制事调整坐标「y轴相反,文本相反」顺序填充,所以在对frame进行设置时要预考虑各frame调整后的坐标是否正确。
-(void)drawRect:(CGRect)rect
{
if (0 == CFArrayGetCount(frameArray)) {
return;
}
NSLog(@"-->self frame height = %f",self.frame.size.height);
// 调整坐标
CGContextRef context = UIGraphicsGetCurrentContext();
{
CGAffineTransform textTran = CGAffineTransformIdentity;
textTran = CGAffineTransformMakeTranslation(0.0, self.frame.size.height);
textTran = CGAffineTransformScale(textTran, 1.0, -1.0);
CGContextConcatCTM(context, textTran);
}
//向矩形框中填充内容
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
for (int i=0; i<CFArrayGetCount(frameArray); i++) {
CTFrameRef frameRef = CFArrayGetValueAtIndex(frameArray, i);
CTFrameDraw(frameRef,context);
}
}
官方解释
CGAffineTransformMakeTranslation
Returns an affine transformation matrix constructed from translation values you provide.
CGAffineTransform CGAffineTransformMakeTranslation (
CGFloat tx,
CGFloat ty
);
Parameters
- tx
-
The value by which to move the x-axis of the coordinate system.
- ty
-
The value by which to move the y-axis of the coordinate system.
Return Value
A new affine transform matrix.
CGAffineTransformScale
Returns an affine transformation matrix constructed by scaling an existing affine transform.
CGAffineTransform CGAffineTransformScale (
CGAffineTransform t,
CGFloat sx,
CGFloat sy
);
Parameters
- t
-
An existing affine transform.
- sx
-
The value by which to scale x values of the affine transform.
- sy
-
The value by which to scale y values of the affine transform.
Return Value
A new affine transformation matrix.