I generated pdf this tutorial. I need to generate the pdf from two different view controllers. When I push from one view controller to get in the VC where I generate the pdf, it does not crash. But when I push from 2nd view controller to get in the VC where I generate the pdf, it gives me EXC_BAD Access
Following is my code.
- (void)drawText:(NSString*)textToDraw inFrame:(CGRect)frameRect fontSize:
(float)sizeofFont
{
NSUInteger length = [textToDraw length];
CFStringRef string = (__bridge CFStringRef) textToDraw;
CFMutableAttributedStringRef currentText =
CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringReplaceString (currentText,CFRangeMake(0, 0), string); **//EXC_BAD_ACCESS**
// CFAttributedStringReplaceString (currentText,CFRangeMake(0, length-1), string);
CTFontRef font = CTFontCreateWithName((CFStringRef)#"UniversLTStd-BoldCn",
sizeofFont, nil);
CFAttributedStringSetAttribute(currentText,CFRangeMake(0,
length),kCTFontAttributeName,font);
if (self.flagToSetBlueColoredText == NO)
{
CFAttributedStringSetAttribute(currentText,CFRangeMake(0, length),kCTForegroundColorAttributeName,[UIColor blackColor].CGColor);
}
else if(self.flagToSetBlueColoredText == YES)
{
CFAttributedStringSetAttribute(currentText,CFRangeMake(0, length),kCTForegroundColorAttributeName,[UIColor blueColor].CGColor);
}
CTFramesetterRef framesetter =
CTFramesetterCreateWithAttributedString(currentText);
CGMutablePathRef framePath = CGPathCreateMutable();
CGPathAddRect(framePath, NULL, frameRect);
CFRange currentRange = CFRangeMake(0, 0);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange,
framePath, NULL);
CGPathRelease(framePath);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
CGContextTranslateCTM(currentContext, 0, frameRect.origin.y*2);
CGContextScaleCTM(currentContext, 1.0, -1.0);
CTFrameDraw(frameRef, currentContext);
CGContextScaleCTM(currentContext, 1.0, -1.0);
CGContextTranslateCTM(currentContext, 0, (-1)*frameRect.origin.y*2);
CFRelease(frameRef);
//CFRelease(currentText);
CFRelease(framesetter);
//CFRelease(stringRef);
}
I don't know if this was a good practise or not, but the following code worked for me. I handled string condition and checked it with NULLand skipped the statement as follows.
- (void)drawText:(NSString*)textToDraw inFrame:(CGRect)frameRect fontSize:
(float)sizeofFont
{
NSInteger length = [textToDraw length];
CFStringRef string = (__bridge CFStringRef) textToDraw;
CFMutableAttributedStringRef currentText =
CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
if (string == NULL)
{
//CFAttributedStringReplaceString(nil ,range, nil);
}
else
{
CFAttributedStringReplaceString(currentText,CFRangeMake(0, 0), string); //EXC_BAD_ACCESS due to nil values of string and currentText
}
CTFontRef font = CTFontCreateWithName((CFStringRef)#"UniversLTStd-BoldCn",
sizeofFont, nil);
CFAttributedStringSetAttribute(currentText,CFRangeMake(0,
length),kCTFontAttributeName,font);
if (self.flagToSetBlueColoredText == NO)
{
CFAttributedStringSetAttribute(currentText,CFRangeMake(0, length),kCTForegroundColorAttributeName,[UIColor blackColor].CGColor);
}
else if(self.flagToSetBlueColoredText == YES)
{
CFAttributedStringSetAttribute(currentText,CFRangeMake(0, length),kCTForegroundColorAttributeName,[UIColor blueColor].CGColor);
}
CTFramesetterRef framesetter =
CTFramesetterCreateWithAttributedString(currentText);
CGMutablePathRef framePath = CGPathCreateMutable();
CGPathAddRect(framePath, NULL, frameRect);
CFRange currentRange = CFRangeMake(0, 0);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange,
framePath, NULL);
CGPathRelease(framePath);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
CGContextTranslateCTM(currentContext, 0, frameRect.origin.y*2);
CGContextScaleCTM(currentContext, 1.0, -1.0);
CTFrameDraw(frameRef, currentContext);
CGContextScaleCTM(currentContext, 1.0, -1.0);
CGContextTranslateCTM(currentContext, 0, (-1)*frameRect.origin.y*2);
CFRelease(frameRef);
//CFRelease(currentText);
CFRelease(framesetter);
//CFRelease(stringRef);
}
Related
I am interested in creating a method in CoreText that will behave as much as possible to the UILabel behavior. So if I am looking to achieve something similar to:
UIFont *font1 = [UIFont fontWithName:kMyriadProSemiBold size:15];
NSDictionary *arialDict = [NSDictionary dictionaryWithObject: font1 forKey:NSFontAttributeName];
NSMutableAttributedString *aAttrString1 = [[NSMutableAttributedString alloc] initWithString:#"My" attributes: arialDict];
UIFont *font2 = [UIFont fontWithName:kMyriadProRegular size:15];
NSDictionary *arialDict2 = [NSDictionary dictionaryWithObject: font2 forKey:NSFontAttributeName];
NSMutableAttributedString *aAttrString2 = [[NSMutableAttributedString alloc] initWithString:#"Profile" attributes: arialDict2];
[aAttrString1 appendAttributedString:aAttrString2];
But using Core Text.
Currently I am using the next method:
+ (void)drawText:(NSString *)textToDraw
inFrame:(CGRect)frameRect
withFont:(UIFont *)originalFont
textColor:(UIColor *)textColor
alignment:(PDFTextAlignment)alignment{
if (!textToDraw) {
// If nil, give it an empty value to draw
textToDraw = #"";
}
// Prepare font
CTFontRef font = [PDFManager ctFontRefFromUIFont:originalFont];
CGColorRef color = textColor.CGColor;
// Paragraph
CTTextAlignment ctAlignment;
switch (alignment) {
case PDFTextAlignmentLeft:
ctAlignment = kCTTextAlignmentLeft;
break;
case PDFTextAlignmentCenter:
ctAlignment = kCTTextAlignmentCenter;
break;
case PDFTextAlignmentRight:
ctAlignment = kCTTextAlignmentRight;
break;
case PDFTextAlignmentJustified:
ctAlignment = kCTTextAlignmentJustified;
break;
default:
ctAlignment = kCTTextAlignmentLeft;
break;
}
CTParagraphStyleSetting settings[] = {
{kCTParagraphStyleSpecifierAlignment, sizeof(ctAlignment), &ctAlignment},
};
CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings, sizeof(settings) / sizeof(settings[0]));
// Create an attributed string
CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName, kCTParagraphStyleAttributeName };
CFTypeRef values[] = { font, color, paragraphStyle };
CFDictionaryRef attr = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values,
sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFStringRef stringRef = (__bridge CFStringRef)textToDraw;
// Prepare the text using a Core Text Framesetter.
CFAttributedStringRef currentText = CFAttributedStringCreate(NULL, stringRef, attr);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(currentText);
CGMutablePathRef framePath = CGPathCreateMutable();
CGPathAddRect(framePath, NULL, frameRect);
// Get the frame that will do the rendering.
CFRange currentRange = CFRangeMake(0, 0);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange, framePath, NULL);
CGPathRelease(framePath);
// Get the graphics context.
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// Put the text matrix into a known state. This ensures
// that no old scaling factors are left in place.
CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
// Core Text draws from the bottom-left corner up, so flip
// the current transform prior to drawing.
// Modify this to take into consideration the origin.
CGContextTranslateCTM(currentContext, 0, frameRect.origin.y*2);
CGContextScaleCTM(currentContext, 1.0, -1.0);
// Draw the frame.
CTFrameDraw(frameRef, currentContext);
// Add these two lines to reverse the earlier transformation.
CGContextScaleCTM(currentContext, 1.0, -1.0);
CGContextTranslateCTM(currentContext, 0, (-1)*frameRect.origin.y*2);
//Confirm that everything is released that needs to be!
CFRelease(frameRef);
CFRelease(stringRef);
CFRelease(framesetter);
CFRelease(font);
CFRelease(paragraphStyle);
}
And I need to update the CFDictionaryRef attr in order to also accept the new attributes?
I ended up by actually using the NSAttributedString as fallows and convert the method from above to:
+ (void)drawAttributedText:(NSAttributedString *)textToDraw
inFrame:(CGRect)frameRect
alignment:(PDFTextAlignment)alignment{
// Paragraph
CTTextAlignment ctAlignment;
switch (alignment) {
case PDFTextAlignmentLeft:
ctAlignment = kCTTextAlignmentLeft;
break;
case PDFTextAlignmentCenter:
ctAlignment = kCTTextAlignmentCenter;
break;
case PDFTextAlignmentRight:
ctAlignment = kCTTextAlignmentRight;
break;
case PDFTextAlignmentJustified:
ctAlignment = kCTTextAlignmentJustified;
break;
default:
ctAlignment = kCTTextAlignmentLeft;
break;
}
CTParagraphStyleSetting settings[] = {
{kCTParagraphStyleSpecifierAlignment, sizeof(ctAlignment), &ctAlignment},
};
CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings, sizeof(settings) / sizeof(settings[0]));
CFAttributedStringRef currentText = (__bridge CFAttributedStringRef)textToDraw;
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(currentText);
CGMutablePathRef framePath = CGPathCreateMutable();
CGPathAddRect(framePath, NULL, frameRect);
// Get the frame that will do the rendering.
CFRange currentRange = CFRangeMake(0, 0);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange, framePath, NULL);
CGPathRelease(framePath);
// Get the graphics context.
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// Put the text matrix into a known state. This ensures
// that no old scaling factors are left in place.
CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
// Core Text draws from the bottom-left corner up, so flip
// the current transform prior to drawing.
// Modify this to take into consideration the origin.
CGContextTranslateCTM(currentContext, 0, frameRect.origin.y*2);
CGContextScaleCTM(currentContext, 1.0, -1.0);
// Draw the frame.
CTFrameDraw(frameRef, currentContext);
// Add these two lines to reverse the earlier transformation.
CGContextScaleCTM(currentContext, 1.0, -1.0);
CGContextTranslateCTM(currentContext, 0, (-1)*frameRect.origin.y*2);
//Confirm that everything is released that needs to be!
CFRelease(frameRef);
CFRelease(framesetter);
CFRelease(paragraphStyle);
}
+ (NSMutableAttributedString *)getAttributedString:(NSString *)str
withFont:(UIFont *)font
andColor:(UIColor *)fontColor{
NSDictionary *arialDict = [NSDictionary dictionaryWithObject: font forKey:NSFontAttributeName];
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:str attributes: arialDict];
return attrString;
}
and the way to use it is:
+ (void)drawPDFTitleUsingString:(NSString *)passedTitle{
NSMutableAttributedString *attStr1 = [self getAttributedString:NSLocalizedString(#"Normal part of the string, ", nil)
withFont:FONT_CLEAR_SANS_REGULAR(18)
andColor:[UIColor blackColor]];
NSMutableAttributedString *attStr2 = [self getAttributedString:NSLocalizedString(#"bold part of the string", nil)
withFont:FONT_CLEAR_SANS_BOLD(18)
andColor:[UIColor blackColor]];
[attStr1 appendAttributedString:attStr2];
[self drawAttributedText:attStr1
inFrame:CGRectMake(PDFTableXPosition, 15 + 55, PDFTableWidth, 42)
alignment:PDFTextAlignmentLeft];
}
I am trying to make a method, that will work simmillarry to UILabel but in CoreText, here is what I am trying to do:
+(void)drawText:(NSString*)textToDraw
inFrame:(CGRect)frameRect
withFont:(NSString *)fontName
andFontColor:(UIColor *)fontColor
andFontSize:(float)fontSize{
CFStringRef fontN = (__bridge CFStringRef)fontName;
NSMutableAttributedString *string = [[NSMutableAttributedString alloc]
initWithString:textToDraw];
CTFontRef helvetica = CTFontCreateWithName(fontN, fontSize, NULL);
[string addAttribute:(id)kCTFontAttributeName
value:(__bridge id)helvetica
range:NSMakeRange(0, [string length])];
[string addAttribute:(id)kCTForegroundColorAttributeName
value:(id)fontColor.CGColor
range:NSMakeRange(0, [string length])];
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string);
CGMutablePathRef framePath = CGPathCreateMutable();
CGPathAddRect(framePath, NULL, frameRect);
// Get the frame that will do the rendering.
CFRange currentRange = CFRangeMake(0, 0);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange, framePath, NULL);
CGPathRelease(framePath);
// Get the graphics context.
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// Put the text matrix into a known state. This ensures
// that no old scaling factors are left in place.
CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
// Core Text draws from the bottom-left corner up, so flip
// the current transform prior to drawing.
CGContextTranslateCTM(currentContext, 0, frameRect.origin.y*2);
CGContextScaleCTM(currentContext, 1.0, -1.0);
// Draw the frame.
CTFrameDraw(frameRef, currentContext);
CGContextScaleCTM(currentContext, 1.0, -1.0);
CGContextTranslateCTM(currentContext, 0, (-1)*frameRect.origin.y*2);
CFRelease(frameRef);
CFRelease(framesetter);
}
The problem is that when I run the app it stop at the next line without throwing an exception:
CTFrameDraw(frameRef, currentContext);
UPDATE:
Resolved the crash after I removed a few extra lines that are not in this post. But I still need some help in adjusting this method in accepting the number of line and also the line break mode (NSLineBreakByWordWrapping, NSLineBreakByTruncatingTail..)
After figuring out the cause of the crash I added the next line at the beginning of the method:
textToDraw = [self getDisplayedStringInFrame:frameRect.size
andFont:[UIFont fontWithName:fontName size:fontSize]
andString:textToDraw];
and added this extra method to deal with the NSLineBreakByTruncatingTail effect in witch I was interested:
+ (NSString *) getDisplayedStringInFrame:(CGSize)size andFont:(UIFont *)font andString:(NSString *)str{
NSString *written = #"";
int i = 0;
int currentWidth = 0;
NSString *nextSetOfString = #"";
while (1)
{
NSRange range;
range.location = i;
range.length = 1;
NSString *nextChar = [str substringWithRange:range];
nextSetOfString = [nextSetOfString stringByAppendingString:nextChar];
CGSize requiredSize = [nextSetOfString sizeWithFont:font constrainedToSize:CGSizeMake(NSIntegerMax, NSIntegerMax)];
currentWidth = requiredSize.width;
if(size.width >= currentWidth && size.height >= requiredSize.height)
{
written = [written stringByAppendingString:nextChar];
}
else
{
break;
}
i++;
}
written = [written substringToIndex:[written length] - 2];
written = [written stringByAppendingString:#".."];
return written;
}
I draw a table view in a pdf like in this tutorial and it works when the table was so big like in tutorial , but i need a little table so i have changed :
int xOrigin = 350;
int yOrigin = 200;
int rowHeight = 10;
int columnWidth = 35;
int numberOfRows = 6;
int numberOfColumns = 3;
[self drawTableAt:CGPointMake(xOrigin, yOrigin) withRowHeight:rowHeight andColumnWidth:columnWidth andRowCount:numberOfRows andColumnCount:numberOfColumns];
[self drawTableDataAt:CGPointMake(xOrigin, yOrigin) withRowHeight:rowHeight andColumnWidth:columnWidth andRowCount:numberOfRows andColumnCount:numberOfColumns];
and now the table is empty :( Have anyone any ideea about how can i populate again the table ?
With reference to the example you used in method
+(void)drawTableDataAt:(CGPoint)origin
withRowHeight:(int)rowHeight
andColumnWidth:(int)columnWidth
andRowCount:(int)numberOfRows
andColumnCount:(int)numberOfColumns
padding = 10
change your size to 20
This method is used to show with what data the table is populated
+(void)drawTableDataAt:(CGPoint)origin
withRowHeight:(int)rowHeight
andColumnWidth:(int)columnWidth
andRowCount:(int)numberOfRows
andColumnCount:(int)numberOfColumns
{
int padding = 10;
NSArray* headers = [NSArray arrayWithObjects:#"Quantity", #"Description", #"Unit price", #"Total", nil];
NSArray* invoiceInfo1 = [NSArray arrayWithObjects:#"1", #"Development", #"$1000", #"$1000", nil];
NSArray* invoiceInfo2 = [NSArray arrayWithObjects:#"1", #"Development", #"$1000", #"$1000", nil];
NSArray* invoiceInfo3 = [NSArray arrayWithObjects:#"1", #"Development", #"$1000", #"$1000", nil];
NSArray* invoiceInfo4 = [NSArray arrayWithObjects:#"1", #"Development", #"$1000", #"$1000", nil];
NSArray* allInfo = [NSArray arrayWithObjects:headers, invoiceInfo1, invoiceInfo2, invoiceInfo3, invoiceInfo4, nil];
for(int i = 0; i < [allInfo count]; i++)
{
NSArray* infoToDraw = [allInfo objectAtIndex:i];
for (int j = 0; j < numberOfColumns; j++)
{
int newOriginX = origin.x + (j*columnWidth);
int newOriginY = origin.y + ((i+1)*rowHeight);
CGRect frame = CGRectMake(newOriginX + padding, newOriginY + padding, columnWidth, rowHeight);
[self drawText:[infoToDraw objectAtIndex:j] inFrame:frame];
}
}
}
This below pasted method is used to draw the text within table cells
+(void)drawText:(NSString*)textToDraw inFrame:(CGRect)frameRect
{
CFStringRef stringRef = (__bridge CFStringRef)textToDraw;
// Prepare the text using a Core Text Framesetter
CFAttributedStringRef currentText = CFAttributedStringCreate(NULL, stringRef, NULL);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(currentText);
CGMutablePathRef framePath = CGPathCreateMutable();
CGPathAddRect(framePath, NULL, frameRect);
// Get the frame that will do the rendering.
CFRange currentRange = CFRangeMake(0, 0);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange, framePath, NULL);
CGPathRelease(framePath);
// Get the graphics context.
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// Put the text matrix into a known state. This ensures
// that no old scaling factors are left in place.
CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
// Core Text draws from the bottom-left corner up, so flip
// the current transform prior to drawing.
CGContextTranslateCTM(currentContext, 0, frameRect.origin.y*2);
CGContextScaleCTM(currentContext, 1.0, -1.0);
// Draw the frame.
CTFrameDraw(frameRef, currentContext);
CGContextScaleCTM(currentContext, 1.0, -1.0);
CGContextTranslateCTM(currentContext, 0, (-1)*frameRect.origin.y*2);
CFRelease(frameRef);
CFRelease(stringRef);
CFRelease(framesetter);
}
In case you want to set the text inside small cells with small font size
-(void)drawText:(NSString*)textToDraw inFrame:(CGRect)frameRect
{
int length=[textToDraw length];
CFStringRef string = (__bridge CFStringRef) textToDraw;
CFMutableAttributedStringRef currentText = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringReplaceString (currentText,CFRangeMake(0, 0), string);
CTFontRef font = CTFontCreateWithName((CFStringRef)#"Helvetica", 8.0f, nil);
CFAttributedStringSetAttribute(currentText,CFRangeMake(0, length),kCTFontAttributeName,font);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(currentText);
CGMutablePathRef framePath = CGPathCreateMutable();
CGPathAddRect(framePath, NULL, frameRect);
CFRange currentRange = CFRangeMake(0, 0);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange, framePath, NULL);
CGPathRelease(framePath);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
CGContextTranslateCTM(currentContext, 0, frameRect.origin.y*2);
CGContextScaleCTM(currentContext, 1.0, -1.0);
CTFrameDraw(frameRef, currentContext);
CGContextScaleCTM(currentContext, 1.0, -1.0);
CGContextTranslateCTM(currentContext, 0, (-1)*frameRect.origin.y*2);
CFRelease(frameRef);
CFRelease(framesetter);
}
I am using the following code to set the text color in Pdf generation. The code is working well ,the only problem is its not setting the text color.
-(void)drawText:(NSString*)textToDraw inFrame:(CGRect)frameRect fontSize:
(float)sizeofFont
{
NSLog(#"FONT SIZE %f",sizeofFont);
int length=[textToDraw length];
CFStringRef string = (__bridge CFStringRef) textToDraw;
CFMutableAttributedStringRef currentText =
CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringReplaceString (currentText,CFRangeMake(0, 0), string);
CTFontRef font = CTFontCreateWithName((CFStringRef)#"UniversLTStd-BoldCn",
sizeofFont, nil);
CFAttributedStringSetAttribute(currentText,CFRangeMake(0,
length),kCTFontAttributeName,font);
CGColorSpaceCreateWithName(string);
NSMutableAttributedString *string11 = [[NSMutableAttributedString alloc]
initWithString:textToDraw];
[string11 addAttribute:(id)kCTForegroundColorAttributeName
value:(id)[UIColor redColor].CGColor
range:NSMakeRange(0, [string11 length])];
CTFramesetterRef framesetter =
CTFramesetterCreateWithAttributedString(currentText);
CGMutablePathRef framePath = CGPathCreateMutable();
CGPathAddRect(framePath, NULL, frameRect);
CFRange currentRange = CFRangeMake(0, 0);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange,
framePath, NULL);
CGPathRelease(framePath);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
CGContextTranslateCTM(currentContext, 0, frameRect.origin.y*2);
CGContextScaleCTM(currentContext, 1.0, -1.0);
CTFrameDraw(frameRef, currentContext);
CGContextScaleCTM(currentContext, 1.0, -1.0);
CGContextTranslateCTM(currentContext, 0, (-1)*frameRect.origin.y*2);
CFRelease(frameRef);
//CFRelease(currentText);
CFRelease(framesetter);
//CFRelease(stringRef);
}
but text color not changing.please help me how to do it?
I have different label and i have to set different color for different label .
Try replacing this code:
CGColorSpaceCreateWithName(string);
NSMutableAttributedString *string11 = [[NSMutableAttributedString alloc]
initWithString:textToDraw];
[string11 addAttribute:(id)kCTForegroundColorAttributeName
value:(id)[UIColor redColor].CGColor
range:NSMakeRange(0, [string11 length])];
with:
CFAttributedStringSetAttribute(currentText,CFRangeMake(0, length),kCTForegroundColorAttributeName,[UIColor redColor].CGColor);
I am working on PDF generation functionality below functionality working fine in iOS 6 but not working in iOS7, so please help me regarding same issue.
(float) drawText:(NSString *)body currentVehical:(NSInteger)currentVehical{
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(currentContext, 0.0, 0.0, 0.0, 1.0);
UIFont *font = [UIFont systemFontOfSize:14.0];
NSLog(#" FRame : \n%f\n%f",(self.pageSize.width - 2*kBorderInset-2*kMarginInset),
(self.pageSize.height - 2*kBorderInset - 2*kMarginInset));
CGSize stringSize = [body sizeWithFont:font
constrainedToSize:CGSizeMake(self.pageSize.width - 2*kBorderInset-2*kMarginInset, self.pageSize.height - 2*kBorderInset - 2*kMarginInset)
lineBreakMode:NSLineBreakByWordWrapping];
CGRect renderingRect = CGRectMake(120,10+self.yCord, self.pageSize.width - 120,stringSize.height+KExtraSpaces);
NSLog(#"PDF draw rect: %#",NSStringFromCGRect(renderingRect));
if (IS_IOS7) {
NSMutableParagraphStyle *paragraphstyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphstyle.lineBreakMode = NSLineBreakByWordWrapping;
paragraphstyle.alignment = NSTextAlignmentLeft;
NSDictionary * attributes = #{ NSFontAttributeName:font, NSParagraphStyleAttributeName: paragraphstyle };
//[body drawInRect:renderingRect withAttributes:attributes];
NSStringDrawingContext *context = [NSStringDrawingContext new];
context.minimumScaleFactor = 0.1;
NSLog(#"body :%#",body);
[body drawWithRect:renderingRect options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:context];
}else{
[body drawInRect:renderingRect withFont:font lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentLeft];
}
return stringSize.height;
}
Thanks in advance.
I recall having a similar problem with a pdf renderer when compiling for iOS7, when it worked perfectly for ios6.1. I seem to remember that the font size was the issue, debug your routine and check font sizes and subsequent frame sizes. Apologies that I can't be more specific, as solved it 3 months ago and forgotten.
Hope this code helps:
+(void)drawTableDataAt:(Survey*)survey columns:(NSMutableArray*)savedColumns listContent:(NSArray*)surveyListContent withOrigin:(CGPoint)origin andRowCount:(int*)count andMaxRowOnPage:(int)size andLinesPerPage:(int)linesPerPage andColumnWidths:(NSMutableArray*)columnWidths withFont:(UIFont*)theFont withLabelFont:(UIFont*)theLabelFont
{
float rowHeight = theFont.lineHeight+3.0;
float padding = -5.0f;
// ………..
CGRect frame = CGRectMake(originX + padding, originY, [[columnWidths objectAtIndex:j] integerValue], rowHeight);
[self drawText:strValue inFrame:frame withFont:theFont withAlignment:kCTRightTextAlignment];
// ………..
}
+(void)drawText:(NSString*)textToDraw inFrame:(CGRect)frameRect withFont:(UIFont*)theFont withAlignment:(CTTextAlignment)textAlignment
{
CFStringRef stringRef = (__bridge_retained CFStringRef)textToDraw;
NSString *fontName = [theFont fontName];
CGFloat fontSize = [theFont pointSize];
// Set Font
CTFontRef font = CTFontCreateWithName( (__bridge CFStringRef)fontName, fontSize, NULL);
CTParagraphStyleSetting settings[ASD_ParagraphStylesSupported];
settings[0].spec = kCTParagraphStyleSpecifierAlignment;
settings[0].valueSize = sizeof(CTTextAlignment);
settings[0].value = &textAlignment;
CTParagraphStyleRef style = CTParagraphStyleCreate((const CTParagraphStyleSetting*) &settings, ASD_ParagraphStylesSupported);
// Create an attributed string
CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName, kCTParagraphStyleAttributeName };
CFTypeRef values[] = { font, [[UIColor blackColor] CGColor], style };
CFDictionaryRef attrs = CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&values,
sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
// Prepare the text using a Core Text Framesetter with Attributes
CFAttributedStringRef currentText = CFAttributedStringCreate(NULL, stringRef, attrs);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(currentText);
CGMutablePathRef framePath = CGPathCreateMutable();
CGPathAddRect(framePath, NULL, frameRect);
// Get the frame that will do the rendering.
CFRange currentRange = CFRangeMake(0, 0);
CTFrameRef frameRef = CTFramesetterCreateFrame(framesetter, currentRange, framePath, NULL);
CGPathRelease(framePath);
// Get the graphics context.
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// Put the text matrix into a known state. This ensures
// that no old scaling factors are left in place.
CGContextSetTextMatrix(currentContext, CGAffineTransformIdentity);
// Core Text draws from the bottom-left corner up, so flip
// the current transform prior to drawing.
CGContextTranslateCTM(currentContext, 0, frameRect.origin.y*2);
CGContextScaleCTM(currentContext, 1.0, -1.0);
// Draw the frame.
CTFrameDraw(frameRef, currentContext);
CGContextScaleCTM(currentContext, 1.0, -1.0);
CGContextTranslateCTM(currentContext, 0, (-1)*frameRect.origin.y*2);
CFRelease(settings);
CFRelease(attrs);
CFRelease(style);
CFRelease(font);
CFRelease(frameRef);
CFRelease(stringRef);
CFRelease(framesetter);
}