Как я могу рассчитать (без поиска) размер шрифта, чтобы соответствовать прямоугольнику? - PullRequest
4 голосов
/ 01 сентября 2011

Я хочу, чтобы мой текст помещался в определенном прямоугольнике, поэтому мне нужно что-то определить размер шрифта. Вопросы уже решали эту проблему в некоторой степени, но они выполняют поиск, который кажется ужасно неэффективным, особенно если вы хотите иметь возможность вычислять во время изменения размера при перетаскивании в реальном времени. Следующий пример может быть улучшен для бинарного поиска и ограничения по высоте, но это все еще поиск. Вместо того, чтобы искать, как я могу вычислить размер шрифта, чтобы соответствовать прямоугольнику?

#define kMaxFontSize    10000

- (CGFloat)fontSizeForAreaSize:(NSSize)areaSize withString:(NSString *)stringToSize usingFont:(NSString *)fontName;
{
    NSFont * displayFont = nil;
    NSSize stringSize = NSZeroSize;
    NSMutableDictionary * fontAttributes = [[NSMutableDictionary alloc] init];

    if (areaSize.width == 0.0 && areaSize.height == 0.0)
        return 0.0;

    NSUInteger fontLoop = 0;
    for (fontLoop = 1; fontLoop <= kMaxFontSize; fontLoop++) {
        displayFont = [[NSFontManager sharedFontManager] convertWeight:YES ofFont:[NSFont fontWithName:fontName size:fontLoop]];
        [fontAttributes setObject:displayFont forKey:NSFontAttributeName];
        stringSize = [stringToSize sizeWithAttributes:fontAttributes];

        if (stringSize.width > areaSize.width)
            break;
        if (stringSize.height > areaSize.height)
            break;
    }

    [fontAttributes release], fontAttributes = nil;

    return (CGFloat)fontLoop - 1.0;
}

1 Ответ

12 голосов
/ 01 сентября 2011

Выберите любой размер шрифта и измерьте размер текста.Разделите каждое из его измерений (ширину и высоту) на одно и то же измерение целевого прямоугольника, а затем разделите размер шрифта на больший коэффициент.

Обратите внимание, что текст будет измеряться в одной строке, так как не существует максимумаширина для этого, чтобы обернуть.Для длинной строки / строки это может привести к неоправданно маленькому размеру шрифта.Для текстового поля вы должны просто установить минимальный размер (например, небольшой размер системного шрифта) и установить режим усечения поля.Если вы намереваетесь обернуть текст, вам нужно измерить его чем-то, что принимает ограничивающий прямоугольник или размер.

Код, который задает вопрос, ориентировочно основан на этой идее:

-(float)scaleToAspectFit:(CGSize)source into:(CGSize)into padding:(float)padding
{
    return MIN((into.width-padding) / source.width, (into.height-padding) / source.height);
}

-(NSFont*)fontSizedForAreaSize:(NSSize)size withString:(NSString*)string usingFont:(NSFont*)font;
{
    NSFont* sampleFont = [NSFont fontWithDescriptor:font.fontDescriptor size:12.];//use standard size to prevent error accrual
    CGSize sampleSize = [string sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:sampleFont, NSFontAttributeName, nil]];
    float scale = [self scaleToAspectFit:sampleSize into:size padding:10];
    return [NSFont fontWithDescriptor:font.fontDescriptor size:scale * sampleFont.pointSize];
}

-(void)windowDidResize:(NSNotification*)notification
{
    text.font = [self fontSizedForAreaSize:text.frame.size withString:text.stringValue usingFont:text.font];
}
...