在iPhone上,如何根据给定的点大小计算字符的像素大小?
点大小被定义为1英寸的1/72。也就是说,72点字体的高度从最低处到最高处大约为1英寸。所以,在72pt字体中,字形的最大高度约为1英寸。
苹果的iPhone技术规格页面声称iPhone目前的分辨率为每英寸163像素。因此,72点等于163像素,约为每点2.2639像素。但请记住,每个字形的高度和宽度都会有所不同,因此这只是一个非常粗略的尺寸估计。通常,基线之间的距离会比字体的点大小稍大一些,以避免文本行相互碰撞。
如果你需要准确的测量(而你可能需要),那么你需要使用字体度量信息来实际测量字形。你可以使用NSString的UIKit补充来实现这一点,这将让你在屏幕上渲染特定字符串时测量其大小。
我们的图形设计师在某些设备上使用像素大小而不是点大小非常具体。 下面的函数将返回基于像素大小的字体。 它使用暴力方法来查找最接近的字体,但然后缓存结果,所以下次返回将非常快。我总是很感激关于如何改进此代码的评论。我将此函数用作名为utils的类中的静态类成员。 您可以轻松地粘贴到任何正在使用的类中。 希望它有所帮助。
/** return a font as close to a pixel size as possible
example:
UIFont *font = [Utils fontWithName:@"HelveticaNeue-Medium" sizeInPixels:33];
@param fontName name of font same as UIFont fontWithName
@param sizeInPixels size in pixels for font
*/
+(UIFont *) fontWithName:(NSString *) fontName sizeInPixels:(CGFloat) pixels {
static NSMutableDictionary *fontDict; // to hold the font dictionary
if ( fontName == nil ) {
// we default to @"HelveticaNeue-Medium" for our default font
fontName = @"HelveticaNeue-Medium";
}
if ( fontDict == nil ) {
fontDict = [ @{} mutableCopy ];
}
// create a key string to see if font has already been created
//
NSString *strFontHash = [NSString stringWithFormat:@"%@-%f", fontName , pixels];
UIFont *fnt = fontDict[strFontHash];
if ( fnt != nil ) {
return fnt; // we have already created this font
}
// lets play around and create a font that falls near the point size needed
CGFloat pointStart = pixels/4;
CGFloat lastHeight = -1;
UIFont * lastFont = [UIFont fontWithName:fontName size:.5];\
NSMutableDictionary * dictAttrs = [ @{ } mutableCopy ];
NSString *fontCompareString = @"Mgj^";
for ( CGFloat pnt = pointStart ; pnt < 1000 ; pnt += .5 ) {
UIFont *font = [UIFont fontWithName:fontName size:pnt];
if ( font == nil ) {
NSLog(@"Unable to create font %@" , fontName );
NSAssert(font == nil, @"font name not found in fontWithName:sizeInPixels" ); // correct the font being past in
}
dictAttrs[NSFontAttributeName] = font;
CGSize cs = [fontCompareString sizeWithAttributes:dictAttrs];
CGFloat fheight = cs.height;
if ( fheight == pixels ) {
// that will be rare but we found it
fontDict[strFontHash] = font;
return font;
}
if ( fheight > pixels ) {
if ( lastFont == nil ) {
fontDict[strFontHash] = font;
return font;
}
// check which one is closer last height or this one
// and return the user
CGFloat fc1 = fabs( fheight - pixels );
CGFloat fc2 = fabs( lastHeight - pixels );
// return the smallest differential
if ( fc1 < fc2 ) {
fontDict[strFontHash] = font;
return font;
} else {
fontDict[strFontHash] = lastFont;
return lastFont;
}
}
lastFont = font;
lastHeight = fheight;
}
NSAssert( false, @"Hopefully should never get here");
return nil;
}
@"Ap"
来确保它包含下降线和上升线。)- (CGFloat)heightForFont:(UIFont *)font
{
NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
CGRect boundingRect = [@"Ap" boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:context];
return boundingRect.size.height;
}
无法可靠地将点转换为像素,因为每个显示器的ppi(每英寸点数)都会有所不同。请阅读以下内容;
话虽如此,一些人已经制作了一些参考表格和计算器,可能会让您有所启发;
http://www.unitconversion.org/typography/postscript-points-to-pixels-x-conversion.html
您可以通过渲染NSAttributedString
并获取其大小来动态计算像素大小。
extension UIFont {
var pixelSize: CGFloat {
let string = "AWZgjpq"
let attributedString = NSMutableAttributedString(string: string)
attributedString.setAttributes([.font: self], range: NSRange(location: 0, length: string.count))
return attributedString.size().height
}
}
进一步的优化可能是添加一个查找字典和缓存结果,或者将测试字符串不作为变量(但调用本身非常快)。此外,如果您的字体具有一些非常不规则的字形,也可以将它们添加到测试字符串中。
用法:let pixelSize = label.font.pixelSize