Арабский текст с пользовательскими шрифтами в iOS - PullRequest
6 голосов
/ 16 сентября 2011

Я работаю над приложением, которое требует отображения арабского текста, используя собственный арабский шрифт.Проблема в том, что мне не повезло в отображении арабского текста с использованием custom арабских шрифтов.Я пытался отобразить текст в UILabel, UITextField, UITextView, UIWebView, FontLabel (от Zynga) и с помощью CoreText.

Примеры проектов можно найти здесь:

Пример приложения с использованием UILabel, UITextField, UITextView и CoreText

Пример приложения с использованием UIWebView (HTML)

Пример приложения с использованием UIWebView (HTML): вам придется установить шрифты в примере проекта.Затем вы можете сравнить результаты и увидеть проблему, запустив приложение в симуляторе (или iPad) и открыв файл Sample.html в браузере (Safari).

Я опубликовал некоторые деталина форуме разработчиков Apple, но я всегда считал, что stackoverflow гораздо более активен, чем официальный форум разработчиков Apple.Вот ссылка на этот пост:

Использование пользовательского арабского шрифта в iOS

What am i doing wrong?

Примечание: шрифты загружены в систему правильно, и я могу успешно применитьПользовательские шрифты для обычного (английского) текста.

ps В stackoverflow есть пара постов, посвященных этой теме, но ни одна из них не помогла, поэтому я публикую новый вопрос.

Ответы [ 5 ]

8 голосов
/ 24 ноября 2011

Обновление:

Начиная с iOS 7, вам не нужно использовать Core Text для рендеринга нестандартного арабского шрифта.Вы можете использовать UILabel и / или UITextView с NSAttributedString.Результаты такие же, как и при использовании Core-Text.Однако, в зависимости от ваших требований, использование Core Text может быть лучшим вариантом.

Обновление:

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

Исходное сообщение

Мне удалось создать приложение для Корана, в котором используется пользовательский арабский шрифт.Я использовал известные арабские шрифты с Core Text framework для получения желаемых результатов.Вы можете увидеть результаты, которые я получил в итоге, проверив приложение Quran Presenter для iPad , которое доступно в App Store.

Вот пример кода, который поможет вам:

- (CTFontRef)newCustomFontWithName:(NSString *)aFontName
                            ofType:(NSString *)type
                        attributes:(NSDictionary *)attributes {
    NSString *fontPath = [[NSBundle mainBundle] pathForResource:aFontName ofType:type];

    NSData *data = [[NSData alloc] initWithContentsOfFile:fontPath];
    CGDataProviderRef fontProvider = CGDataProviderCreateWithCFData((CFDataRef)data);
    [data release];

    CGFontRef cgFont = CGFontCreateWithDataProvider(fontProvider);
    CGDataProviderRelease(fontProvider);

    CTFontDescriptorRef fontDescriptor = CTFontDescriptorCreateWithAttributes((CFDictionaryRef)attributes);
    CTFontRef font = CTFontCreateWithGraphicsFont(cgFont, 0, NULL, fontDescriptor);
    CFRelease(fontDescriptor);
    CGFontRelease(cgFont);
    return font;
}

- (CATextLayer *)customCATextLayer {
    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                [NSNumber numberWithFloat:24.f], (NSString *)kCTFontSizeAttribute,
                                [NSNumber numberWithInt:1], (NSString *)kCTLigatureAttributeName,
                                nil];

    CTFontRef font = [self newCustomFontWithName:@"PDMS_Saleem_QuranFont-signed" 
                                          ofType:@"ttf" 
                                      attributes:attributes];

    CATextLayer *normalTextLayer = [[CATextLayer alloc] init];
    normalTextLayer.font = font;
    normalTextLayer.string = NSLocalizedString(@"Sample", nil);
    normalTextLayer.wrapped = YES;
    normalTextLayer.foregroundColor = [[UIColor blackColor] CGColor];
    normalTextLayer.fontSize = 24.f;
    normalTextLayer.alignmentMode = kCAAlignmentCenter;
    normalTextLayer.frame = CGRectMake(0.f, 10.f, 320.f, 32.f);

    CFRelease(font);
    return [normalTextLayer autorelease];
}

