Hi all
I am in the process of rendering rich text using CoreText in iphone os sdk 4. The drawing can be single page or multi page. I have subclassed the UIView whose draw rect is as given below:
Here "_delegate" points to another class instance that initiates the process of rendering the rich text.
My problem is that I am getting the height of rendered text using the function call measureFrame which is little bigger than the actual one which results in bigger gaps between paragraphs. Also it is quite confusing when it comes to dealing with coordinate system for CoreText in iphone. The function that is calulating the height of CTFrame is as given below
I have also tried "CTLineGetTypographicBounds" instead of CTLineGetImageBounds and also considered the last line in each frame.
Still getting bigger frame height.
Whats wrong here?
Any idea??
Thanks
Arnieterm
I am in the process of rendering rich text using CoreText in iphone os sdk 4. The drawing can be single page or multi page. I have subclassed the UIView whose draw rect is as given below:
Code:
- (void)drawRect:(CGRect)rect{
// Initialize a graphics context and set the text matrix to a known value.
CGContextRef context = UIGraphicsGetCurrentContext();
float viewHeight = self.bounds.size.height;
CGContextTranslateCTM(context, 0, viewHeight);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGRect textBounds = rect;
textBounds.origin.y = -10;
NSArray* arrayOfElements = [_delegate getArrayOfDataToRender];
int arrayIndex = 0;
for (arrayIndex = startIndex; arrayIndex < [arrayOfElements count]; arrayIndex++) {
id currentElement = [arrayOfElements objectAtIndex:arrayIndex];
if ( [currentElement isKindOfClass:[NSMutableAttributedString class]] ) {
CFMutableAttributedStringRef attrString = NULL;
if (( startRange.location>0 ) && (arrayIndex == startIndex)) {
attrString = (CFMutableAttributedStringRef) ([ ((NSAttributedString*)currentElement) attributedSubstringFromRange:startRange] );
}else {
attrString = (CFMutableAttributedStringRef)currentElement;
}
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, textBounds);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);
CFRange fullAttributedStringRange = CFRangeMake(0, CFStringGetLength((CFStringRef)attrString));
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, fullAttributedStringRange, path, NULL);
NSLog(@"Before drawing the available rectangle is : %@",NSStringFromCGRect(textBounds));
if (frame != NULL) {
CTFrameDraw(frame, context);
CFRange visibleRange = CTFrameGetVisibleStringRange(frame);
if (visibleRange.length < fullAttributedStringRange.length) {
NSRange invisibleStringRange = NSMakeRange(visibleRange.length , fullAttributedStringRange.length - visibleRange.length );
CFRelease(frame);
frame = NULL;
CFRelease(framesetter);
framesetter = NULL;
CFRelease(path);
path = NULL;
attrString = NULL;
[_delegate insertNextPage: arrayIndex: invisibleStringRange];
break;
}
if (arrayIndex == 5) {
NSLog(@"Text rendered `:%@",[ ((NSMutableAttributedString*)attrString) string]);
}
CGFloat aHeight = [self measureFrame: frame: context];
//I need to do the below given stuff in order to bring the various frames closer to each other. Not an applicable approach at all
if (CFArrayGetCount(CTFrameGetLines(frame)) >1) {
textBounds.origin.y -= (aHeight)/2;
textBounds.size.height -= (aHeight);
}else {
textBounds.origin.y -= aHeight;
textBounds.size.height -= (aHeight);
}
NSLog(@"Height is :%f",aHeight);
NSLog(@"After drawing the available rectangle is : %@",NSStringFromCGRect(textBounds));
NSLog(@"************************\n\n");
CFRelease(frame);
frame = NULL;
CFRelease(framesetter);
framesetter = NULL;
CFRelease(path);
path = NULL;
attrString = NULL;
}
}else if ([currentElement isKindOfClass:[UIImage class]]) {
/*
UIImage* currentImage = (UIImage*)currentElement;
CGSize imgSize = currentImage.size;
if (imgSize.height > textBounds.size.height) {
[_delegate insertNextPage: arrayIndex: NSMakeRange(0, 0)];
break;
}
CGRect imageFrame = CGRectMake((textBounds.size.width - imgSize.width)/2, -(textBounds.origin.y ), imgSize.width, imgSize.height);
UIImageView* imgvw = [ [ UIImageView alloc] initWithFrame: imageFrame];
imgvw.image = currentImage;
[self addSubview:imgvw];
[imgvw release];
textBounds.origin.y -= imgSize.height ;
*/
}
}
if (arrayIndex == [arrayOfElements count] ) {
[_delegate drawingFinished];
}
}
Here "_delegate" points to another class instance that initiates the process of rendering the rich text.
My problem is that I am getting the height of rendered text using the function call measureFrame which is little bigger than the actual one which results in bigger gaps between paragraphs. Also it is quite confusing when it comes to dealing with coordinate system for CoreText in iphone. The function that is calulating the height of CTFrame is as given below
Code:
-(CGFloat)measureFrame: (CTFrameRef)frame : (CGContextRef)ctx{
CFArrayRef lines = CTFrameGetLines(frame);
CGFloat height = 0.0;
CGFloat height2 = 0.0;
CGFloat ascent, descent, leading;
for (CFIndex index = 0; index < CFArrayGetCount(lines); index++) {
CTLineRef line = (CTLineRef)CFArrayGetValueAtIndex(lines, index);
CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
CGRect lineHeight = CTLineGetImageBounds(line, ctx);
height += lineHeight.size.height;
height2 += (ascent + fabsf(descent) + leading);
}
NSLog(@"Height %f Height2 :%f",height, height2);
return ceil(height);
Still getting bigger frame height.
Whats wrong here?
Any idea??
Thanks
Arnieterm