iOS 項(xiàng)目小結(jié)

1.iOS中的round辜窑、ceil、floor函數(shù)略解

round如果參數(shù)是小數(shù)寨躁,則求本身的四舍五入.ceil如果參數(shù)是小數(shù)穆碎,則求最小的整數(shù)但不小于本身.floor如果參數(shù)是小數(shù),則求最大的整數(shù)但不大于本身.

Example:如何值是3.4的話职恳,則

-- round 3.000000

-- ceil 4.000000

-- floor 3.00000



登錄|注冊

xiaoxiaobukuang的專欄

目錄視圖

摘要視圖

訂閱

【CSDN技術(shù)主題月】深度學(xué)習(xí)框架的重構(gòu)與思考深度學(xué)習(xí)代碼專欄攢課--我的學(xué)習(xí)我做主知識庫個人圖譜上線所禀,快來領(lǐng)取~

關(guān)閉

CoreText(四):行 CTLineRef

標(biāo)簽:字體coretext

2016-09-08 18:14241人閱讀評論(0)收藏舉報(bào)

分類:

iOS連載(8)

版權(quán)聲明:本文為博主原創(chuàng)文章方面,未經(jīng)博主允許不得轉(zhuǎn)載。

目錄(?)[+]

一色徘、字符(Character)和字形(Glyphs)

排版過程中一個重要的步驟就是從字符到字形的轉(zhuǎn)換恭金,字符表示信息本身,而字形是它的圖形表現(xiàn)形式褂策。字符一般就是指某種編碼横腿,如Unicode編碼,而字形則是這些編碼對應(yīng)的圖片斤寂。但是他們之間不是一一對應(yīng)關(guān)系耿焊,同個字符的不同字體族,不同字體大小扬蕊,不同字體樣式都對應(yīng)了不同的字形艇拍。而由于連寫(Ligatures)的存在桑包,多個字符也會存在對應(yīng)一個字形的情況姚垃。

下面就來詳情看看字形的各個參數(shù)也就是所謂的字形度量Glyph Metrics

(1)函筋、邊界框 bbox(bounding box)

這是一個假想的框子,它盡可能緊密的裝入字形再愈。

(2)榜苫、基線(baseline)

一條假想的線,一行上的字形都以此線作為上下位置的參考,在這條線的左側(cè)存在一個點(diǎn)叫做基線的原點(diǎn)翎冲,

(3)垂睬、上行高度(ascent)

從原點(diǎn)到字體中最高(這里的高深都是以基線為參照線的)的字形的頂部的距離,ascent是一個正值

(4)抗悍、下行高度(descent)

從原點(diǎn)到字體中最深的字形底部的距離驹饺,descent是一個負(fù)值(比如一個字體原點(diǎn)到最深的字形的底部的距離為2,那么descent就為-2)

(5)缴渊、行距(line gap)

line gap也可以稱作leading(其實(shí)準(zhǔn)確點(diǎn)講應(yīng)該叫做External leading),行高line Height則可以通過 ascent + |descent| + linegap 來計(jì)算赏壹。

(6)、字間距(Kerning)

字與字之間的距離衔沼,為了排版的美觀蝌借,并不是所有的字形之間的距離都是一致的,但是這個基本步影響到我們的文字排版指蚁。

(7)菩佑、基礎(chǔ)原點(diǎn)(Origin)

基線上最左側(cè)的點(diǎn)。

紅框高度既為當(dāng)前行的行高凝化,綠線為baseline稍坯,綠色到紅框上部分為當(dāng)前行的最大Ascent,綠線到黃線為當(dāng)前行的最大Desent搓劫,而黃框的高即為行間距劣光。由此可以得出:lineHeight = Ascent + |Decent| + Leading袜蚕。

二、坐標(biāo)系

傳統(tǒng)的Mac中的坐標(biāo)系的原點(diǎn)在左下角绢涡,比如NSView默認(rèn)的坐標(biāo)系,原點(diǎn)就在左下角遣疯。但Mac中有些View為了其實(shí)現(xiàn)的便捷將原點(diǎn)變換到左上角雄可,像NSTableView的坐標(biāo)系坐標(biāo)原點(diǎn)就在左上角。

iOSUIKit中缠犀,UIView是以左上角為原點(diǎn)数苫,而Core Text一開始的定位是使用與桌面應(yīng)用的排版系統(tǒng),桌面應(yīng)用的坐標(biāo)系是以左下角為原點(diǎn)辨液,即Core Text在繪制的時(shí)候也是參照左下角為原點(diǎn)進(jìn)行繪制的虐急,所以需要對當(dāng)前的坐標(biāo)系進(jìn)行處理。

實(shí)際上滔迈,Core Graphic 中的context也是以左下角為原點(diǎn)的止吁, 但是為什么我們用Core Graphic

繪制一些簡單的圖形的時(shí)候不需要對坐標(biāo)系進(jìn)行處理呢,是因?yàn)橥ㄟ^這個方法UIGraphicsGetCurrentContext()來獲得的當(dāng)前context是已經(jīng)被處理過的了燎悍,用下面方法可以查看指定的上下文的當(dāng)前圖形狀態(tài)變換矩陣敬惦。

方法一

//因?yàn)镃ore Text要配合Core Graphic 配合使用的,如Core Graphic一樣谈山,繪圖的時(shí)候需要獲得當(dāng)前的上下文進(jìn)行繪制CGContextRef context = UIGraphicsGetCurrentContext();NSLog(@"當(dāng)前context的變換矩陣 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));//翻轉(zhuǎn)當(dāng)前的坐標(biāo)系(因?yàn)閷τ诘讓永L制引擎來說俄删,屏幕左下角為(0,0))CGContextSetTextMatrix(context, CGAffineTransformIdentity);//設(shè)置字形變換矩陣為CGAffineTransformIdentity奏路,也就是說每一個字形都不做圖形變換CGAffineTransform flipVertical = CGAffineTransformMake(1,0,0,-1,0,self.bounds.size.height);CGContextConcatCTM(context, flipVertical);//將當(dāng)前context的坐標(biāo)系進(jìn)行flipNSLog(@"翻轉(zhuǎn)后context的變換矩陣 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));

1

2

3

4

5

6

7

8

1

2

3

4

5

6

7

8

打印結(jié)果為:

當(dāng)前context的變換矩陣[2, 0, 0, -2, 0, 800]翻轉(zhuǎn)后context的變換矩陣[2, 0, 0, 2, 0, 0]

1

2

1

2

方法二