- (void)viewDidLoad {
    [super viewDidLoad];

    CATextLayer *normalTextLayer = [self customCATextLayer];
    [self.customView.layer addSublayer:normalTextLayer];
}

Обратите внимание, что я использую CATextLayer и CTFontRef.Есть несколько проблем с этим подходом.1. Вам придется жить с проблемами в выбранном «пользовательском арабском шрифте».2. Вам придется использовать арабский текст, который использует расширенные символы, поддерживаемые шрифтом.

HTH.

3 голосов
/ 21 ноября 2013

Я впервые начал изучать разработку для iOS еще в середине 2012 года, и я искал повсюду в Интернете, чтобы найти правильное решение для пользовательских персидских шрифтов в iPhone, и никогда не мог найти правильное решение.Была библиотека Core Text, которую я пробовал однажды, и она не всегда работала нормально, особенно если вам нужно было добавить дополнительно subview, чтобы добавить свой текст с пользовательским шрифтом.Я попробовал Arabic Converter некоторое время назад, и он работал нормально, но с новым Xcode он вообще не вносил изменений в текст, кроме веб-представлений, и он только работал неправильно!

Итак.В любом случае, я рад, что Apple решает проблемы с поддержкой большего количества языков.Теперь вот очень простое решение, которое прекрасно работает:

  1. Перейдите к файлу info.plist вашего проекта,
  2. Щелкните правой кнопкой мыши и выберите Add row,
  3. ТипFonts provided by application в новой строке,
  4. Введите имя нужного шрифта в качестве элементов для этого ключа.

enter image description here

Перетащите файл шрифта в проект, Примените его к нужному тексту:

UITextView *persianText; persianText.text = @"در جستجوی قهرمان نباشید \nبلکه خود قهرمان شوید"; persianText.font = [UIFont fontWithName:@"IranNastaliq" size: 12.0];

Annnd ...!Сборка и запуск ... Тадааа!Работает!

enter image description here

3 голосов
/ 12 сентября 2012

Эти классы сделают свою работу:

https://github.com/Accorpa/Arabic-Converter-From-and-To-Arabic-Presentation-Forms-B

Скачайте их, и я уверен, что это ответит на ваш вопрос, потому что у меня была точно такая же проблема раньше!

Пример кода:

ArabicConverter *converter = [[ArabicConverter alloc] init];
NSString* convertedString = [converter convertArabic:@"منذ دقيقة"];
infoText.font = [UIFont fontWithName:@"YOUARABICFONT" size:16];
infoText.text = convertedString;

Теперь infoText будет правильно отображать шрифт:)

1 голос
/ 06 декабря 2013

Для UIWebview: в основном принятый ответ не относится к делу UIWebView. Итак, вот способ, которым я решил эту проблему.

first: Используя hpple , синтаксический анализатор HTML obj-c, я просмотрел html и в основном удалил текст и добавил его к NSMutableString, например так:

// contentText is the HTML text. The format is just text in <p> tags
NSData *contentData = [contentText dataUsingEncoding:NSUTF8StringEncoding];
TFHpple *htmlParser = [TFHpple hppleWithHTMLData:contentData];
NSString *htmlXpathQueryString = @"//p";
NSArray *newsNodes = [htmlParser searchWithXPathQuery:htmlXpathQueryString];
NSMutableArray *newsParagraphs = [@[] mutableCopy];
NSMutableString *newsContent = [@"" mutableCopy];

for (TFHppleElement *element in newsNodes) {
    NSString *paragraphText = [[element firstChild] content];
    [newsParagraphs addObject:paragraphText];
    [newsContent appendFormat:@"%@\n",paragraphText];
}

// explained below (bodyView is a CTContainerView object)
self.bodyView.contentStr = newsContent;
self.bodyView.callback = ^(CGSize size) {
    [self adjustScrollViewSize:size];
};
[self.bodyView buildFrames];

