Swift - Drawing Text with Drawinrect:Withattributes:

Swift - Drawing text with drawInRect:withAttributes:

The problem is that font is optional because the convenience contructors now return optional values, so font needs to be unwrapped to be a value in your dictionary:

if let actualFont = font {
let textFontAttributes = [
NSFontAttributeName: actualFont,
NSForegroundColorAttributeName: textColor,
NSParagraphStyleAttributeName: textStyle
]

text.drawInRect(NSOffsetRect(textRect, 0, 1), withAttributes: textFontAttributes)
}

Swift 3 - NSString.draw(in: rect, withAttributes:) -- Text not being drawn at expected point

How are you setting atPoint? If you are using the same coordinate space as the screen, that won't work... which is what I suspect is happening.

Suppose your image is 1000 x 2000, and you are showing it in a UIImageView that is 100 x 200. If you tap at x: 50 y: 100 in the view (at the center), and then send that point to your function, it will draw the text at x: 50 y: 100 of the image -- which will be in the upper-left corner, instead of in the center.

So, you need to convert your point from the Image View size to the actual image size.. either before you call your function, or by modifying your function to handle it.

An example (not necessarily the best way to do it):

    // assume:
// View Size is 100 x 200
// Image Size is 1000 x 2000
// tapPoint is CGPoint(x: 50, y: 100)

let xFactor = image.size.width / imageView.frame.size.width
// xFactor now equals 10

let yFactor = image.size.height / imageView.frame.size.height
// yFactor now equals 10

let convertedPoint = CGPoint(x: tapPoint.x * xFactor, y: tapPoint.y * yFactor)

convertedPoint now equals CGPoint(x: 500, y: 1000), and you can send that as the atPoint value in your call to addTextToImage.

drawInRect: withAttributes text center vertically or put some padding

First you need to calculate the height of the text, with this information and the height of your bounding rectangle, you can easily compute the new rectangle to center the text.

I will share a piece of code I use to center vertically. In my case I use a different drawInRect function (drawInRect:withFont...) and I use sizeWithFont to calculate the size of the text. YOu would either adapt this code to use the functions you're already using (with attributes), or either use the functions I'm posting here.

UIFont *font = [UIFont systemFontOfSize:14];
CGSize size = [text sizeWithFont:font];
if (size.width < rect.size.width)
{
CGRect r = CGRectMake(rect.origin.x,
rect.origin.y + (rect.size.height - size.height)/2,
rect.size.width,
(rect.size.height - size.height)/2);
[text drawInRect:r withFont:font lineBreakMode:UILineBreakModeClip alignment:UITextAlignmentLeft];
}

Draw text at 90 degree on NSImage

Here is demo of approach with calculable location

demo

class DemoView: NSView {
override func draw(_ rect: NSRect) {

// .. your drawing code here

NSColor.red.set() // just for demo
rect.fill() // just for demo

if let context = NSGraphicsContext.current?.cgContext {
context.saveGState()

let text: NSString = "Hello World"
let attributes = [
NSAttributedString.Key.foregroundColor: NSColor.white,
NSAttributedString.Key.font: NSFont.systemFont(ofSize: 24)
]

let size = text.size(withAttributes: attributes)
context.translateBy(x: size.height, y: (rect.height - size.width) / 2)
context.rotate(by: CGFloat.pi / 2)

text.draw(at: .zero, withAttributes: attributes)

context.restoreGState()
}
}
}

NSString drawInRect:withAttributes: is not drawing text with greater width than the rect in iOS 7.0.3

Try this:

-(void)drawText:(NSString *)string {
// this method must be called after a valid graphic context
// is configured, it can be called in drawRect:, or a bitmap or pdf context is configured.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);

NSDictionary *attrsDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
myFontForContentBold, NSFontAttributeName,
[NSNumber numberWithFloat:1.0], NSBaselineOffsetAttributeName, nil];
NSAttributedString *richText = [[NSAttributedString alloc] initWithString:string attributes:attrsDictionary];