//因?yàn)镃ore Text要配合Core Graphic 配合使用的畴椰,如Core Graphic一樣,繪圖的時(shí)候需要獲得當(dāng)前的上下文進(jìn)行繪制CGContextRefcontext= UIGraphicsGetCurrentContext();NSLog(@"當(dāng)前context的變換矩陣 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));//翻轉(zhuǎn)當(dāng)前的坐標(biāo)系(因?yàn)閷τ诘讓永L制引擎來說鸽粉,屏幕左下角為(0斜脂,0))CGContextSetTextMatrix(context, CGAffineTransformIdentity);CGContextTranslateCTM(context,0, self.bounds.size.height);CGContextScaleCTM(context,1.0, -1.0);NSLog(@"翻轉(zhuǎn)后context的變換矩陣 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));

1

2

3

4

5

6

7

8

1

2

3

4

5

6

7

8

打印:

當(dāng)前context的變換矩陣[2, 0, 0, -2, 0, 800]翻轉(zhuǎn)后context的變換矩陣[2, 0, -0, 2, 0, 0]

1

2

1

2

可以發(fā)現(xiàn)變換矩陣與CGAffineTransformIdentity的值[1, 0, 0, 1, 0,

0]是不相同的潜叛,并且與設(shè)備是否為Retina屏和設(shè)備尺寸相關(guān)秽褒。他的作用是將上下文空間坐標(biāo)系進(jìn)行翻轉(zhuǎn),并使原來的左下角原點(diǎn)變成左上角是原點(diǎn)威兜,并將向上為正y軸變?yōu)橄蛳聻檎齳軸销斟。

所以在使用drawRect的時(shí)候,當(dāng)前的context已經(jīng)被做了一次翻轉(zhuǎn)椒舵,如果不對當(dāng)前的坐標(biāo)系進(jìn)行處理蚂踊,會發(fā)現(xiàn),繪制出來的文字是鏡像上下顛倒的笔宿。所以在UIView的drawRect方法中的context上進(jìn)行Core

Text繪制之前需要對context進(jìn)行一次Flip犁钟。

三棱诱、主要函數(shù)

1、傳入CTFrame涝动,返回一個裝有多個CTLine對象的數(shù)組迈勋。

CFArrayRefCTFrameGetLines(

CTFrameRef frame )CT_AVAILABLE(10_5,3_2);

1

2

1

2

2、獲取數(shù)組中的元素個數(shù)

CFIndexCFArrayGetCount(CFArrayRef theArray);

1

1

3醋粟、獲取數(shù)組中第idx個元素

constvoid*CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx);

1

1

4靡菇、 獲取所有CTLineRef的基礎(chǔ)原點(diǎn),傳入CTFrame米愿,CFRange厦凤,和一個CGPoint的結(jié)構(gòu)體數(shù)組指針,該函數(shù)會把每一個CTLine的origin坐標(biāo)寫到數(shù)組里育苟。

voidCTFrameGetLineOrigins(? ? ? ? CTFrameRef frame,? ? ? ? CFRange range,CGPointorigins[] ) CT_AVAILABLE(10_5,3_2);

1

2

3

4

1

2

3

4

5较鼓、獲取CTLine中文字在整段文字中的Range

CFRangeCTLineGetStringRange(

CTLineRef line )CT_AVAILABLE(10_5,3_2);

1

2

1

2

6、獲取CTLine中的CTRun的數(shù)組

CFArrayRefCTLineGetGlyphRuns(

CTLineRef line )CT_AVAILABLE(10_5,3_2);

1

2

1

2

7违柏、獲取CTRun在整段文字中的Range

CFRangeCTRunGetStringRange(

CTRunRef run )CT_AVAILABLE(10_5,3_2);

1

2

1

2

8博烂、 獲取點(diǎn)擊處position文字在整段文字中的index

CFIndexCTLineGetStringIndexForPosition(

CTLineRef line,

CGPoint position )CT_AVAILABLE(10_5,3_2);

1

2

3

1

2

3

9、獲取整段文字中charIndex位置的字符相對line的原點(diǎn)的x值

CGFloatCTLineGetOffsetForStringIndex(? ? CTLineRef line,? ? CFIndex charIndex,CGFloat* __nullable secondaryOffset ) CT_AVAILABLE(10_5,3_2);

1

2

3

4

1

2

3

4

10勇垛、獲取數(shù)組中字形個個數(shù)

CFIndexCTLineGetGlyphCount(

CTLineRef line )CT_AVAILABLE(10_5,3_2);

1

2

1

2

11脖母、設(shè)置CoreText繪制前的坐標(biāo)。設(shè)置基線位置

CG_EXTERNvoidCGContextSetTextPosition(CGContextRef __nullable c,CGFloatx,CGFloaty)? ? CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

1

2

3

1

2

3

12闲孤、繪制CTLine谆级。

voidCTLineDraw(

CTLineRef line,

CGContextRef context )CT_AVAILABLE(10_5,3_2);

1

2

3

1

2

3

13、獲取CTLine的上行高度讼积,下行高度肥照,行距

doubleCTLineGetTypographicBounds(? ? CTLineRef line,CGFloat* __nullable ascent,CGFloat* __nullable descent,CGFloat* __nullable leading ) CT_AVAILABLE(10_5,3_2);

1

2

3

4

5

1

2

3

4

5

14、設(shè)置當(dāng)前文本矩陣

CG_EXTERN voidCGContextSetTextMatrix(CGContextRef __nullable c,

CGAffineTransform t)CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);

1

2

3

1

2

3

15勤众、獲取一行文字的范圍舆绎,

就是指把這一行文字點(diǎn)有的像素矩陣作為一個image圖片,來得到整個矩形區(qū)域们颜。相對于每一行基線原點(diǎn)的偏移量和寬高(例如:{{1.2吕朵,

-2.57227}, {208.025,

19.2523}},就是相對于本身的基線原點(diǎn)向右偏移1.2個單位窥突,向下偏移2.57227個單位努溃,后面是寬高)

CGRectCTLineGetImageBounds(

CTLineRef line,

CGContextRef __nullable context )CT_AVAILABLE(10_5,3_2);

1

2

3

1

2

3

例如:

//獲取frame中CTLineRef數(shù)組CFArrayRef Lines = CTFrameGetLines(frame);//獲取數(shù)組Lines中的個數(shù)CFIndex lineCount = CFArrayGetCount(Lines);//獲取數(shù)組中第一個CTLineRefCTLineRef lineRef = CFArrayGetValueAtIndex(Lines,0);//獲取lineRef中CTRunRef數(shù)組CFArrayRef runs = CTLineGetGlyphRuns(lineRef);//獲取CTLineRef中字形個數(shù)CFIndex rus = CTLineGetGlyphCount(lineRef);//獲取數(shù)組runs中的個數(shù)CFIndex runCount = CFArrayGetCount(runs);NSLog(@"lines =%ldruns =%ldrus =%ld",lineCount,runCount,rus);

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

打印:

lines=7? runs = 5 rus = 37

1

1

四阻问、舉例

1梧税、繪框