- (void)adjustScrollViewSize:(CGSize)contentSize {
    CGRect overallSize = CGRectUnion(imageView.frame, titleText.frame);
    CGRect bodyViewFr = self.bodyView.frame;
    CGRect bodyViewWrapperFr = CGRectMake(bodyViewFr.origin.x, 
            bodyViewFr.origin.y, contentSize.width, contentSize.height+30);
    overallSize = CGRectUnion(overallSize, bodyViewWrapperFr);
    self.scrollView.contentSize = overallSize.size;
}

Затем я использовал Core Text для рендеринга текста в веб-просмотр, следуя инструкциям этого учебника. Вот другие файлы:

CTContainerView.h

#import <UIKit/UIKit.h>

typedef void (^CompletionBlock)(CGSize size);
@interface CTContainerView : UIView

@property (nonatomic, strong) NSString *contentStr;
@property (nonatomic, strong) CompletionBlock callback;

- (void)buildFrames;

@end

CTContainerView.m

#import <CoreText/CoreText.h>
#import "CTContainerView.h"
#import "CTView.h"

const float kMargin = 10;

@implementation CTContainerView {
    NSAttributedString* attString;
}

// get the required size for the final view to render
// the complete text of the body.. then pass it on
// to CTContentView
- (void)buildFrames {
    // first build the attributedString with all its properties
    NSString *fontName = @"29LTBukra";  // THE ARABIC FONT NAME!!!!
    CTFontRef fontRef = CTFontCreateWithName((CFStringRef)fontName, 12.0f, NULL);

    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    [paragraphStyle setLineSpacing:6];

    NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)fontRef, kCTFontAttributeName,
                           paragraphStyle, NSParagraphStyleAttributeName, nil];
    attString = [[NSAttributedString alloc] initWithString:self.contentStr attributes:attrs];

    // get the required final view size given attString
    CGRect selfFr = self.frame;
    CGRect textFr = CGRectInset(selfFr, kMargin, kMargin);
    CGSize requiredSize = [self getRequiredViewSizeInViewWithSize:textFr.size];
    requiredSize.height = requiredSize.height + 100;
    CGRect requiredFrame = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, requiredSize.width, requiredSize.height);

    // construct a CTFrameRef based on the 1. attStr and 2. calculated fr above
    CGMutablePathRef path = CGPathCreateMutable(); //1
    CGPathAddRect(path, NULL, requiredFrame);

    CTFramesetterRef framesetter =
    CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attString); //3
    CTFrameRef frame =
    CTFramesetterCreateFrame(framesetter,
                             CFRangeMake(0, [attString length]), path, NULL);

    // adjust size of container
    selfFr.size = requiredSize;
    self.frame = selfFr;

    // create an empty CTContentView
    CTView *ctView = [[CTView alloc] initWithFrame: CGRectMake(5, 0, requiredSize.width, requiredSize.height)];
    [ctView setBackgroundColor:[UIColor whiteColor]];
    [ctView setCtFrame:(__bridge id)(frame)];
    [self addSubview:ctView];
    CFRelease(path);

    // call callback
    self.callback(requiredSize);
}

- (CGSize)getRequiredViewSizeInViewWithSize:(CGSize)viewSize {
    CGRect paragraphRect =
    [attString boundingRectWithSize:CGSizeMake(viewSize.width, CGFLOAT_MAX)
                            options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
                            context:nil];
    return paragraphRect.size;
}

CTContentView.h

#import <UIKit/UIKit.h>

@interface CTView : UIView
@property (nonatomic, strong) id ctFrame;
@end

CTContentView.m

#import <CoreText/CoreText.h>
#import "CTView.h"

@implementation CTView

@synthesize ctFrame;

-(void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();

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

    CTFrameDraw((CTFrameRef)ctFrame, context);
}

@end
1 голос
/ 26 июня 2013

Если вы ориентируетесь на iOS 6, вы можете использовать NSAttributedString, чтобы сделать это намного проще:

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:info.text attributes:@{ NSFontAttributeName : [UIFont fontWithName:@"Scheherazade" size:32], NSLigatureAttributeName: @2}];

cell.textLabel.attributedText = attributedString;

Обратитесь к моему ответу здесь для некоторых обсуждений по другим вопросам, обычно связанным с арабскими шрифтами, таким как межстрочный интервал и лигатуры.

...