2011年1月20日星期四

iphone开发中文章显示的一种排版技术


1。绘制简单的一行文字

- (void)drawRect:(CGRect)rect
{
// create a font, quasi systemFontWithSize:24.0
CTFontRef sysUIFont = CTFontCreateUIFontForLanguage(kCTFontSystemFontType,
24.0, NULL);

// create a naked string
NSString *string = @"Some Text";

// blue
CGColorRef color = [UIColor blueColor].CGColor;

// single underline
NSNumber *underline = [NSNumber numberWithInt:kCTUnderlineStyleSingle];

// pack it into attributes dictionary
NSDictionary *attributesDict = [NSDictionary dictionaryWithObjectsAndKeys:
(id)sysUIFont, (id)kCTFontAttributeName,
color, (id)kCTForegroundColorAttributeName,
underline, (id)kCTUnderlineStyleAttributeName, nil];

// make the attributed string
NSAttributedString *stringToDraw = [[NSAttributedString alloc] initWithString:string
attributes:attributesDict];

// now for the actual drawing
CGContextRef context = UIGraphicsGetCurrentContext();

// flip the coordinate system
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

// draw
CTLineRef line = CTLineCreateWithAttributedString(
(CFAttributedStringRef)stringToDraw);
CGContextSetTextPosition(context, 10.0, 10.0);
CTLineDraw(line, context);

// clean up
CFRelease(line);
CFRelease(sysUIFont);
[stringToDraw release];
}
2。实现分列的文本显示
实现的效果如下:




- (void)drawRect:(CGRect)rect
{
NSString *longText = @"Lorem ipsum dolor sit amet, "; /* ... */

NSMutableAttributedString *string = [[NSMutableAttributedString alloc]
initWithString:longText];

// make a few words bold
CTFontRef helvetica = CTFontCreateWithName(CFSTR("Helvetica"), 14.0, NULL);
CTFontRef helveticaBold = CTFontCreateWithName(CFSTR("Helvetica-Bold"), 14.0, NULL);

[string addAttribute:(id)kCTFontAttributeName
value:(id)helvetica
range:NSMakeRange(0, [string length])];

[string addAttribute:(id)kCTFontAttributeName
value:(id)helveticaBold
range:NSMakeRange(6, 5)];

[string addAttribute:(id)kCTFontAttributeName
value:(id)helveticaBold
range:NSMakeRange(109, 9)];

[string addAttribute:(id)kCTFontAttributeName
value:(id)helveticaBold
range:NSMakeRange(223, 6)];

// add some color
[string addAttribute:(id)kCTForegroundColorAttributeName
value:(id)[UIColor redColor].CGColor
range:NSMakeRange(18, 3)];

[string addAttribute:(id)kCTForegroundColorAttributeName
value:(id)[UIColor greenColor].CGColor
range:NSMakeRange(657, 6)];

[string addAttribute:(id)kCTForegroundColorAttributeName
value:(id)[UIColor blueColor].CGColor
range:NSMakeRange(153, 6)];

// layout master
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(
(CFAttributedStringRef)string);

// left column form
CGMutablePathRef leftColumnPath = CGPathCreateMutable();
CGPathAddRect(leftColumnPath, NULL,
CGRectMake(0, 0,
self.bounds.size.width/2.0,
self.bounds.size.height));

// left column frame
CTFrameRef leftFrame = CTFramesetterCreateFrame(framesetter,
CFRangeMake(0, 0),
leftColumnPath, NULL);

// right column form
CGMutablePathRef rightColumnPath = CGPathCreateMutable();
CGPathAddRect(rightColumnPath, NULL,
CGRectMake(self.bounds.size.width/2.0, 0,
self.bounds.size.width/2.0,
self.bounds.size.height));

NSInteger rightColumStart = CTFrameGetVisibleStringRange(leftFrame).length;

// right column frame
CTFrameRef rightFrame = CTFramesetterCreateFrame(framesetter,
CFRangeMake(rightColumStart, 0),
rightColumnPath,
NULL);

// flip the coordinate system
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

// draw
CTFrameDraw(leftFrame, context);
CTFrameDraw(rightFrame, context);

// cleanup
CFRelease(leftFrame);
CGPathRelease(leftColumnPath);
CFRelease(rightFrame);
CGPathRelease(rightColumnPath);
CFRelease(framesetter);
CFRelease(helvetica);
CFRelease(helveticaBold);
[string release];
}

布局功能:

下划线功能:
// pack it into attributes dictionary
NSDictionary *attributesDict = [NSDictionary dictionaryWithObjectsAndKeys:
(id)sysUIFont, (id)kCTFontAttributeName,
color, (id)kCTForegroundColorAttributeName,
underline, (id)kCTUnderlineStyleAttributeName, nil];

Underlining is not a feature of the font itself, but of NSAttributedString, likely because you can underline text in ANY font. These are your options:

None

Single Line

Double Line

Thick Line



These can be bitwise OR combined with several underlining line styles:

Solid Line

Dotted Line

Dashed Line

Dash-Dotted Line

Dash-Dot-Dotted Lin



删除线功能
// add custom attribute
[string addAttribute:@"DTCustomStrikeOut"
  value:[NSNumber numberWithBool:YES]
  range:NSMakeRange(18, 138)];


// reset text position
CGContextSetTextPosition(context, 0, 0);

// get lines
CFArrayRef leftLines = CTFrameGetLines(leftFrame);
CGPoint *origins = malloc(sizeof(CGPoint)*[(NSArray *)leftLines count]);
CTFrameGetLineOrigins(leftFrame,
CFRangeMake(0, 0), origins);
NSInteger lineIndex = 0;

for (id oneLine in (NSArray *)leftLines)
{
CFArrayRef runs = CTLineGetGlyphRuns((CTLineRef)oneLine);
CGRect lineBounds = CTLineGetImageBounds((CTLineRef)oneLine, context);

lineBounds.origin.x += origins[lineIndex].x;
lineBounds.origin.y += origins[lineIndex].y;
lineIndex++;
CGFloat offset = 0;

for (id oneRun in (NSArray *)runs)
{
CGFloat ascent = 0;
CGFloat descent = 0;

CGFloat width = CTRunGetTypographicBounds((CTRunRef) oneRun,
CFRangeMake(0, 0),
&ascent,
&descent, NULL);

NSDictionary *attributes = (NSDictionary *)CTRunGetAttributes((CTRunRef) oneRun);

BOOL strikeOut = [[attributes objectForKey:@"DTCustomStrikeOut"] boolValue];

if (strikeOut)
{
CGRect bounds = CGRectMake(lineBounds.origin.x + offset,
lineBounds.origin.y,
width, ascent + descent);

// don't draw too far to the right
if (bounds.origin.x + bounds.size.width > CGRectGetMaxX(lineBounds))
{
bounds.size.width = CGRectGetMaxX(lineBounds) - bounds.origin.x;
}

// get text color or use black
id color = [attributes objectForKey:(id)kCTForegroundColorAttributeName];

if (color)
{
CGContextSetStrokeColorWithColor(context, (CGColorRef)color);
}
else
{
CGContextSetGrayStrokeColor(context, 0, 1.0);
}

CGFloat y = roundf(bounds.origin.y + bounds.size.height / 2.0);
CGContextMoveToPoint(context, bounds.origin.x, y);
CGContextAddLineToPoint(context, bounds.origin.x + bounds.size.width, y);

CGContextStrokePath(context);
}

offset += width;
}
}

// cleanup
free(origins);


详细介绍:

http://www.cocoanetics.com/2011/01/befriending-core-text/
发表评论