- (void)drawRect:(CGRect)rect{// 步驟1:得到當(dāng)前用于繪制畫布的上下文,用于后續(xù)將內(nèi)容繪制在畫布上// 因?yàn)镃ore Text要配合Core Graphic 配合使用的,如Core Graphic一樣第队,繪圖的時(shí)候需要獲得當(dāng)前的上下文進(jìn)行繪制CGContextRef context = UIGraphicsGetCurrentContext();NSLog(@"當(dāng)前context的變換矩陣 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));// 步驟2:翻轉(zhuǎn)當(dāng)前的坐標(biāo)系(因?yàn)閷τ诘讓永L制引擎來說哮塞,屏幕左下角為(0,0))CGContextSetTextMatrix(context, CGAffineTransformIdentity);//設(shè)置字形變換矩陣為CGAffineTransformIdentity凳谦,也就是說每一個字形都不做圖形變換CGAffineTransform flipVertical = CGAffineTransformMake(1,0,0,-1,0,self.bounds.size.height);? ? CGContextConcatCTM(context, flipVertical);//將當(dāng)前context的坐標(biāo)系進(jìn)行flipNSLog(@"翻轉(zhuǎn)后context的變換矩陣 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));// 步驟3:創(chuàng)建繪制區(qū)域CGMutablePathRef path = CGPathCreateMutable();? ? CGPathAddRect(path,NULL,self.bounds);// 步驟4:創(chuàng)建需要繪制的文字與計(jì)算需要繪制的區(qū)域NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:@"iOS程序在啟動時(shí)會創(chuàng)建一個主線程忆畅,而在一個線程只能執(zhí)行一件事情,如果在主線程執(zhí)行某些耗時(shí)操作尸执,例如加載網(wǎng)絡(luò)圖片邻眷,下載資源文件等會阻塞主線程(導(dǎo)致界面卡死,無法交互)剔交,所以就需要使用多線程技術(shù)來避免這類情況。iOS中有三種多線程技術(shù) NSThread改衩,NSOperation岖常,GCD,這三種技術(shù)是隨著IOS發(fā)展引入的葫督,抽象層次由低到高竭鞍,使用也越來越簡單。"];// 步驟5:根據(jù)AttributedString生成CTFramesetterRefCTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrString);? ? CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, [attrString length]), path,NULL);//獲取frame中CTLineRef數(shù)組CFArrayRef Lines = CTFrameGetLines(frame);//獲取數(shù)組Lines中的個數(shù)CFIndex lineCount = CFArrayGetCount(Lines);//獲取基線原點(diǎn)CGPointorigins[lineCount];? ? CTFrameGetLineOrigins(frame, CFRangeMake(0,0), origins);for(CFIndex i =0; i < lineCount; i ++) {? ? ? ? CTLineRef line = CFArrayGetValueAtIndex(Lines, i);//相對于每一行基線原點(diǎn)的偏移量和寬高(例如:{{1.2橄镜, -2.57227}, {208.025, 19.2523}}偎快,就是相對于本身的基線原點(diǎn)向右偏移1.2個單位,向下偏移2.57227個單位洽胶,后面是寬高)CGRectlineBounds = CTLineGetImageBounds((CTLineRef)line, context);NSLog(@"lineBounds = %@",NSStringFromCGRect(lineBounds));NSLog(@"point = %@",NSStringFromCGPoint(origins[i]));//每一行的起始點(diǎn)(相對于context)加上相對于本身基線原點(diǎn)的偏移量lineBounds.origin.x+= origins[i].x;? ? ? ? lineBounds.origin.y+= origins[i].y;//填充CGContextSetLineWidth(context,1.0);? ? ? ? CGContextAddRect(context,lineBounds);? ? ? ? CGContextSetStrokeColorWithColor(context, [[UIColorredColor] CGColor]);? ? ? ? CGContextStrokeRect(context, lineBounds);? ? }// 步驟6:進(jìn)行繪制CTFrameDraw(frame, context);// 步驟7.內(nèi)存管理CFRelease(frame);? ? CFRelease(path);? ? CFRelease(frameSetter);}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

打由辜小:

當(dāng)前context的變換矩陣 [2,0,0,-2,0,800]翻轉(zhuǎn)后context的變換矩陣 [2,0,0,2,0,0]lineBounds={{0.7734375,-2.052}, {354.70246875000004, 11.964}}point= {0,387}lineBounds={{0.44400000000000001,-2.052}, {371.06400000000002, 11.94}}point= {0,370}lineBounds={{0.38400000000000001,-2.052}, {371.06400000000002, 11.975999999999999}}point= {0,353}lineBounds={{0.41999999999999998,-2.052}, {320.66929687499999, 11.927999999999999}}point= {0,336}lineBounds={{0.9140625,-2.501953125}, {366.28096875, 12.473953125}}point= {0,319}lineBounds={{0.40800000000000003,-2.052}, {148.16400000000002, 11.94}}point= {0,302}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

1

2

3

4

5

6

7

8

9

10

11

12

13

14

2、單行繪制

- (void)drawRect:(CGRect)rect{// 步驟1:得到當(dāng)前用于繪制畫布的上下文姊氓,用于后續(xù)將內(nèi)容繪制在畫布上// 因?yàn)镃ore Text要配合Core Graphic 配合使用的丐怯,如Core Graphic一樣,繪圖的時(shí)候需要獲得當(dāng)前的上下文進(jìn)行繪制CGContextRef context = UIGraphicsGetCurrentContext();NSLog(@"當(dāng)前context的變換矩陣 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));// 步驟2:翻轉(zhuǎn)當(dāng)前的坐標(biāo)系(因?yàn)閷τ诘讓永L制引擎來說翔横,屏幕左下角為(0读跷,0))CGContextSetTextMatrix(context, CGAffineTransformIdentity);//設(shè)置字形變換矩陣為CGAffineTransformIdentity,也就是說每一個字形都不做圖形變換CGAffineTransform flipVertical = CGAffineTransformMake(1,0,0,-1,0,self.bounds.size.height);? ? CGContextConcatCTM(context, flipVertical);//將當(dāng)前context的坐標(biāo)系進(jìn)行flipNSLog(@"翻轉(zhuǎn)后context的變換矩陣 %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));// 步驟3:創(chuàng)建繪制區(qū)域CGMutablePathRef path = CGPathCreateMutable();? ? CGPathAddRect(path,NULL,self.bounds);// 步驟4:創(chuàng)建需要繪制的文字與計(jì)算需要繪制的區(qū)域NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:@"門梁真可怕 當(dāng)中英文混合之后禾唁,??????????會出現(xiàn)行高不統(tǒng)一的情況效览,現(xiàn)在在繪制的時(shí)候根據(jù)字體的descender來偏移繪制,對齊baseline荡短。??????????同時(shí)點(diǎn)擊鏈接的時(shí)候會調(diào)用drawRect: 造成繪制異常丐枉,所以將setNeedsDisplay注釋,如需刷新肢预,請手動調(diào)用矛洞。帶上emoji以供測試????????????????????"];? ? CTFontRef font = CTFontCreateWithName(CFSTR("Georgia"),20,NULL);? ? [attrString addAttribute:(id)kCTFontAttributeName value:(__bridgeid)font range:NSMakeRange(0, attrString.length)];// 步驟5:根據(jù)AttributedString生成CTFramesetterRefCTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrString);? ? CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, [attrString length]), path,NULL);//獲取frame中CTLineRef數(shù)組CFArrayRef Lines = CTFrameGetLines(frame);//獲取數(shù)組Lines中的個數(shù)CFIndex lineCount = CFArrayGetCount(Lines);//獲取基線原點(diǎn)CGPointorigins[lineCount];? ? CTFrameGetLineOrigins(frame, CFRangeMake(0,0), origins);for(CFIndex i =0; i < lineCount; i ++) {? ? ? ? CTLineRef line = CFArrayGetValueAtIndex(Lines, i);//遍歷每一行CTLineCGFloatlineAscent;CGFloatlineDescent;CGFloatlineLeading;// 行距// 該函數(shù)除了會設(shè)置好ascent,descent,leading之外,還會返回這行的寬度CTLineGetTypographicBounds(line, &lineAscent, &lineDescent, &lineLeading);NSLog(@"lineAscent = %f",lineAscent);NSLog(@"lineDescent = %f",lineDescent);NSLog(@"lineLeading = %f",lineLeading);CGPointlineOrigin = origins[i];NSLog(@"point = %@",NSStringFromCGPoint(lineOrigin));CGRectoldLineBounds = CTLineGetImageBounds((CTLineRef)line, context);NSLog(@"lineBounds改動前:%@",NSStringFromCGRect(oldLineBounds));NSLog(@"y = %f? d = %f? fontD = %f",lineOrigin.y,lineDescent,CTFontGetDescent(font));NSLog(@"Position修改前%@",NSStringFromCGPoint(CGContextGetTextPosition(context)));? ? ? ? CGContextSetTextPosition(context, lineOrigin.x, lineOrigin.y-lineDescent - CTFontGetDescent(font));NSLog(@"Position修改后%@",NSStringFromCGPoint(CGContextGetTextPosition(context)));CGRectlineBounds = CTLineGetImageBounds((CTLineRef)line, context);NSLog(@"lineBounds改動后 = %@",NSStringFromCGRect(lineBounds));//填充CGContextSetLineWidth(context,1.0);? ? ? ? CGContextAddRect(context,lineBounds);? ? ? ? CGContextSetStrokeColorWithColor(context, [[UIColorredColor] CGColor]);? ? ? ? CGContextStrokeRect(context, lineBounds);? ? ? ? CTLineDraw(line, context);//繪制原點(diǎn)為左下角}// 步驟6:進(jìn)行繪制//? ? CTFrameDraw(frame, context);// 步驟7.內(nèi)存管理CFRelease(frame);? ? CFRelease(path);? ? CFRelease(frameSetter);}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

打印數(shù)據(jù):

當(dāng)前context的變換矩陣 [2,0,0, -2,0,800]翻轉(zhuǎn)后context的變換矩陣 [2,0,0,2,0,0]lineAscent =22.000000lineDescent =6.875000lineLeading =0.000000point ={0, 378}lineBounds改動前:{{1.98, -3.5499999999999998},{328.34421874999998, 22}}y =378.000000d =6.875000fontD =4.384766Position修改前{0, 0}Position修改后{0, 366.740234375}lineBounds改動后 ={{1.98, 363.19023437499999},{328.34421874999998, 22}}lineAscent =22.000000lineDescent =6.875000lineLeading =0.000000point ={0, 349}lineBounds改動前:{{331.32421875, 363.19023437499999},{367.41999999999996, 22}}y =349.000000d =6.875000fontD =4.384766Position修改前{330.82421875, 366.740234375}Position修改后{0, 337.740234375}lineBounds改動后 ={{0.5, 334.19023437499999},{367.41999999999996, 22}}lineAscent =21.200000lineDescent =6.800000lineLeading =0.000000point ={0, 321}lineBounds改動前:{{369.83999999999997, 335.58023437499997},{368.16703124999998, 18.66}}y =321.000000d =6.800000fontD =4.384766Position修改前{369, 337.740234375}Position修改后{0, 309.81523437499999}lineBounds改動后 ={{0.83999999999999997, 307.65523437499996},{368.16703124999998, 18.66}}lineAscent =22.000000lineDescent =6.875000lineLeading =0.000000point ={0, 292}lineBounds改動前:{{370.40703124999999, 306.26523437499998},{365.81625000000003, 22}}y =292.000000d =6.875000fontD =4.384766Position修改前{369.70703125, 309.81523437499999}Position修改后{0, 280.740234375}lineBounds改動后 ={{0.70000000000000007, 277.19023437499999},{365.81625000000003, 22}}lineAscent =21.200000lineDescent =6.800000lineLeading =0.000000point ={0, 264}lineBounds改動前:{{368.41624999999999, 278.58023437499997},{353.68367187500002, 18.620000000000001}}y =264.000000d =6.800000fontD =4.384766Position修改前{367.65625, 280.740234375}Position修改后{0, 252.81523437499999}lineBounds改動后 ={{0.76000000000000001, 250.65523437499999},{353.68367187500002, 18.620000000000001}}lineAscent =21.200000lineDescent =6.800000lineLeading =0.000000point ={0, 236}lineBounds改動前:{{356.94367187500001, 248.47929687499999},{363.27226562499999, 20.775937499999998}}y =236.000000d =6.800000fontD =4.384766Position修改前{355.263671875, 252.81523437499999}Position修改后{0, 224.81523437499999}lineBounds改動后 ={{1.6799999999999999, 220.47929687499999},{363.27226562499999, 20.775937499999998}}lineAscent =21.200000lineDescent =6.800000lineLeading =0.000000point ={0, 208}lineBounds改動前:{{367.25226562500001, 220.47929687499999},{328.44562499999995, 20.915937499999998}}y =208.000000d =6.800000fontD =4.384766Position修改前{366.572265625, 224.81523437499999}Position修改后{0, 196.81523437499999}lineBounds改動后 ={{0.68000000000000005, 192.47929687499999},{328.44562499999995, 20.915937499999998}}lineAscent =22.000000lineDescent =6.875000lineLeading =0.000000point ={0, 179}lineBounds改動前:{{330.265625, 193.26523437499998},{229, 22}}y =179.000000d =6.875000fontD =4.384766Position修改前{329.765625, 196.81523437499999}Position修改后{0, 167.740234375}lineBounds改動后 ={{0.5, 164.19023437499999},{229, 22}}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

3、固定行間距

行高=每行的asent + 每行的descent + 行數(shù)*行間距

.m

#import"MyView.h"#import// 行距constCGFloatkGlobalLineLeading =5.0;@interfaceMyView()@property(nonatomic,assign)CGFloattextHeight;@end@implementationMyView- (instancetype)initWithFrame:(CGRect)frame{self= [superinitWithFrame:frame];if(self) {self.text= @"我自橫刀向天笑沼本,去留肝膽兩昆侖噩峦。--譚嗣同同學(xué)你好啊。This is my first CoreText demo,how are you ?I love three things,the sun,the moon,and you.the sun for the day,the moon for the night,and you forever.??????????????去年今日此門中抽兆,人面桃花相映紅识补。人面不知何處去,桃花依舊笑春風(fēng)辫红。??????????????少年不知愁滋味凭涂,愛上層樓,愛上層樓贴妻,為賦新詞強(qiáng)說愁切油。56321363464.而今識盡愁滋味,欲說還休名惩,欲說還休澎胡,卻道天涼好個秋。123456娩鹉,7890攻谁,56321267895434。缺月掛疏桐弯予,漏斷人初靜戚宦。誰見幽人獨(dú)往來,縹緲孤鴻影锈嫩。驚起卻回頭受楼,有恨無人省。撿盡寒枝不肯棲祠挫,寂寞沙洲冷那槽。";self.font= [UIFontsystemFontOfSize:15];? ? }returnself;}#pragma mark - 計(jì)算高度/**

*? 高度 = 每行的asent + 每行的descent + 行數(shù)*行間距

*? 行間距為指定的數(shù)值

*/+ (CGFloat)textHeightWithText:(NSString*)aText width:(CGFloat)aWidth font:(UIFont*)aFont{? ? NSMutableAttributedString *content = [[NSMutableAttributedString alloc] initWithString:aText];// 設(shè)置全局樣式[selfaddGlobalAttributeWithContent:content font:aFont];? ? CTFramesetterRef framesetterRef = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)content);//粗略的計(jì)算高度CGSizesuggestSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetterRef, CFRangeMake(0, aText.length),NULL, CGSizeMake(aWidth, MAXFLOAT),NULL);? ? CGMutablePathRef path = CGPathCreateMutable();? ? CGPathAddRect(path,NULL, CGRectMake(0,0, aWidth, suggestSize.height*10));// 10這個數(shù)值是隨便給的,主要是為了確保高度足夠CTFrameRef frameRef = CTFramesetterCreateFrame(framesetterRef, CFRangeMake(0, aText.length), path,NULL);? ? CFArrayRef lines = CTFrameGetLines(frameRef);? ? CFIndex lineCount = CFArrayGetCount(lines);CGFloatascent =0;CGFloatdescent =0;CGFloatleading =0;CGFloattotalHeight =0;NSLog(@"計(jì)算高度開始");for(CFIndex i =0; i < lineCount; i++){? ? ? ? CTLineRef lineRef = CFArrayGetValueAtIndex(lines, i);? ? ? ? CTLineGetTypographicBounds(lineRef, &ascent, &descent, &leading);NSLog(@"ascent = %f---descent = %f---leading = %f",ascent,descent,leading);? ? ? ? totalHeight += ascent + descent + kGlobalLineLeading;//行間距}NSLog(@"totalHeight = %f",totalHeight);returntotalHeight;}#pragma mark - 工具方法#pragma mark 給字符串添加全局屬性等舔,比如行距骚灸,字體大小,默認(rèn)顏色+ (void)addGlobalAttributeWithContent:(NSMutableAttributedString *)aContent font:(UIFont*)aFont{CGFloatlineLeading = kGlobalLineLeading;// 行間距constCFIndex kNumberOfSettings =2;//設(shè)置段落格式CTParagraphStyleSetting lineBreakStyle;? ? CTLineBreakMode lineBreakMode = kCTLineBreakByWordWrapping;? ? lineBreakStyle.spec= kCTParagraphStyleSpecifierLineBreakMode;? ? lineBreakStyle.valueSize=sizeof(CTLineBreakMode);? ? lineBreakStyle.value= &lineBreakMode;//設(shè)置行距CTParagraphStyleSetting lineSpaceStyle;? ? CTParagraphStyleSpecifier spec;? ? spec = kCTParagraphStyleSpecifierLineSpacingAdjustment;? ? lineSpaceStyle.spec= spec;? ? lineSpaceStyle.valueSize=sizeof(CGFloat);? ? lineSpaceStyle.value= &lineLeading;// 結(jié)構(gòu)體數(shù)組CTParagraphStyleSetting theSettings[kNumberOfSettings] = {? ? ? ? lineBreakStyle,? ? ? ? lineSpaceStyle,? ? };? ? CTParagraphStyleRef theParagraphRef = CTParagraphStyleCreate(theSettings, kNumberOfSettings);// 將設(shè)置的行距應(yīng)用于整段文字[aContent addAttribute:NSParagraphStyleAttributeName value:(__bridgeid)(theParagraphRef) range:NSMakeRange(0, aContent.length)];? ? CFStringRef fontName = (__bridge CFStringRef)aFont.fontName;? ? CTFontRef fontRef = CTFontCreateWithName(fontName, aFont.pointSize,NULL);// 將字體大小應(yīng)用于整段文字[aContent addAttribute:NSFontAttributeName value:(__bridgeid)fontRef range:NSMakeRange(0, aContent.length)];// 給整段文字添加默認(rèn)顏色[aContent addAttribute:NSForegroundColorAttributeName value:[UIColorblackColor] range:NSMakeRange(0, aContent.length)];// 內(nèi)存管理CFRelease(theParagraphRef);? ? CFRelease(fontRef);}/**

*? 一行一行繪制慌植,未調(diào)整行高(行高不固定)

*/- (void)drawRectWithLineByLine{// 1.創(chuàng)建需要繪制的文字NSMutableAttributedString *attributed = [[NSMutableAttributedString alloc] initWithString:self.text];// 2.設(shè)置行距等樣式[[selfclass] addGlobalAttributeWithContent:attributed font:self.font];self.textHeight= [[selfclass] textHeightWithText:self.textwidth:CGRectGetWidth(self.bounds) font:self.font];// 3.創(chuàng)建繪制區(qū)域甚牲,path的高度對繪制有直接影響,如果高度不夠蝶柿,則計(jì)算出來的CTLine的數(shù)量會少一行或者少多行CGMutablePathRef path = CGPathCreateMutable();? ? CGPathAddRect(path,NULL, CGRectMake(0,0, CGRectGetWidth(self.bounds),self.textHeight));// 4.根據(jù)NSAttributedString生成CTFramesetterRefCTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributed);? ? CTFrameRef ctFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, attributed.length), path,NULL);// 1.獲取上下文CGContextRef contextRef = UIGraphicsGetCurrentContext();// 2.轉(zhuǎn)換坐標(biāo)系CGContextSetTextMatrix(contextRef, CGAffineTransformIdentity);? ? CGContextTranslateCTM(contextRef,0,self.textHeight);// 此處用計(jì)算出來的高度CGContextScaleCTM(contextRef,1.0, -1.0);// 重置高度//? ? CGPathAddRect(path, NULL, CGRectMake(0, 0, CGRectGetWidth(self.bounds), self.textHeight));// 一行一行繪制CFArrayRef lines = CTFrameGetLines(ctFrame);? ? CFIndex lineCount = CFArrayGetCount(lines);CGPointlineOrigins[lineCount];// 把ctFrame里每一行的初始坐標(biāo)寫到數(shù)組里丈钙,注意CoreText的坐標(biāo)是左下角為原點(diǎn)CTFrameGetLineOrigins(ctFrame, CFRangeMake(0,0), lineOrigins);for(inti =0; i < lineCount; i++){CGPointpoint = lineOrigins[i];NSLog(@"point.y = %f",point.y);? ? }NSLog(@"font.ascender = %f,descender = %f,lineHeight = %f,leading = %f",self.font.ascender,self.font.descender,self.font.lineHeight,self.font.leading);CGFloatframeY =0;for(CFIndex i =0; i < lineCount; i++){// 遍歷每一行CTLineCTLineRef line = CFArrayGetValueAtIndex(lines, i);CGFloatlineAscent;CGFloatlineDescent;CGFloatlineLeading;// 行距// 該函數(shù)除了會設(shè)置好ascent,descent,leading之外,還會返回這行的寬度CTLineGetTypographicBounds(line, &lineAscent, &lineDescent, &lineLeading);NSLog(@"lineAscent = %f",lineAscent);NSLog(@"lineDescent = %f",lineDescent);NSLog(@"lineLeading = %f",lineLeading);CGPointlineOrigin = lineOrigins[i];NSLog(@"i = %ld, lineOrigin = %@",i,NSStringFromCGPoint(lineOrigin));// 微調(diào)Y值交汤,需要注意的是CoreText的Y值是在baseLine處雏赦,而不是下方的descent劫笙。// lineDescent為正數(shù),self.font.descender為負(fù)數(shù)if(i >0){// 第二行之后需要計(jì)算frameY = frameY - kGlobalLineLeading - lineAscent;? ? ? ? ? ? lineOrigin.y= frameY;? ? ? ? }else{// 第一行可直接用frameY = lineOrigin.y;? ? ? ? }// 調(diào)整坐標(biāo)CGContextSetTextPosition(contextRef, lineOrigin.x, lineOrigin.y);? ? ? ? CTLineDraw(line, contextRef);// 微調(diào)frameY = frameY - lineDescent;? ? }? ? CFRelease(path);? ? CFRelease(framesetter);? ? CFRelease(ctFrame);}- (void)drawRect:(CGRect)rect{? ? [selfdrawRectWithLineByLine];}@end

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

.h文件

#import@interfaceMyView:UIView@property(nonatomic,copy)NSString*text;@property(nonatomic,strong)UIFont*font;+ (CGFloat)textHeightWithText:(NSString*)aText width:(CGFloat)aWidth font:(UIFont*)aFont;@end

1

2

3

4

5

6

7

8

9

10

11

1

2

3

4

5

6

7

8

9

10

11

結(jié)果:

3星岗、固定行高

總高度 = 行數(shù)*每行的高度

.m

#import"MyView.h"#import// 行距constCGFloatkGlobalLineLeading =5.0;// 在15字體下填大,比值小于這個計(jì)算出來的高度會導(dǎo)致emoji顯示不全constCGFloatkPerLineRatio =1.4;@interfaceMyView()@property(nonatomic,assign)CGFloattextHeight;@end@implementationMyView- (instancetype)initWithFrame:(CGRect)frame{self= [superinitWithFrame:frame];if(self) {self.text= @"我自橫刀向天笑,去留肝膽兩昆侖俏橘。--譚嗣同同學(xué)你好啊允华。This is my first CoreText demo,how are you ?I love three things,the sun,the moon,and you.the sun for the day,the moon for the night,and you forever.??????????????去年今日此門中,人面桃花相映紅寥掐。人面不知何處去靴寂,桃花依舊笑春風(fēng)。??????????????少年不知愁滋味召耘,愛上層樓百炬,愛上層樓,為賦新詞強(qiáng)說愁污它。56321363464.而今識盡愁滋味收壕,欲說還休,欲說還休轨蛤,卻道天涼好個秋。123456虫埂,7890祥山,56321267895434。缺月掛疏桐掉伏,漏斷人初靜缝呕。誰見幽人獨(dú)往來,縹緲孤鴻影斧散。驚起卻回頭供常,有恨無人省。撿盡寒枝不肯棲鸡捐,寂寞沙洲冷栈暇。";self.font= [UIFontsystemFontOfSize:15];? ? }returnself;}/**

*? 高度 = 每行的固定高度 * 行數(shù)

*/+ (CGFloat)textHeightWithText:(NSString*)aText width:(CGFloat)aWidth font:(UIFont*)aFont{? ? NSMutableAttributedString *content = [[NSMutableAttributedString alloc] initWithString:aText];// 給字符串設(shè)置字體行距等樣式[selfaddGlobalAttributeWithContent:content font:aFont];? ? CTFramesetterRef framesetterRef = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)content);// 粗略的高度,該高度不準(zhǔn)箍镜,僅供參考CGSizesuggestSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetterRef, CFRangeMake(0, content.length),NULL, CGSizeMake(aWidth, MAXFLOAT),NULL);NSLog(@"suggestHeight = %f",suggestSize.height);? ? CGMutablePathRef pathRef = CGPathCreateMutable();? ? CGPathAddRect(pathRef,NULL, CGRectMake(0,0, aWidth, suggestSize.height));? ? CTFrameRef frameRef = CTFramesetterCreateFrame(framesetterRef, CFRangeMake(0, content.length), pathRef,NULL);? ? CFArrayRef lines = CTFrameGetLines(frameRef);? ? CFIndex lineCount = CFArrayGetCount(lines);NSLog(@"行數(shù) = %ld",lineCount);// 總高度 = 行數(shù)*每行的高度源祈,其中每行的高度為指定的值,不同字體大小不一樣CGFloataccurateHeight = lineCount * (aFont.pointSize* kPerLineRatio);CGFloatheight = accurateHeight;? ? CFRelease(pathRef);? ? CFRelease(frameRef);returnheight;}#pragma mark - 工具方法#pragma mark 給字符串添加全局屬性色迂,比如行距香缺,字體大小,默認(rèn)顏色+ (void)addGlobalAttributeWithContent:(NSMutableAttributedString *)aContent font:(UIFont*)aFont{CGFloatlineLeading = kGlobalLineLeading;// 行間距constCFIndex kNumberOfSettings =2;//設(shè)置段落格式CTParagraphStyleSetting lineBreakStyle;? ? CTLineBreakMode lineBreakMode = kCTLineBreakByWordWrapping;? ? lineBreakStyle.spec= kCTParagraphStyleSpecifierLineBreakMode;? ? lineBreakStyle.valueSize=sizeof(CTLineBreakMode);? ? lineBreakStyle.value= &lineBreakMode;//設(shè)置行距CTParagraphStyleSetting lineSpaceStyle;? ? CTParagraphStyleSpecifier spec;? ? spec = kCTParagraphStyleSpecifierLineSpacingAdjustment;? ? lineSpaceStyle.spec= spec;? ? lineSpaceStyle.valueSize=sizeof(CGFloat);? ? lineSpaceStyle.value= &lineLeading;// 結(jié)構(gòu)體數(shù)組CTParagraphStyleSetting theSettings[kNumberOfSettings] = {? ? ? ? lineBreakStyle,? ? ? ? lineSpaceStyle,? ? };? ? CTParagraphStyleRef theParagraphRef = CTParagraphStyleCreate(theSettings, kNumberOfSettings);// 將設(shè)置的行距應(yīng)用于整段文字[aContent addAttribute:NSParagraphStyleAttributeName value:(__bridgeid)(theParagraphRef) range:NSMakeRange(0, aContent.length)];? ? CFStringRef fontName = (__bridge CFStringRef)aFont.fontName;? ? CTFontRef fontRef = CTFontCreateWithName(fontName, aFont.pointSize,NULL);// 將字體大小應(yīng)用于整段文字[aContent addAttribute:NSFontAttributeName value:(__bridgeid)fontRef range:NSMakeRange(0, aContent.length)];// 給整段文字添加默認(rèn)顏色[aContent addAttribute:NSForegroundColorAttributeName value:[UIColorblackColor] range:NSMakeRange(0, aContent.length)];// 內(nèi)存管理CFRelease(theParagraphRef);? ? CFRelease(fontRef);}#pragma mark - 一行一行繪制歇僧,行高確定图张,行與行之間對齊- (void)drawRectWithLineByLineAlignment{// 1.創(chuàng)建需要繪制的文字NSMutableAttributedString *attributed = [[NSMutableAttributedString alloc] initWithString:self.text];// 2.設(shè)置行距等樣式[[selfclass] addGlobalAttributeWithContent:attributed font:self.font];self.textHeight= [[selfclass] textHeightWithText:self.textwidth:CGRectGetWidth(self.bounds) font:self.font];// 3.創(chuàng)建繪制區(qū)域,path的高度對繪制有直接影響,如果高度不夠祸轮,則計(jì)算出來的CTLine的數(shù)量會少一行或者少多行CGMutablePathRef path = CGPathCreateMutable();? ? CGPathAddRect(path,NULL, CGRectMake(0,0, CGRectGetWidth(self.bounds),self.textHeight*2));// 4.根據(jù)NSAttributedString生成CTFramesetterRefCTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributed);? ? CTFrameRef ctFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, attributed.length), path,NULL);// 獲取上下文CGContextRef contextRef = UIGraphicsGetCurrentContext();// 轉(zhuǎn)換坐標(biāo)系CGContextSetTextMatrix(contextRef, CGAffineTransformIdentity);? ? CGContextTranslateCTM(contextRef,0,self.textHeight);// 此處用計(jì)算出來的高度CGContextScaleCTM(contextRef,1.0, -1.0);// 一行一行繪制CFArrayRef lines = CTFrameGetLines(ctFrame);? ? CFIndex lineCount = CFArrayGetCount(lines);CGPointlineOrigins[lineCount];// 把ctFrame里每一行的初始坐標(biāo)寫到數(shù)組里兽埃,注意CoreText的坐標(biāo)是左下角為原點(diǎn)CTFrameGetLineOrigins(ctFrame, CFRangeMake(0,0), lineOrigins);for(inti =0; i < lineCount; i++)? ? {CGPointpoint = lineOrigins[i];NSLog(@"point.y = %f",point.y);? ? }NSLog(@"font.ascender = %f,descender = %f,lineHeight = %f,leading = %f",self.font.ascender,self.font.descender,self.font.lineHeight,self.font.leading);CGFloatframeY =0;NSLog(@"self.textHeight = %f,lineHeight = %f",self.textHeight,self.font.pointSize* kPerLineRatio);for(CFIndex i =0; i < lineCount; i++){// 遍歷每一行CTLineCTLineRef line = CFArrayGetValueAtIndex(lines, i);CGFloatlineAscent;CGFloatlineDescent;CGFloatlineLeading;// 行距// 該函數(shù)除了會設(shè)置好ascent,descent,leading之外,還會返回這行的寬度CTLineGetTypographicBounds(line, &lineAscent, &lineDescent, &lineLeading);NSLog(@"lineAscent = %f",lineAscent);NSLog(@"lineDescent = %f",lineDescent);NSLog(@"lineLeading = %f",lineLeading);CGPointlineOrigin = lineOrigins[i];NSLog(@"i = %ld, lineOrigin = %@",i,NSStringFromCGPoint(lineOrigin));// 微調(diào)Y值倔撞,需要注意的是CoreText的Y值是在baseLine處讲仰,而不是下方的descent。CGFloatlineHeight =self.font.pointSize* kPerLineRatio;? ? ? ? frameY =self.textHeight- (i +1)*lineHeight -self.font.descender;NSLog(@"frameY = %f",frameY);? ? ? ? lineOrigin.y= frameY;// 調(diào)整坐標(biāo)CGContextSetTextPosition(contextRef, lineOrigin.x, lineOrigin.y);? ? ? ? CTLineDraw(line, contextRef);? ? }? ? CFRelease(path);? ? CFRelease(framesetter);? ? CFRelease(ctFrame);}- (void)drawRect:(CGRect)rect{? ? [selfdrawRectWithLineByLineAlignment];}@end

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

.h

#import@interfaceMyView:UIView@property(nonatomic,copy)NSString*text;@property(nonatomic,strong)UIFont*font;+ (CGFloat)textHeightWithText:(NSString*)aText width:(CGFloat)aWidth font:(UIFont*)aFont;@end

1

2

3

4

5

6

7

8

9

10

11

1

2

3

4

5

6

7

8

9

10

11

結(jié)果

參考

CoreText使用教程(三)

0

0

上一篇CoreText(四):圖文混排

下一篇CoreText(五):省略號

我的同類文章

iOS連載(8)

?CoreText(五):省略號2016-09-19閱讀293

?CoreText(三):繪制文本2016-08-31閱讀210

?CoreText(一):基本用法2016-08-30閱讀128

?顏色(二):CGColor2016-01-09閱讀257

?CoreText(四):圖文混排2016-08-31閱讀241

?CoreText(二):段落CTParagraphStyle2016-08-31閱讀195

?顏色(三):CIColor2016-01-09閱讀137

?顏色(一):UIColor2016-01-09閱讀197

參考知識庫

Swift知識庫

1792關(guān)注|395收錄

猜你在找

iOS8開發(fā)技術(shù)(Swift版):屏幕適配

老郭全套iOS開發(fā)課程【UI技術(shù)】

iOS8開發(fā)視頻教程Swift語言版-Part 3:iOS 8多分辨率屏幕適配

iOS8開發(fā)技術(shù)(Swift版):本地化

iOS企業(yè)級應(yīng)用開發(fā)-iOS6定位服務(wù)與地圖

javascript對象小探之四---undefinednullNaN的相互運(yùn)算

Nodejs 在命令行下執(zhí)行Consolelog命令時(shí)第二行會打印undefined的原因

ios-CoreText-核心文本

關(guān)于coretext繪圖字體始終無法改變大小的原因

CoreText ios 上的用法

查看評論

暫無評論

您還沒有登錄,請[登錄][注冊]

* 以上用戶言論只代表其個人觀點(diǎn)痪蝇,不代表CSDN網(wǎng)站的觀點(diǎn)或立場

核心技術(shù)類目

全部主題HadoopAWS移動游戲JavaAndroidiOSSwift智能硬件DockerOpenStackVPNSparkERPIE10EclipseCRMJavaScript數(shù)據(jù)庫UbuntuNFCWAPjQueryBIHTML5SpringApache.NETAPIHTMLSDKIISFedoraXMLLBSUnitySplashtopUMLcomponentsWindows MobileRailsQEMUKDECassandraCloudStackFTCcoremailOPhoneCouchBase云計(jì)算iOS6RackspaceWeb AppSpringSideMaemoCompuware大數(shù)據(jù)aptechPerlTornadoRubyHibernateThinkPHPHBasePureSolrAngularCloud FoundryRedisScalaDjangoBootstrap

個人資料

xiaoxiaobukuang

訪問:69977次

積分:1736

等級:

排名:第16926名

原創(chuàng):104篇

轉(zhuǎn)載:4篇

譯文:0篇

評論:3條

文章搜索

文章分類

瘋狂iOS(上)(12)

瘋狂iOS(下)(11)

iOS多線程和推送(11)

HTTP和Socket套接字(2)

iOS管理(7)

iOS崩潰(3)

iOS總結(jié)(11)

iOS控件(1)

iOS基礎(chǔ)(6)

iOS三方庫(8)

iOS連載(9)

iOS視圖切換(4)

iOS動畫(7)

iOS 8 新增控件(3)

iOS 9 新特性(7)

UIKit性能優(yōu)化(3)

iOS提高(8)

閱讀排行

第十章:使用MapKit開發(fā)地圖服務(wù)(3979)

自動引用計(jì)數(shù)(3516)

block(3360)

第六章:加速計(jì)與陀螺儀(3271)

BlocksKit的使用(3136)

第九章:使用CoreLocation定位(3111)

第七章:多線程(2984)

第五章:管理手機(jī)(2859)

第四章:多媒體應(yīng)用開發(fā)(2794)

第三章:iOS的數(shù)據(jù)存儲與IO(2768)

評論排行

第七章:多線程(2)

iOS 常用公共方法(1)

第三章:C語言特性(0)

第二章:流程控制與數(shù)組(0)

第一章:數(shù)據(jù)類型和運(yùn)算符(0)

CAShapeLayer和UIBezierPath(0)

HTTP協(xié)議(0)

TCP/IP協(xié)議(0)

CoreText(五):省略號(0)

iOS并發(fā)編程指南(0)

推薦文章

* 2016 年最受歡迎的編程語言是什么鄙陡?

* Chromium擴(kuò)展(Extension)的頁面(Page)加載過程分析

* Android Studio 2.2 來啦

* 手把手教你做音樂播放器(二)技術(shù)原理與框架設(shè)計(jì)

* JVM 性能調(diào)優(yōu)實(shí)戰(zhàn)之:使用阿里開源工具 TProfiler 在海量業(yè)務(wù)代碼中精確定位性能代碼

最新評論

iOS 常用公共方法

那個小五先生:Cool

第七章:多線程

xiaoxiaobukuang:@goldenepoch:第一個評論,多謝u飭3梅!以后多多指教

第七章:多線程

goldenepoch:介紹的很詳細(xì)

公司簡介|招賢納士|廣告服務(wù)|銀行匯款帳號|聯(lián)系方式|版權(quán)聲明|法律顧問|問題報(bào)告|合作伙伴|論壇反饋

網(wǎng)站客服雜志客服微博客服webmaster@csdn.net400-600-2320|北京創(chuàng)新樂知信息技術(shù)有限公司 版權(quán)所有|江蘇樂知網(wǎng)絡(luò)技術(shù)有限公司 提供商務(wù)支持

京?ICP?證?09002463?號|Copyright ? 1999-2016, CSDN.NET, All Rights Reserved

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末给僵,一起剝皮案震驚了整個濱河市毫捣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌帝际,老刑警劉巖蔓同,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蹲诀,居然都是意外死亡斑粱,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門脯爪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來则北,“玉大人,你說我怎么就攤上這事痕慢∩写В” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵掖举,是天一觀的道長快骗。 經(jīng)常有香客問我,道長塔次,這世上最難降的妖魔是什么滨巴? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮俺叭,結(jié)果婚禮上恭取,老公的妹妹穿的比我還像新娘。我一直安慰自己熄守,他們只是感情好蜈垮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布耗跛。 她就那樣靜靜地躺著,像睡著了一般攒发。 火紅的嫁衣襯著肌膚如雪调塌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天惠猿,我揣著相機(jī)與錄音羔砾,去河邊找鬼。 笑死偶妖,一個胖子當(dāng)著我的面吹牛姜凄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播趾访,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼态秧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了扼鞋?” 一聲冷哼從身側(cè)響起申鱼,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎云头,沒想到半個月后捐友,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡溃槐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年楚殿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片竿痰。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖砌溺,靈堂內(nèi)的尸體忽然破棺而出影涉,到底是詐尸還是另有隱情,我是刑警寧澤规伐,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布蟹倾,位于F島的核電站,受9級特大地震影響猖闪,放射性物質(zhì)發(fā)生泄漏鲜棠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一培慌、第九天 我趴在偏房一處隱蔽的房頂上張望豁陆。 院中可真熱鬧,春花似錦吵护、人聲如沸盒音。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祥诽。三九已至譬圣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間雄坪,已是汗流浹背义辕。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工侯勉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓库继,卻偏偏與公主長得像,于是被迫代替她去往敵國和親荠医。 傳聞我的和親對象是個殘疾皇子扰路,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容