2015-03-13 91 views
2

編輯:Here's a Github Gist如果這是更具可讀性的代碼。核心文本中的垂直文本對齊

我正在寫一個方法來使用核心文本在PDF中的矩形內繪製文本。我寫的東西完成了我所需要的一切,除了垂直對齊(頂部,中間,底部)。目前正在繪製文本的標準方式是頂部,我特別需要底部對齊。

- (void)drawText:(NSString *)textToDraw inFrame:(CGRect)frameRect withFont:(UIFont *)originalFont textColor:(UIColor *)textColor alignment:(PDFTextAlignment)alignment verticalAlignment:(PDFTextVerticalAlignment)verticalAlignment { 

    if (!textToDraw) { 
     // If nil, give it an empty value to draw 
     textToDraw = @""; 
    } 


    // Prepare font 
    CTFontRef font = [self 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); 

    CFRelease(frameRef); 
    CFRelease(stringRef); 
    CFRelease(framesetter); 
    CFRelease(font); 
    CFRelease(paragraphStyle); 
} 

下面是如何將目前在矩形繪製文本的例子(注意與線繪製的矩形是我傳遞在同一frameRect)... enter image description here。 我希望這個文本顯示爲在這個矩形中的底部對齊,像這樣... enter image description here

我已經通過this SO post的解決方案,但沒有任何運氣讓文本正確對齊。

我傳遞了垂直對齊的枚舉值,所以理想情況下我將使用以下條件確定垂直對齊。

if (verticalAlignment == PDFTextVerticalAlignmentTop) { 
    // Top align 
} else if (verticalAlignment == PDFTextVerticalAlignmentCenter) { 
    // Center (vertical) align 
} else if (verticalAlignment == PDFTextVerticalAlignmentBottom) { 
    // Bottom align 
} else { 
    // Default: Bottom alignment 
} 

謝謝!

回答

3

因爲我不太清楚你是如何從鏈接文章中找到解決方案的,我會根據其中一個答案提出解決方案。這可能正是你所嘗試的,但它也可能是適當的解決方案。

我假設存在一種獲取CTFrameRef大小的方法,只要返回適當的CGSize,就將該實現留給您。除了鏈接的SO帖子中顯示的方法之外,還可能需要查看CTFramesetterSuggestFrameSizeWithConstraints。假設這個功能是可用的,它應該是足夠的調整繪圖功能

... 
CGMutablePathRef framePath = CGPathCreateMutable();  

// Get the graphics context. 
CGContextRef currentContext = UIGraphicsGetCurrentContext(); 

CGRect textRect = frameRect; // Will also give you the default behavior for top align 
CGSize textSize = [self measureFrame:frameref forContext:currentContext]; 

if (verticalAlignment == PDFTextVerticalAlignmentBottom) { 
    // Bottom align 
    textRect.size.height = textSize.height; 
    textRect.origin.y = frameRect.origin.y + frameRect.size.height - textSize.height; 
} else if (verticalAlignment == PDFTextVerticalAlignmentCenter) { 
    // Center (vertical) align 
    textRect.size.height = textSize.height; 
    textRect.origin.y = frameRect.origin.y + (frameRect.size.height - textSize.height)/2; 
} 

CGPathAddRect(framePath, NULL, textRect); 
... 
+0

呀,最後我寫的東西非常接近這個的這一部分,採用NSAtrributedString來獲取文本框矩形的大小。我會與本週晚些時候回到這個項目時寫的相比,同時感謝並享受賞金! – timgcarlson 2015-03-22 22:48:34