core text -...
TRANSCRIPT
![Page 1: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/1.jpg)
Core Textgithub.com/anyvoid/CoreTextDemo
![Page 2: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/2.jpg)
Константин КиселёвВедущий разработчик
![Page 3: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/3.jpg)
Содержание
๏Основы Core Text
• Маркируем области в тексте
• Два столбца• Обтекание текстом
3
![Page 4: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/4.jpg)
Рецепты Юлии Высоцкой
4
![Page 5: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/5.jpg)
Рецепты Юлии Высоцкой
При нажатии на ссылку со временем открывается установка таймера
5
![Page 6: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/6.jpg)
Рецепты Юлии Высоцкой
6
![Page 7: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/7.jpg)
Бар Депозит – Управление Баром
Во время набора имени в поиске участки совпадения
подсвечиваются в выпадающем меню
7
![Page 8: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/8.jpg)
Рендеринг текста
UIKit
Core Text
Quartz Core
8
![Page 9: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/9.jpg)
UIKit
• Ничего сложного
• UIFont
• UILabel, UITextView, UIWebView
• Минимальные возможности настройки отображения
• в iOS 6 можно задавать NSAttributedString !
9
![Page 10: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/10.jpg)
Рендеринг текста
UIKit
Core Text
Quartz Core
10
![Page 11: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/11.jpg)
Quartz Core
• Непосредственная отрисовка глифов• CGFontRef
• Фиксированная информация о шрифте
• Использование — корректировка отображения
11
![Page 12: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/12.jpg)
CGDataProviderRef fontDataProvider = CGDataProviderCreateWithFilename( [fontPath UTF8String] );
CGFontRef font = CGFontCreateWithDataProvider( fontDataProvider );
CGGlyph glyphs[glyphCount];
for ( size_t i = 0; i < glyphCount; ++i ) { ... glyphs[i] = CGFontGetGlyphWithGlyphName( font, glyphName ); ... }
CGContextSetFont( context, font ); CGContextSetFontSize( context, fontSize );
CGContextShowGlyphsAtPoint( context, p.x, p.y, glyphs, glyphCount );
Quartz Core
12
![Page 13: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/13.jpg)
CGDataProviderRef fontDataProvider = CGDataProviderCreateWithFilename( [fontPath UTF8String] );
CGFontRef font = CGFontCreateWithDataProvider( fontDataProvider );
CGGlyph glyphs[glyphCount];
for ( size_t i = 0; i < glyphCount; ++i ) { ... glyphs[i] = CGFontGetGlyphWithGlyphName( font, glyphName ); ... }
CGContextSetFont( context, font ); CGContextSetFontSize( context, fontSize );
CGContextShowGlyphsAtPoint( context, p.x, p.y, glyphs, glyphCount );
Quartz Core
13
![Page 14: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/14.jpg)
CGDataProviderRef fontDataProvider = CGDataProviderCreateWithFilename( [fontPath UTF8String] );
CGFontRef font = CGFontCreateWithDataProvider( fontDataProvider );
CGGlyph glyphs[glyphCount];
for ( size_t i = 0; i < glyphCount; ++i ) { ... glyphs[i] = CGFontGetGlyphWithGlyphName( font, glyphName ); ... }
CGContextSetFont( context, font ); CGContextSetFontSize( context, fontSize );
CGContextShowGlyphsAtPoint( context, p.x, p.y, glyphs, glyphCount );
Quartz Core
14
![Page 15: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/15.jpg)
Рендеринг текста
UIKit
Core Text
Quartz Core
15
![Page 16: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/16.jpg)
Core Text
• Оптимальное сложность/возможности• CTFontRef
• CTFrame, CTLine, CTRun, CTGlyph
• Можно использовать в нескольких потоках, но с ограничениями. . .
16
![Page 17: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/17.jpg)
Core Text
• Все функции
• Объекты, не задающие размещение текста:
- CTFont
- CTFontDescriptor
- ...
• Объекты, задающие размещение:
- CTFrameSetter
- CTTypeSetter
- CTFrame
- CTRun
- CTLine
- ...
Потокобезопасно Непотокобезопасно
17
![Page 18: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/18.jpg)
Core Text
СFAttributedString CTFrameSetter
CTTypeSetter CTFrame
CGPath CTLine
CTLine
CTRun
CTRun
CTGlyph CTGlyph
18
![Page 19: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/19.jpg)
Core Text
• CTFrame – область вывода всего текста
• CTLine – одна строка
• CTRun – последовательность символов с одинаковыми атрибутами
• CTGlyph – один символ шрифта
19
![Page 20: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/20.jpg)
Core Text
CTFrame
CTLine
This is CTRun Next CTRun The End.
20
![Page 21: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/21.jpg)
- (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext();
// Делаем текущую матрицу единичной CGContextSetTextMatrix( context, CGAffineTransformIdentity ); // Добавляем к матрице перенос по вертикали CGContextTranslateCTM( context, 0, rect.size.height ); // Добавляем отражение по вертикали CGContextScaleCTM( context, 1, -1 ); // ...
Core Text
• Отраженная и сдвинутая по вертикали система координат
21
![Page 22: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/22.jpg)
CGFloat width = rect.size.width, height = rect.size.height; CGFloat rect = CGRectMake(0, 0, width, height);
CGMutablePathRef mutablePath = CGPathCreateMutable(); CGPathAddRect( mutablePath, NULL, rect ); CTFrameRef frame = CTFramesetterCreateFrame(
frameSetter, frameRange, mutablePath, NULL );
• Создаем CTFrameSetter из CFAttributedString
• Далее получаем CTFrame, используя CGPath
CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString( attrStr );
Core Text
22
![Page 23: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/23.jpg)
CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString( attrStr );
CGFloat width = rect.size.width, height = rect.size.height; CGFloat rect = CGRectMake(0, 0, width, height);
CGMutablePathRef mutablePath = CGPathCreateMutable(); CGPathAddRect( mutablePath, NULL, rect ); CTFrameRef frame = CTFramesetterCreateFrame(
frameSetter, frameRange, mutablePath, NULL );
• Создаем CTFrameSetter из CFAttributedString
• Далее получаем CTFrame, используя CGPath
Core Text
23
![Page 24: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/24.jpg)
• Полученный CTFrame является моделью, по которой отрисовывается текст в графическом контексте после вызова
• Аналогичные функции для отрисовки отдельных CTLine, CTRun
Core Text
CTFrameDraw( frame, context );
CGContextSetTextPosition(context, p.x, p.y); CTLineDraw(line, context); CTRunDraw(run, context, CFRangeMake(0, 0));
24
![Page 25: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/25.jpg)
• Полученный CTFrame является моделью, по которой отрисовывается текст в графическом контексте после вызова
• Аналогичные функции для отрисовки отдельных CTLine, CTRun
CTFrameDraw( frame, context );
Core Text
CGContextSetTextPosition(context, p.x, p.y); CTLineDraw(line, context); CTRunDraw(run, context, CFRangeMake(0, 0));
25
![Page 26: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/26.jpg)
CTFrameDraw( frame, context );
• Полученный CTFrame является моделью, по которой отрисовывается текст в графическом контексте после вызова
• Аналогичные функции для отрисовки отдельных CTLine, CTRun
Core Text
CGContextSetTextPosition(context, p.x, p.y); CTLineDraw(line, context); CTRunDraw(run, context, CFRangeMake(0, 0));
26
![Page 27: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/27.jpg)
• Проход по всем участкам фрейма: NSArray* lines = (__bridge NSArray *)CTFrameGetLines( frame ); for ( int lineIndex = 0; lineIndex < length; ++lineIndex ) { CTLineRef line =
(__bridge CTLineRef)[lines objectAtIndex: lineIndex];
NSArray* runs = (__bridge NSArray *)CTLineGetGlyphRuns( line );
for ( int runIndex = 0; runIndex < runs.count; ++runIndex ) { CTRunRef run =
(__bridge CTRunRef)[runs objectAtIndex: runIndex]; // ... } }
Core Text
27
![Page 28: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/28.jpg)
• Проход по всем участкам фрейма: NSArray* lines = (__bridge NSArray *)CTFrameGetLines( frame ); for ( int lineIndex = 0; lineIndex < length; ++lineIndex ) { CTLineRef line =
(__bridge CTLineRef)[lines objectAtIndex: lineIndex];
NSArray* runs = (__bridge NSArray *)CTLineGetGlyphRuns( line );
for ( int runIndex = 0; runIndex < runs.count; ++runIndex ) { CTRunRef run =
(__bridge CTRunRef)[runs objectAtIndex: runIndex]; // ... } }
Core Text
28
![Page 29: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/29.jpg)
• Проход по всем участкам фрейма: NSArray* lines = (__bridge NSArray *)CTFrameGetLines( frame ); for ( int lineIndex = 0; lineIndex < length; ++lineIndex ) { CTLineRef line =
(__bridge CTLineRef)[lines objectAtIndex: lineIndex];
NSArray* runs = (__bridge NSArray *)CTLineGetGlyphRuns( line );
for ( int runIndex = 0; runIndex < runs.count; ++runIndex ) { CTRunRef run =
(__bridge CTRunRef)[runs objectAtIndex: runIndex]; // ... } }
Core Text
29
![Page 30: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/30.jpg)
• Проход по всем участкам фрейма: NSArray* lines = (__bridge NSArray *)CTFrameGetLines( frame ); for ( int lineIndex = 0; lineIndex < length; ++lineIndex ) { CTLineRef line =
(__bridge CTLineRef)[lines objectAtIndex: lineIndex];
NSArray* runs = (__bridge NSArray *)CTLineGetGlyphRuns( line );
for ( int runIndex = 0; runIndex < runs.count; ++runIndex ) { CTRunRef run =
(__bridge CTRunRef)[runs objectAtIndex: runIndex]; // ... } }
Core Text
30
![Page 31: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/31.jpg)
Core Texty
x
При определенных
условиях вещество
трансформирует межядерный
фонон
origin
origin + ascent
origin – descent
31
![Page 32: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/32.jpg)
• Получаем origin-ы для строк:
• Получаем frame строки:
• Получаем frame для CTRun:
lineWidth = CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
lineHeight = ascent + descent + leading;
runWidth = CTRunGetTypographicBounds( run, CFRangeMake(0, 0),&runAscent, &runDescent, &runLeading );
topY = lineOrigins[lineIndex].y + ascent;leftX = CTLineGetOffsetForStringIndex(line, runRange.location, NULL);runHeight = runAscent + runDescent + runLeading;
CGPoint lineOrigins[lines.count];CTFrameGetLineOrigins(
frame, CFRangeMake(0, lines.count), lineOrigins);
Core Text
32
![Page 33: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/33.jpg)
• Получаем origin-ы для строк:
• Получаем frame строки:
• Получаем frame для CTRun:
lineWidth = CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
lineHeight = ascent + descent + leading;
runWidth = CTRunGetTypographicBounds( run, CFRangeMake(0, 0),&runAscent, &runDescent, &runLeading );
topY = lineOrigins[lineIndex].y + ascent;leftX = CTLineGetOffsetForStringIndex(line, runRange.location, NULL);runHeight = runAscent + runDescent + runLeading;
CGPoint lineOrigins[lines.count];CTFrameGetLineOrigins(
frame, CFRangeMake(0, lines.count), lineOrigins);
Core Text
33
![Page 34: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/34.jpg)
• Получаем origin-ы для строк:
• Получаем frame строки:
• Получаем frame для CTRun:
lineWidth = CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
lineHeight = ascent + descent + leading;
runWidth = CTRunGetTypographicBounds( run, CFRangeMake(0, 0),&runAscent, &runDescent, &runLeading );
topY = lineOrigins[lineIndex].y + ascent;leftX = CTLineGetOffsetForStringIndex(line, runRange.location, NULL);runHeight = runAscent + runDescent + runLeading;
CGPoint lineOrigins[lines.count];CTFrameGetLineOrigins(
frame, CFRangeMake(0, lines.count), lineOrigins);
Core Text
34
![Page 35: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/35.jpg)
runWidth = CTRunGetTypographicBounds( run, CFRangeMake(0, 0),&runAscent, &runDescent, &runLeading );
topY = lineOrigins[lineIndex].y + ascent;leftX = CTLineGetOffsetForStringIndex(line, runRange.location, NULL);runHeight = runAscent + runDescent + runLeading;
• Получаем origin-ы для строк:
• Получаем frame строки:
• Получаем frame для CTRun:
lineWidth = CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
lineHeight = ascent + descent + leading;
CGPoint lineOrigins[lines.count];CTFrameGetLineOrigins(
frame, CFRangeMake(0, lines.count), lineOrigins);
Core Text
35
![Page 36: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/36.jpg)
• Получаем origin-ы для строк:
• Получаем frame строки:
• Получаем frame для CTRun:
lineWidth = CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
lineHeight = ascent + descent + leading;
runWidth = CTRunGetTypographicBounds( run, CFRangeMake(0, 0),&runAscent, &runDescent, &runLeading );
topY = lineOrigins[lineIndex].y + ascent;leftX = CTLineGetOffsetForStringIndex(line, runRange.location, NULL);runHeight = runAscent + runDescent + runLeading;
CGPoint lineOrigins[lines.count];CTFrameGetLineOrigins(
frame, CFRangeMake(0, lines.count), lineOrigins);
Core Text
36
![Page 37: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/37.jpg)
Core Text
• Полезные свойства параграфов:• межстрочный интервал
• выравнивание по горизонтали
• line break mode
• отступ красной строки
• . . .37
![Page 38: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/38.jpg)
Core Text
• CTParagraphStyleSetting
• CTParagraphStyleRef
CTParagraphStyleSetting parSet[] = { {kCTParagraphStyleSpecifierAlignment, sizeof(value), &value}, {kCTParagraphStyleSpecifierLineSpacing, ...}, {kCTParagraphStyleSpecifierLineBreakMode, ...} ...};
NSInteger optsNum = sizeof(parSet) / sizeof(CTParagraphStyleSetting);
CTParagraphStyleRef parStyle = CTParagraphStyleCreate( parSet, optsNum);
38
![Page 39: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/39.jpg)
Core Text
• Установка свойств параграфов доступна:- iOS < 6: ТОЛЬКО при инициализации
NSAttributedString / NSMutableAttributedString
- iOS 6: можно делать addAttribute у NSMutableAttributedString
39
![Page 40: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/40.jpg)
• Неприятности:
- выделения пишем сами
- анализ текста (html, rtf и чего угодно своего, например, с разбивкой на параграфы) тоже пишем сами
Core Text
40
![Page 41: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/41.jpg)
• Приятности:
✓ огромные возможности по кастомизации вывода текста
✓ очень удобно и быстро, когда нужно использовать UILabel, но цветной или с маркированными участками
✓ Достаточно быстр
Core Text
41
![Page 42: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/42.jpg)
• Тест на скорость:‣ UITableView, 5000 ячеек
‣ В каждой ячейке label с кастомным шрифтом MetaPro-Normal, цвет текста с прозрачностью
‣ iPhone 4, Xcode Instruments -> CA Instrument
Core Text
42
![Page 43: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/43.jpg)
• Тест на скорость:‣ UITableView, 5000 ячеек
‣ В каждой ячейке label с кастомным шрифтом MetaPro-Normal, цвет текста с прозрачностью
‣ iPhone 4, Xcode Instruments -> CA Instrument
Core Text
~ 55–56 fpsUILabel
~ 60 fpsCore Text
43
![Page 44: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/44.jpg)
• Тест на скорость:‣ UITableView, 5000 ячеек
‣ В каждой ячейке label с кастомным шрифтом MetaPro-Normal, цвет текста с прозрачностью
‣ iPhone 4, Xcode Instruments -> CA Instrument
Core Text
~ 55–56 fpsUILabel
~ 60 fpsCore TextCore Text точно не
медленнее44
![Page 45: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/45.jpg)
Содержание
• Основы Core Text
๏Маркируем области в тексте
• Два столбца• Обтекание текстом
45
![Page 46: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/46.jpg)
Маркировка
• Результаты поиска
• Кастомные ссылки в UILabel
➡И все это без UIWebView !
http://anyvoid.ru
46
![Page 47: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/47.jpg)
Маркировка
47
![Page 48: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/48.jpg)
Маркировка
• Создаём наследник UIView:
- selectWithPattern:(NSString *)pattern - метод, который будет создавать модель для маркировки указанного текста
- drawRect:(CGRect)rect - здесь будет непосредственная отрисовка текста с маркировкой
48
![Page 49: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/49.jpg)
Маркировка
[regexp enumerateMatchesInString: ... usingBlock:^(NSTextCheckingResult *result, ...) { // При совпадении куска текста с шаблоном:
// 1. Добавляем участок в список совпадений [ranges addObject: [NSValue valueWithRange: [result range]]];
// 2. Помечаем участок цветом в отдельной атрибутированной строке [attrTextMutable addAttribute: kCTForegroundColorAttributeName value: [UIColor redColor].CGColor range: [result range]]; }];
• Добавляем какой-нибудь атрибут к участкам, которые хотим выделить и сохраняем их в в self.ranges
49
![Page 50: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/50.jpg)
Маркировка
[regexp enumerateMatchesInString: ... usingBlock:^(NSTextCheckingResult *result, ...) { // При совпадении куска текста с шаблоном:
// 1. Добавляем участок в список совпадений [ranges addObject: [NSValue valueWithRange: [result range]]];
// 2. Помечаем участок цветом в отдельной атрибутированной строке [attrTextMutable addAttribute: kCTForegroundColorAttributeName value: [UIColor redColor].CGColor range: [result range]]; }];
• Добавляем какой-нибудь атрибут к участкам, которые хотим выделить, и сохраняем их в в self.ranges
50
![Page 51: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/51.jpg)
Маркировка
• В drawRect проходим по всем CTRun каждой строки и получаем их frame, если они входят в сохраненные участки
➡ При проверке подходит ли run обращаем внимание на то, что конец строки может разорвать CTRun => нужно проверять включение, а не совпадение
51
![Page 52: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/52.jpg)
Маркировка
CFRange runCFRange = CTRunGetStringRange( run );
NSValue* parentRangeValue = [self parentForRange: runRange];if ( parentRangeValue ) {
// CTRun подходит, можно получить его frame и использовать это...
}
• Получаем frame рана с помощью CTRunGetTypographicBounds
• Осталось только что-нибудь добавить для выделения. . . .
• Маркированным участкам теперь соответствуют отдельные CTRun
52
![Page 53: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/53.jpg)
Маркировка• Добавим кнопку, frame которой будет выглядеть следующим образом:
CGRect buttonFrame = CGRectMake( leftX - leftPadding, topY - leftPadding, runWidth + leftPadding + rightPadding, runHeight + bottomPadding + topPadding );
CGAffineTransform transform = CGAffineTransformMakeTranslation(0, rect.size.height);
transform = CGAffineTransformScale(1, -1);buttonFrame = CGRectApplyAffineTransform(transform, buttonFrame);
• Не забываем, что мы работали в преобразованной системе координат:
53
![Page 54: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/54.jpg)
МаркировкаМожно использовать нажатие кнопки для чего-нибудь
54
![Page 55: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/55.jpg)
Содержание
• Основы Core Text
• Маркируем области в тексте
๏Два столбца
• Обтекание текстом
55
![Page 56: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/56.jpg)
• Два столбца делаются просто - выводим текст в нескольких CTFrame
- задаем CGPath для границ столбца
- чтобы определить, сколько текста вывели в предыдущем столбце, используем:
CFRange prevColTextRange = CTFrameGetVisibleStringRange(colFrames[columnIdx - 1]);
Два столбца
CGRect colRect = CGRectMake(originX, originY, colWidth, colHeight);CGPathAddRect(rectPath, NULL, colRect);
56
![Page 57: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/57.jpg)
• Два столбца делаются просто - выводим текст в нескольких CTFrame
- задаем CGPath для границ столбца
- чтобы определить, сколько текста вывели в предыдущем столбце, используем:
CFRange prevColTextRange = CTFrameGetVisibleStringRange(colFrames[columnIdx - 1]);
Два столбца
CGRect colRect = CGRectMake(originX, originY, colWidth, colHeight);CGPathAddRect(rectPath, NULL, colRect);
57
![Page 58: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/58.jpg)
Содержание
• Основы Core Text
• Выделяем области в тексте
• Два столбца๏Обтекание текстом
58
![Page 59: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/59.jpg)
Обтекание• Чтобы текст обтекал shape, нужно вырезать последний из основного фрейма
- Не нужно пытаться делать это через Core Graphics
- В Core Text есть специальные опции, которые задают вырезаемые области
59
![Page 60: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/60.jpg)
• Каждый вырезаемый CGPath задается через CFDictionaryRef
Обтекание
- (CFDictionaryRef)createClippingPathWithPath:(CGPathRef)pathRef { NSDictionary* ret = [NSDictionary dictionaryWithObject: (__bridge id)(pathRef) forKey: kCTFramePathClippingPathAttributeName]; return (__bridge CFDictionaryRef)(ret);}
60
![Page 61: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/61.jpg)
• Затем массив из CDictionaryRef ставится значением опции и передается в CTFrameSetterCreateFrame
frameOptionsDict = [NSDictionary dictionaryWithObject: clippingPaths
forKey: kCTFrameClippingPathsAttributeName];
Обтекание
CTFramesetterCreateFrame(..., (__bridge CFDictionaryRef)frameOptionsDict);
61
![Page 62: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/62.jpg)
Apple Font Tool Suitehttps://developer.apple.com/fonts/
ftxdumperfuser -t hhea -A d Font.otf
ftxdumperfuser -t hhea -A f Font.otf
ascender="716"descender="-212"lineGap="219"
ascender="975"descender="-217"lineGap="29"
Custom font Helvetica Neue
62
![Page 64: Core Text - cache-mskmar09.cdn.yandex.netcache-mskmar09.cdn.yandex.net/download.yandex.ru/company/... · 3. Рецепты Юлии ... поиске участки совпадения](https://reader034.vdocuments.net/reader034/viewer/2022042611/5a95552f7f8b9a18628ca13e/html5/thumbnails/64.jpg)
Кофе-брейк