CGRect textRect = [richText boundingRectWithSize:CGSizeMake(400, CGFLOAT_MAX)
options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
context:nil];

textRect = CGRectMake(130, 80, 400, textRect.size.height);

[richText drawInRect:textRect];
}

If you need to draw large chunk of text, consider Text Kit.

The Text Kit approach:

- (void)drawAddressList:(NSArray *)list atPoint:(CGPoint)point {
NSTextStorage *textStorage = [[NSTextStorage alloc] init];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(400.0f, FLT_MAX)];
[textStorage addLayoutManager:layoutManager];
[layoutManager addTextContainer:textContainer];
textContainer.lineFragmentPadding = 0.0f;

NSDictionary *attributes = @{NSFontAttributeName:[UIFont preferredFontForTextStyle:UIFontTextStyleBody]};
// it's a simple attributes for illustration
for (NSString *address in list) {
NSString *buffer = [NSString stringWithFormat:@"%@\n", address];
[textStorage appendAttributedString:[[NSAttributedString alloc] initWithString:buffer attributes:attributes]];
}

[layoutManager ensureLayoutForTextContainer:textContainer];
CGRect rect = [layoutManager usedRectForTextContainer:textContainer];
rect.size.width = 400.0f;
rect.size.height = ceilf(rect.size.height);
rect.origin = point; // this is the frame needed to draw the address list

[layoutManager drawGlyphsForGlyphRange:NSMakeRange(0, textStorage.length) atPoint:point];
}

How to set text color when using drawInRect?

You need to set the color of the text in the "attributes" dictionary you pass in via:

[textContent drawInRect: CGRectInset(textRect, 0, 6) withAttributes:attributes];

My suggest would be:

NSDictionary *attributes = @{ NSFontAttributeName:helveticaFont,
NSParagraphStyleAttributeName:paragraphStyle,
NSForegroundColorAttributeName: [NPSColor whiteColor]}

How to use drawInRect:withAttributes: instead of drawAtPoint:forWidth:withFont:fontSize:lineBreakMode:baselineAdjustment: in iOS 7

You can use NSDictionary and apply attributes like this:

NSFont *font = [NSFont fontWithName:@"Palatino-Roman" size:14.0];

NSDictionary *attrsDictionary =

[NSDictionary dictionaryWithObjectsAndKeys:
font, NSFontAttributeName,
[NSNumber numberWithFloat:1.0], NSBaselineOffsetAttributeName, nil];

Use attrsDictionary as argument.

Refer: Attributed String Programming Guide

Refer: Standard Attributes

SWIFT:
IN String drawInRect is not available but we can use NSString instead:

let font = UIFont(name: "Palatino-Roman", size: 14.0)
let baselineAdjust = 1.0
let attrsDictionary = [NSFontAttributeName:font, NSBaselineOffsetAttributeName:baselineAdjust] as [NSObject : AnyObject]
let str:NSString = "Hello World"
str.drawInRect(CGRectZero, withAttributes: attrsDictionary)

NSString drawInRect:withAttributes: not correctly centered when using NSKernAttributeName

The kerning must be applied only to the first character of each kerning pair.
If you want to display a string with kerning between all n characters then the kerning
attribute must be set for the first n-1 characters.

Instead of:

[text drawInRect:textRect withAttributes:@{NSKernAttributeName: @(self.kerning),
NSForegroundColorAttributeName: textColor,
NSFontAttributeName: font,
NSParagraphStyleAttributeName: paragraphStyle}];

you have to create an attributed string so that you can set the kerning attribute
for a specific range instead of the entire string:

NSMutableAttributedString *as = [[NSMutableAttributedString alloc]
initWithString:text
attributes:@{
NSForegroundColorAttributeName: textColor,
NSFontAttributeName: font,
NSParagraphStyleAttributeName: paragraphStyle}];
[as addAttribute:NSKernAttributeName
value:@(self.kerning)
range:NSMakeRange(0, [text length] - 1)];

[as drawInRect:textRect];

Here the result for the string "1234" and kerning -4.0:

Sample Image



Related Topics



Leave a reply



Submit