Search code examples
iosobjective-ccore-text

iOS: Draw a text at a point in a rectangle


I'm using core text API to draw text on UI. (I don't know other methods, because most Google search results lead me to core text api).

I have read some tutorials online about using core text API. In those tutorial, I see step by step to config from matrix, attribute string to framesetter ... but none of them explain carefully meaning of each step, so I cannot modify by myself.

Below code is the function draw text on screen with (x,y) is the location which I want to draw. This piece of code describe clearly step by step do draw on screen. Nevertheless I don't know where to put x and y parameters, so text will start to draw at this point in rectangle.

// draw text on screen.
+ (void)drawText:(CGContextRef)context bound:(CGRect)rect text:(NSString *)text x:(float)x y:(float) y color:(UIColor *)color size:(float)textSize{
    CGContextSaveGState(context);
    // always remember to reset the text matrix before drawing.
    // otherwise the result will be unpredictable like using uninitialize memory
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextSetTextMatrix(context, CGAffineTransformMakeScale(1.0f, -1.0f));
    // Flip the coordinate system. because core Text uses different coordinate system with UI Kit
    CGContextTranslateCTM(context, 0, rect.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    // step 1: prepare attribute string
    NSDictionary *attributes;
    attributes = @{
            (NSString *) kCTFontAttributeName            : [UIFont fontWithName:@"Helvetica" size:textSize],
            (NSString *) kCTForegroundColorAttributeName : color
    };

    NSAttributedString *str = [[NSAttributedString alloc]
                               initWithString:text attributes:attributes];

    CFAttributedStringRef attrString = (__bridge CFAttributedStringRef)str;

    // step 2: create CTFFrameSetter
    CTFramesetterRef framesetter =
    CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrString);

    // step 3. create CGPath
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, rect);

    // step 4. get the frame
    // use the CGPath and CTFrameSetter to create CTFrame. then drawn it in currently context
    CTFrameRef frame = CTFramesetterCreateFrame
            (framesetter, CFRangeMake(0, 0), path, NULL);

    CTFrameDraw(frame, context);

    // step 5. release resource
    //CFRelease(attrString);
    CFRelease(framesetter);
    CFRelease(frame);
    CFRelease(path);

    CGContextRestoreGState(context);
}

Moreover, I see there are function: CGContextSetTextPosition This seem what I need, but where should I put in above code. I have tried some, but no succeed. Please tell me how to fix this.

Thanks :)


Solution

  • This is not CoreText solution but after your comment under your question I assume this would be a proper answer.

    Basic text drawing on a view.

    .h

    #import <UIKit/UIKit.h>
    
    @interface aView : UIView
    @end
    

    .m

    #import "aView.h"
    
    @implementation aView
    
    - (void)drawText:(CGFloat)xPosition yPosition:(CGFloat)yPosition canvasWidth:(CGFloat)canvasWidth canvasHeight:(CGFloat)canvasHeight
    {
        //Draw Text 
        CGRect textRect = CGRectMake(xPosition, yPosition, canvasWidth, canvasHeight);
        NSMutableParagraphStyle* textStyle = NSMutableParagraphStyle.defaultParagraphStyle.mutableCopy;
        textStyle.alignment = NSTextAlignmentLeft;
    
        NSDictionary* textFontAttributes = @{NSFontAttributeName: [UIFont fontWithName: @"Helvetica" size: 12], NSForegroundColorAttributeName: UIColor.redColor, NSParagraphStyleAttributeName: textStyle};
    
        [@"Hello, World!" drawInRect: textRect withAttributes: textFontAttributes];
    }
    
    
    - (void)drawRect:(CGRect)rect {
        [self drawText:0 yPosition:0 canvasWidth:200 canvasHeight:150];
    }
    
    @end