├── .gitignore ├── CoreTextSample.xcodeproj └── project.pbxproj ├── CoreTextSample ├── AppDelegate.h ├── AppDelegate.m ├── CoreTextSample-Info.plist ├── CoreTextSample-Prefix.pch ├── CoreTextView.h ├── CoreTextView.m ├── CoreTextViewController.h ├── CoreTextViewController.m ├── InfomationView.h ├── InfomationView.m ├── Sample0.h ├── Sample0.m ├── Sample1.h ├── Sample1.m ├── Sample10.h ├── Sample10.m ├── Sample11.h ├── Sample11.m ├── Sample12.h ├── Sample12.m ├── Sample13.h ├── Sample13.m ├── Sample14.h ├── Sample14.m ├── Sample2.h ├── Sample2.m ├── Sample3.h ├── Sample3.m ├── Sample4.h ├── Sample4.m ├── Sample5.h ├── Sample5.m ├── Sample6.h ├── Sample6.m ├── Sample7.h ├── Sample7.m ├── Sample8.h ├── Sample8.m ├── Sample8.txt ├── Sample9.h ├── Sample9.m ├── TableViewController.h ├── TableViewController.m ├── Text.txt ├── en.lproj │ └── InfoPlist.strings └── main.m ├── Default-568h@2x.png └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # hidden/temp files 2 | .DS_Store 3 | *.swp 4 | *~.nib 5 |   6 | # Build dir 7 | build/ 8 |   9 | # Xcode project files except for the project file 10 | *.xcodeproj/* 11 | !*.xcodeproj/project.pbxproj 12 |   13 | # Windows image thumbnail file 14 | Thumbs.db 15 |   16 | # User-specific project settings 17 | *.mode1v3 18 | *.mode2v3 -------------------------------------------------------------------------------- /CoreTextSample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B82BF63415AB9C7D00076C7E /* Sample4.m in Sources */ = {isa = PBXBuildFile; fileRef = B82BF63315AB9C7D00076C7E /* Sample4.m */; }; 11 | B82BF63B15AB9F6200076C7E /* Sample9.m in Sources */ = {isa = PBXBuildFile; fileRef = B82BF63A15AB9F6200076C7E /* Sample9.m */; }; 12 | B8460E8815A8708500C825FB /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B8460E8715A8708500C825FB /* UIKit.framework */; }; 13 | B8460E8A15A8708500C825FB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B8460E8915A8708500C825FB /* Foundation.framework */; }; 14 | B8460E8C15A8708500C825FB /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B8460E8B15A8708500C825FB /* CoreGraphics.framework */; }; 15 | B8460E9215A8708500C825FB /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B8460E9015A8708500C825FB /* InfoPlist.strings */; }; 16 | B8460E9415A8708500C825FB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B8460E9315A8708500C825FB /* main.m */; }; 17 | B8460E9815A8708500C825FB /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B8460E9715A8708500C825FB /* AppDelegate.m */; }; 18 | B8460EB615A903AE00C825FB /* TableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B8460EB515A903AE00C825FB /* TableViewController.m */; }; 19 | B8460EB915A903DE00C825FB /* CoreTextViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B8460EB815A903DE00C825FB /* CoreTextViewController.m */; }; 20 | B8460EBE15A9042400C825FB /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B8460EBD15A9042400C825FB /* CoreText.framework */; }; 21 | B8460EC115A904D800C825FB /* CoreTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = B8460EC015A904D800C825FB /* CoreTextView.m */; }; 22 | B8460EC315A905CE00C825FB /* Text.txt in Resources */ = {isa = PBXBuildFile; fileRef = B8460EC215A905CE00C825FB /* Text.txt */; }; 23 | B8460EC715A9085F00C825FB /* Sample0.m in Sources */ = {isa = PBXBuildFile; fileRef = B8460EC615A9085F00C825FB /* Sample0.m */; }; 24 | B8460ECE15A9117600C825FB /* Sample1.m in Sources */ = {isa = PBXBuildFile; fileRef = B8460ECD15A9117600C825FB /* Sample1.m */; }; 25 | B8460ED115A91EBF00C825FB /* Sample2.m in Sources */ = {isa = PBXBuildFile; fileRef = B8460ED015A91EBF00C825FB /* Sample2.m */; }; 26 | B8460ED415A922DD00C825FB /* Sample3.m in Sources */ = {isa = PBXBuildFile; fileRef = B8460ED315A922DD00C825FB /* Sample3.m */; }; 27 | B8460ED715A926FB00C825FB /* Sample5.m in Sources */ = {isa = PBXBuildFile; fileRef = B8460ED615A926FB00C825FB /* Sample5.m */; }; 28 | B8460EDA15A92BDC00C825FB /* Sample6.m in Sources */ = {isa = PBXBuildFile; fileRef = B8460ED915A92BDC00C825FB /* Sample6.m */; }; 29 | B8460EE415A9454C00C825FB /* Sample7.m in Sources */ = {isa = PBXBuildFile; fileRef = B8460EE315A9454C00C825FB /* Sample7.m */; }; 30 | B8460EF215A9E42D00C825FB /* Sample8.m in Sources */ = {isa = PBXBuildFile; fileRef = B8460EF115A9E42D00C825FB /* Sample8.m */; }; 31 | B8460EF515A9E47200C825FB /* InfomationView.m in Sources */ = {isa = PBXBuildFile; fileRef = B8460EF415A9E47200C825FB /* InfomationView.m */; }; 32 | B8460F1715AB345A00C825FB /* Sample8.txt in Resources */ = {isa = PBXBuildFile; fileRef = B8460F1615AB345A00C825FB /* Sample8.txt */; }; 33 | B87D0CE01646D42F002D7788 /* Sample13.m in Sources */ = {isa = PBXBuildFile; fileRef = B87D0CDF1646D42F002D7788 /* Sample13.m */; }; 34 | B884FAB515ABC4D200D525A3 /* Sample10.m in Sources */ = {isa = PBXBuildFile; fileRef = B884FAB415ABC4D200D525A3 /* Sample10.m */; }; 35 | B884FABD15ABD45C00D525A3 /* Sample11.m in Sources */ = {isa = PBXBuildFile; fileRef = B884FABC15ABD45C00D525A3 /* Sample11.m */; }; 36 | B8984F48164F667B00E6A3D3 /* Sample14.m in Sources */ = {isa = PBXBuildFile; fileRef = B8984F47164F667A00E6A3D3 /* Sample14.m */; }; 37 | B8D7F7D21611F4B400B56697 /* Sample12.m in Sources */ = {isa = PBXBuildFile; fileRef = B8D7F7D11611F4B400B56697 /* Sample12.m */; }; 38 | B8D7F7DF1612DBFE00B56697 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B8D7F7DE1612DBFD00B56697 /* Default-568h@2x.png */; }; 39 | /* End PBXBuildFile section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | B82BF63215AB9C7D00076C7E /* Sample4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sample4.h; sourceTree = ""; }; 43 | B82BF63315AB9C7D00076C7E /* Sample4.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sample4.m; sourceTree = ""; }; 44 | B82BF63915AB9F6200076C7E /* Sample9.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sample9.h; sourceTree = ""; }; 45 | B82BF63A15AB9F6200076C7E /* Sample9.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sample9.m; sourceTree = ""; }; 46 | B8460E8315A8708500C825FB /* CoreTextSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CoreTextSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | B8460E8715A8708500C825FB /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 48 | B8460E8915A8708500C825FB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 49 | B8460E8B15A8708500C825FB /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 50 | B8460E8F15A8708500C825FB /* CoreTextSample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CoreTextSample-Info.plist"; sourceTree = ""; }; 51 | B8460E9115A8708500C825FB /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 52 | B8460E9315A8708500C825FB /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 53 | B8460E9515A8708500C825FB /* CoreTextSample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CoreTextSample-Prefix.pch"; sourceTree = ""; }; 54 | B8460E9615A8708500C825FB /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 55 | B8460E9715A8708500C825FB /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 56 | B8460EB415A903AE00C825FB /* TableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableViewController.h; sourceTree = ""; }; 57 | B8460EB515A903AE00C825FB /* TableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableViewController.m; sourceTree = ""; }; 58 | B8460EB715A903DE00C825FB /* CoreTextViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreTextViewController.h; sourceTree = ""; }; 59 | B8460EB815A903DE00C825FB /* CoreTextViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreTextViewController.m; sourceTree = ""; }; 60 | B8460EBD15A9042400C825FB /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; 61 | B8460EBF15A904D800C825FB /* CoreTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreTextView.h; sourceTree = ""; }; 62 | B8460EC015A904D800C825FB /* CoreTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreTextView.m; sourceTree = ""; }; 63 | B8460EC215A905CE00C825FB /* Text.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Text.txt; sourceTree = ""; }; 64 | B8460EC515A9085F00C825FB /* Sample0.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sample0.h; sourceTree = ""; }; 65 | B8460EC615A9085F00C825FB /* Sample0.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sample0.m; sourceTree = ""; }; 66 | B8460ECC15A9117600C825FB /* Sample1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sample1.h; sourceTree = ""; }; 67 | B8460ECD15A9117600C825FB /* Sample1.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sample1.m; sourceTree = ""; }; 68 | B8460ECF15A91EBF00C825FB /* Sample2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sample2.h; sourceTree = ""; }; 69 | B8460ED015A91EBF00C825FB /* Sample2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sample2.m; sourceTree = ""; }; 70 | B8460ED215A922DD00C825FB /* Sample3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sample3.h; sourceTree = ""; }; 71 | B8460ED315A922DD00C825FB /* Sample3.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sample3.m; sourceTree = ""; }; 72 | B8460ED515A926FB00C825FB /* Sample5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sample5.h; sourceTree = ""; }; 73 | B8460ED615A926FB00C825FB /* Sample5.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sample5.m; sourceTree = ""; }; 74 | B8460ED815A92BDC00C825FB /* Sample6.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sample6.h; sourceTree = ""; }; 75 | B8460ED915A92BDC00C825FB /* Sample6.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sample6.m; sourceTree = ""; }; 76 | B8460EE215A9454C00C825FB /* Sample7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sample7.h; sourceTree = ""; }; 77 | B8460EE315A9454C00C825FB /* Sample7.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sample7.m; sourceTree = ""; }; 78 | B8460EF015A9E42D00C825FB /* Sample8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sample8.h; sourceTree = ""; }; 79 | B8460EF115A9E42D00C825FB /* Sample8.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sample8.m; sourceTree = ""; }; 80 | B8460EF315A9E47200C825FB /* InfomationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InfomationView.h; sourceTree = ""; }; 81 | B8460EF415A9E47200C825FB /* InfomationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InfomationView.m; sourceTree = ""; }; 82 | B8460F1615AB345A00C825FB /* Sample8.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Sample8.txt; sourceTree = ""; }; 83 | B87D0CDE1646D42E002D7788 /* Sample13.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sample13.h; sourceTree = ""; }; 84 | B87D0CDF1646D42F002D7788 /* Sample13.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sample13.m; sourceTree = ""; }; 85 | B884FAB315ABC4D200D525A3 /* Sample10.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sample10.h; sourceTree = ""; }; 86 | B884FAB415ABC4D200D525A3 /* Sample10.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sample10.m; sourceTree = ""; }; 87 | B884FABB15ABD45C00D525A3 /* Sample11.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sample11.h; sourceTree = ""; }; 88 | B884FABC15ABD45C00D525A3 /* Sample11.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sample11.m; sourceTree = ""; }; 89 | B8984F46164F667800E6A3D3 /* Sample14.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sample14.h; sourceTree = ""; }; 90 | B8984F47164F667A00E6A3D3 /* Sample14.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sample14.m; sourceTree = ""; }; 91 | B8D7F7D01611F4B400B56697 /* Sample12.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sample12.h; sourceTree = ""; }; 92 | B8D7F7D11611F4B400B56697 /* Sample12.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Sample12.m; sourceTree = ""; }; 93 | B8D7F7DE1612DBFD00B56697 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 94 | /* End PBXFileReference section */ 95 | 96 | /* Begin PBXFrameworksBuildPhase section */ 97 | B8460E8015A8708500C825FB /* Frameworks */ = { 98 | isa = PBXFrameworksBuildPhase; 99 | buildActionMask = 2147483647; 100 | files = ( 101 | B8460EBE15A9042400C825FB /* CoreText.framework in Frameworks */, 102 | B8460E8815A8708500C825FB /* UIKit.framework in Frameworks */, 103 | B8460E8A15A8708500C825FB /* Foundation.framework in Frameworks */, 104 | B8460E8C15A8708500C825FB /* CoreGraphics.framework in Frameworks */, 105 | ); 106 | runOnlyForDeploymentPostprocessing = 0; 107 | }; 108 | /* End PBXFrameworksBuildPhase section */ 109 | 110 | /* Begin PBXGroup section */ 111 | B8460E7815A8708500C825FB = { 112 | isa = PBXGroup; 113 | children = ( 114 | B8D7F7DE1612DBFD00B56697 /* Default-568h@2x.png */, 115 | B8460EBD15A9042400C825FB /* CoreText.framework */, 116 | B8460E8D15A8708500C825FB /* CoreTextSample */, 117 | B8460E8615A8708500C825FB /* Frameworks */, 118 | B8460E8415A8708500C825FB /* Products */, 119 | ); 120 | sourceTree = ""; 121 | }; 122 | B8460E8415A8708500C825FB /* Products */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | B8460E8315A8708500C825FB /* CoreTextSample.app */, 126 | ); 127 | name = Products; 128 | sourceTree = ""; 129 | }; 130 | B8460E8615A8708500C825FB /* Frameworks */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | B8460E8715A8708500C825FB /* UIKit.framework */, 134 | B8460E8915A8708500C825FB /* Foundation.framework */, 135 | B8460E8B15A8708500C825FB /* CoreGraphics.framework */, 136 | ); 137 | name = Frameworks; 138 | sourceTree = ""; 139 | }; 140 | B8460E8D15A8708500C825FB /* CoreTextSample */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | B8460E9615A8708500C825FB /* AppDelegate.h */, 144 | B8460E9715A8708500C825FB /* AppDelegate.m */, 145 | B8460EB415A903AE00C825FB /* TableViewController.h */, 146 | B8460EB515A903AE00C825FB /* TableViewController.m */, 147 | B8460EB715A903DE00C825FB /* CoreTextViewController.h */, 148 | B8460EB815A903DE00C825FB /* CoreTextViewController.m */, 149 | B8460EBF15A904D800C825FB /* CoreTextView.h */, 150 | B8460EC015A904D800C825FB /* CoreTextView.m */, 151 | B8460EC415A9084A00C825FB /* Sample */, 152 | B8460EC215A905CE00C825FB /* Text.txt */, 153 | B8460E8E15A8708500C825FB /* Supporting Files */, 154 | ); 155 | path = CoreTextSample; 156 | sourceTree = ""; 157 | }; 158 | B8460E8E15A8708500C825FB /* Supporting Files */ = { 159 | isa = PBXGroup; 160 | children = ( 161 | B8460E8F15A8708500C825FB /* CoreTextSample-Info.plist */, 162 | B8460E9015A8708500C825FB /* InfoPlist.strings */, 163 | B8460E9315A8708500C825FB /* main.m */, 164 | B8460E9515A8708500C825FB /* CoreTextSample-Prefix.pch */, 165 | ); 166 | name = "Supporting Files"; 167 | sourceTree = ""; 168 | }; 169 | B8460EC415A9084A00C825FB /* Sample */ = { 170 | isa = PBXGroup; 171 | children = ( 172 | B8460EC515A9085F00C825FB /* Sample0.h */, 173 | B8460EC615A9085F00C825FB /* Sample0.m */, 174 | B8460ECC15A9117600C825FB /* Sample1.h */, 175 | B8460ECD15A9117600C825FB /* Sample1.m */, 176 | B8460ECF15A91EBF00C825FB /* Sample2.h */, 177 | B8460ED015A91EBF00C825FB /* Sample2.m */, 178 | B8460ED215A922DD00C825FB /* Sample3.h */, 179 | B8460ED315A922DD00C825FB /* Sample3.m */, 180 | B82BF63215AB9C7D00076C7E /* Sample4.h */, 181 | B82BF63315AB9C7D00076C7E /* Sample4.m */, 182 | B8460ED515A926FB00C825FB /* Sample5.h */, 183 | B8460ED615A926FB00C825FB /* Sample5.m */, 184 | B8460ED815A92BDC00C825FB /* Sample6.h */, 185 | B8460ED915A92BDC00C825FB /* Sample6.m */, 186 | B8460EF315A9E47200C825FB /* InfomationView.h */, 187 | B8460EF415A9E47200C825FB /* InfomationView.m */, 188 | B8460EE215A9454C00C825FB /* Sample7.h */, 189 | B8460EE315A9454C00C825FB /* Sample7.m */, 190 | B8460EF015A9E42D00C825FB /* Sample8.h */, 191 | B8460EF115A9E42D00C825FB /* Sample8.m */, 192 | B8460F1615AB345A00C825FB /* Sample8.txt */, 193 | B82BF63915AB9F6200076C7E /* Sample9.h */, 194 | B82BF63A15AB9F6200076C7E /* Sample9.m */, 195 | B884FAB315ABC4D200D525A3 /* Sample10.h */, 196 | B884FAB415ABC4D200D525A3 /* Sample10.m */, 197 | B884FABB15ABD45C00D525A3 /* Sample11.h */, 198 | B884FABC15ABD45C00D525A3 /* Sample11.m */, 199 | B8D7F7D01611F4B400B56697 /* Sample12.h */, 200 | B8D7F7D11611F4B400B56697 /* Sample12.m */, 201 | B87D0CDE1646D42E002D7788 /* Sample13.h */, 202 | B87D0CDF1646D42F002D7788 /* Sample13.m */, 203 | B8984F46164F667800E6A3D3 /* Sample14.h */, 204 | B8984F47164F667A00E6A3D3 /* Sample14.m */, 205 | ); 206 | name = Sample; 207 | sourceTree = ""; 208 | }; 209 | /* End PBXGroup section */ 210 | 211 | /* Begin PBXNativeTarget section */ 212 | B8460E8215A8708500C825FB /* CoreTextSample */ = { 213 | isa = PBXNativeTarget; 214 | buildConfigurationList = B8460EA115A8708500C825FB /* Build configuration list for PBXNativeTarget "CoreTextSample" */; 215 | buildPhases = ( 216 | B8460E7F15A8708500C825FB /* Sources */, 217 | B8460E8015A8708500C825FB /* Frameworks */, 218 | B8460E8115A8708500C825FB /* Resources */, 219 | ); 220 | buildRules = ( 221 | ); 222 | dependencies = ( 223 | ); 224 | name = CoreTextSample; 225 | productName = CoreTextSample; 226 | productReference = B8460E8315A8708500C825FB /* CoreTextSample.app */; 227 | productType = "com.apple.product-type.application"; 228 | }; 229 | /* End PBXNativeTarget section */ 230 | 231 | /* Begin PBXProject section */ 232 | B8460E7A15A8708500C825FB /* Project object */ = { 233 | isa = PBXProject; 234 | attributes = { 235 | LastUpgradeCheck = 1340; 236 | ORGANIZATIONNAME = "Yu Sugawara"; 237 | }; 238 | buildConfigurationList = B8460E7D15A8708500C825FB /* Build configuration list for PBXProject "CoreTextSample" */; 239 | compatibilityVersion = "Xcode 3.2"; 240 | developmentRegion = English; 241 | hasScannedForEncodings = 0; 242 | knownRegions = ( 243 | English, 244 | en, 245 | ); 246 | mainGroup = B8460E7815A8708500C825FB; 247 | productRefGroup = B8460E8415A8708500C825FB /* Products */; 248 | projectDirPath = ""; 249 | projectRoot = ""; 250 | targets = ( 251 | B8460E8215A8708500C825FB /* CoreTextSample */, 252 | ); 253 | }; 254 | /* End PBXProject section */ 255 | 256 | /* Begin PBXResourcesBuildPhase section */ 257 | B8460E8115A8708500C825FB /* Resources */ = { 258 | isa = PBXResourcesBuildPhase; 259 | buildActionMask = 2147483647; 260 | files = ( 261 | B8460E9215A8708500C825FB /* InfoPlist.strings in Resources */, 262 | B8460EC315A905CE00C825FB /* Text.txt in Resources */, 263 | B8460F1715AB345A00C825FB /* Sample8.txt in Resources */, 264 | B8D7F7DF1612DBFE00B56697 /* Default-568h@2x.png in Resources */, 265 | ); 266 | runOnlyForDeploymentPostprocessing = 0; 267 | }; 268 | /* End PBXResourcesBuildPhase section */ 269 | 270 | /* Begin PBXSourcesBuildPhase section */ 271 | B8460E7F15A8708500C825FB /* Sources */ = { 272 | isa = PBXSourcesBuildPhase; 273 | buildActionMask = 2147483647; 274 | files = ( 275 | B8460E9415A8708500C825FB /* main.m in Sources */, 276 | B8460E9815A8708500C825FB /* AppDelegate.m in Sources */, 277 | B8460EB615A903AE00C825FB /* TableViewController.m in Sources */, 278 | B8460EB915A903DE00C825FB /* CoreTextViewController.m in Sources */, 279 | B8460EC115A904D800C825FB /* CoreTextView.m in Sources */, 280 | B8460EC715A9085F00C825FB /* Sample0.m in Sources */, 281 | B8460ECE15A9117600C825FB /* Sample1.m in Sources */, 282 | B8460ED115A91EBF00C825FB /* Sample2.m in Sources */, 283 | B8460ED415A922DD00C825FB /* Sample3.m in Sources */, 284 | B8460ED715A926FB00C825FB /* Sample5.m in Sources */, 285 | B8460EDA15A92BDC00C825FB /* Sample6.m in Sources */, 286 | B8460EE415A9454C00C825FB /* Sample7.m in Sources */, 287 | B8460EF215A9E42D00C825FB /* Sample8.m in Sources */, 288 | B8460EF515A9E47200C825FB /* InfomationView.m in Sources */, 289 | B82BF63415AB9C7D00076C7E /* Sample4.m in Sources */, 290 | B82BF63B15AB9F6200076C7E /* Sample9.m in Sources */, 291 | B884FAB515ABC4D200D525A3 /* Sample10.m in Sources */, 292 | B884FABD15ABD45C00D525A3 /* Sample11.m in Sources */, 293 | B8D7F7D21611F4B400B56697 /* Sample12.m in Sources */, 294 | B87D0CE01646D42F002D7788 /* Sample13.m in Sources */, 295 | B8984F48164F667B00E6A3D3 /* Sample14.m in Sources */, 296 | ); 297 | runOnlyForDeploymentPostprocessing = 0; 298 | }; 299 | /* End PBXSourcesBuildPhase section */ 300 | 301 | /* Begin PBXVariantGroup section */ 302 | B8460E9015A8708500C825FB /* InfoPlist.strings */ = { 303 | isa = PBXVariantGroup; 304 | children = ( 305 | B8460E9115A8708500C825FB /* en */, 306 | ); 307 | name = InfoPlist.strings; 308 | sourceTree = ""; 309 | }; 310 | /* End PBXVariantGroup section */ 311 | 312 | /* Begin XCBuildConfiguration section */ 313 | B8460E9F15A8708500C825FB /* Debug */ = { 314 | isa = XCBuildConfiguration; 315 | buildSettings = { 316 | ALWAYS_SEARCH_USER_PATHS = NO; 317 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 318 | CLANG_ENABLE_OBJC_ARC = YES; 319 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 320 | CLANG_WARN_BOOL_CONVERSION = YES; 321 | CLANG_WARN_COMMA = YES; 322 | CLANG_WARN_CONSTANT_CONVERSION = YES; 323 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 324 | CLANG_WARN_EMPTY_BODY = YES; 325 | CLANG_WARN_ENUM_CONVERSION = YES; 326 | CLANG_WARN_INFINITE_RECURSION = YES; 327 | CLANG_WARN_INT_CONVERSION = YES; 328 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 329 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 330 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 331 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 332 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 333 | CLANG_WARN_STRICT_PROTOTYPES = YES; 334 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 335 | CLANG_WARN_UNREACHABLE_CODE = YES; 336 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 337 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 338 | COPY_PHASE_STRIP = NO; 339 | ENABLE_STRICT_OBJC_MSGSEND = YES; 340 | ENABLE_TESTABILITY = YES; 341 | GCC_C_LANGUAGE_STANDARD = gnu99; 342 | GCC_DYNAMIC_NO_PIC = NO; 343 | GCC_NO_COMMON_BLOCKS = YES; 344 | GCC_OPTIMIZATION_LEVEL = 0; 345 | GCC_PREPROCESSOR_DEFINITIONS = ( 346 | "DEBUG=1", 347 | "$(inherited)", 348 | ); 349 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 350 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 351 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 352 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 353 | GCC_WARN_UNDECLARED_SELECTOR = YES; 354 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 355 | GCC_WARN_UNUSED_FUNCTION = YES; 356 | GCC_WARN_UNUSED_VARIABLE = YES; 357 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 358 | ONLY_ACTIVE_ARCH = YES; 359 | SDKROOT = iphoneos; 360 | }; 361 | name = Debug; 362 | }; 363 | B8460EA015A8708500C825FB /* Release */ = { 364 | isa = XCBuildConfiguration; 365 | buildSettings = { 366 | ALWAYS_SEARCH_USER_PATHS = NO; 367 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 368 | CLANG_ENABLE_OBJC_ARC = YES; 369 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 370 | CLANG_WARN_BOOL_CONVERSION = YES; 371 | CLANG_WARN_COMMA = YES; 372 | CLANG_WARN_CONSTANT_CONVERSION = YES; 373 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 374 | CLANG_WARN_EMPTY_BODY = YES; 375 | CLANG_WARN_ENUM_CONVERSION = YES; 376 | CLANG_WARN_INFINITE_RECURSION = YES; 377 | CLANG_WARN_INT_CONVERSION = YES; 378 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 379 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 380 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 381 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 382 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 383 | CLANG_WARN_STRICT_PROTOTYPES = YES; 384 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 385 | CLANG_WARN_UNREACHABLE_CODE = YES; 386 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 387 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 388 | COPY_PHASE_STRIP = YES; 389 | ENABLE_STRICT_OBJC_MSGSEND = YES; 390 | GCC_C_LANGUAGE_STANDARD = gnu99; 391 | GCC_NO_COMMON_BLOCKS = YES; 392 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 393 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 394 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 395 | GCC_WARN_UNDECLARED_SELECTOR = YES; 396 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 397 | GCC_WARN_UNUSED_FUNCTION = YES; 398 | GCC_WARN_UNUSED_VARIABLE = YES; 399 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 400 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 401 | SDKROOT = iphoneos; 402 | VALIDATE_PRODUCT = YES; 403 | }; 404 | name = Release; 405 | }; 406 | B8460EA215A8708500C825FB /* Debug */ = { 407 | isa = XCBuildConfiguration; 408 | buildSettings = { 409 | ARCHS = "$(ARCHS_STANDARD)"; 410 | CLANG_ENABLE_OBJC_ARC = YES; 411 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 412 | GCC_PREFIX_HEADER = "CoreTextSample/CoreTextSample-Prefix.pch"; 413 | INFOPLIST_FILE = "CoreTextSample/CoreTextSample-Info.plist"; 414 | PRODUCT_BUNDLE_IDENTIFIER = "YuSugawara.${PRODUCT_NAME:rfc1034identifier}"; 415 | PRODUCT_NAME = "$(TARGET_NAME)"; 416 | WRAPPER_EXTENSION = app; 417 | }; 418 | name = Debug; 419 | }; 420 | B8460EA315A8708500C825FB /* Release */ = { 421 | isa = XCBuildConfiguration; 422 | buildSettings = { 423 | ARCHS = "$(ARCHS_STANDARD)"; 424 | CLANG_ENABLE_OBJC_ARC = YES; 425 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 426 | GCC_PREFIX_HEADER = "CoreTextSample/CoreTextSample-Prefix.pch"; 427 | INFOPLIST_FILE = "CoreTextSample/CoreTextSample-Info.plist"; 428 | PRODUCT_BUNDLE_IDENTIFIER = "YuSugawara.${PRODUCT_NAME:rfc1034identifier}"; 429 | PRODUCT_NAME = "$(TARGET_NAME)"; 430 | WRAPPER_EXTENSION = app; 431 | }; 432 | name = Release; 433 | }; 434 | /* End XCBuildConfiguration section */ 435 | 436 | /* Begin XCConfigurationList section */ 437 | B8460E7D15A8708500C825FB /* Build configuration list for PBXProject "CoreTextSample" */ = { 438 | isa = XCConfigurationList; 439 | buildConfigurations = ( 440 | B8460E9F15A8708500C825FB /* Debug */, 441 | B8460EA015A8708500C825FB /* Release */, 442 | ); 443 | defaultConfigurationIsVisible = 0; 444 | defaultConfigurationName = Release; 445 | }; 446 | B8460EA115A8708500C825FB /* Build configuration list for PBXNativeTarget "CoreTextSample" */ = { 447 | isa = XCConfigurationList; 448 | buildConfigurations = ( 449 | B8460EA215A8708500C825FB /* Debug */, 450 | B8460EA315A8708500C825FB /* Release */, 451 | ); 452 | defaultConfigurationIsVisible = 0; 453 | defaultConfigurationName = Release; 454 | }; 455 | /* End XCConfigurationList section */ 456 | }; 457 | rootObject = B8460E7A15A8708500C825FB /* Project object */; 458 | } 459 | -------------------------------------------------------------------------------- /CoreTextSample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/07. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ViewController; 12 | 13 | @interface AppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) ViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /CoreTextSample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/07. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "TableViewController.h" 11 | 12 | @implementation AppDelegate 13 | 14 | @synthesize window = _window; 15 | @synthesize viewController = _viewController; 16 | 17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 18 | { 19 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 20 | TableViewController *tvc = [[TableViewController alloc] init]; 21 | UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:tvc]; 22 | [self.window setRootViewController:nc]; 23 | [self.window makeKeyAndVisible]; 24 | return YES; 25 | } 26 | 27 | - (void)applicationWillResignActive:(UIApplication *)application 28 | { 29 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 30 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 31 | } 32 | 33 | - (void)applicationDidEnterBackground:(UIApplication *)application 34 | { 35 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 36 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 37 | } 38 | 39 | - (void)applicationWillEnterForeground:(UIApplication *)application 40 | { 41 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 42 | } 43 | 44 | - (void)applicationDidBecomeActive:(UIApplication *)application 45 | { 46 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 47 | } 48 | 49 | - (void)applicationWillTerminate:(UIApplication *)application 50 | { 51 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /CoreTextSample/CoreTextSample-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /CoreTextSample/CoreTextSample-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'CoreTextSample' target in the 'CoreTextSample' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /CoreTextSample/CoreTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoreTextView.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface CoreTextView : UIView 13 | 14 | @property (nonatomic) NSString *text; 15 | - (void)drawCoreTextWithRect:(CGRect)rect attributedString:(NSAttributedString*)attrStr; 16 | - (void)drawCoreTextWithRect:(CGRect)rect text:(NSString*)text attributedDictionary:(NSDictionary*)attrDict; 17 | - (void)drawCoreTextWithRect:(CGRect)rect ctFrame:(CTFrameRef)ctFrame; 18 | 19 | @property (nonatomic) CTParagraphStyleRef ctParagraphStyle; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /CoreTextSample/CoreTextView.m: -------------------------------------------------------------------------------- 1 | // 2 | // CoreTextView.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "CoreTextView.h" 10 | 11 | @implementation CoreTextView 12 | 13 | - (id)initWithFrame:(CGRect)frame 14 | { 15 | self = [super initWithFrame:frame]; 16 | if (self) { 17 | NSString *path = [[NSBundle mainBundle] pathForResource:@"Text" ofType:@"txt"]; 18 | self.text = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; 19 | self.backgroundColor = [UIColor whiteColor]; 20 | 21 | 22 | /* http://novis.jimdo.com/2011/07/02/coretextの日本語行間の問題-解決/ */ 23 | CTParagraphStyleSetting setting[10]; 24 | CGFloat floatValue[10]; 25 | 26 | floatValue[0] = 0.0; // Deprecated (see header file) 27 | floatValue[1] = 0.0; 28 | floatValue[2] = 0.0; 29 | floatValue[3] = 0.0; 30 | floatValue[4] = 5.0; // Line spacing (必要に応じて行間調整) 31 | floatValue[5] = floatValue[4]; // Same as kCTParagraphStyleSpecifierMinimumLineSpacing 32 | 33 | setting[0].spec = kCTParagraphStyleSpecifierLineSpacing; // Deprecated (see header file) 34 | setting[0].valueSize = sizeof(CGFloat); 35 | setting[0].value = &floatValue[0]; 36 | 37 | setting[1].spec = kCTParagraphStyleSpecifierParagraphSpacing; 38 | setting[1].valueSize = sizeof(CGFloat); 39 | setting[1].value = &floatValue[1]; 40 | 41 | setting[2].spec = kCTParagraphStyleSpecifierMaximumLineHeight; 42 | setting[2].valueSize = sizeof(CGFloat); 43 | setting[2].value = &floatValue[2]; 44 | 45 | setting[3].spec = kCTParagraphStyleSpecifierMinimumLineHeight; 46 | setting[3].valueSize = sizeof(CGFloat); 47 | setting[3].value = &floatValue[3]; 48 | 49 | setting[4].spec = kCTParagraphStyleSpecifierMinimumLineSpacing; 50 | setting[4].valueSize = sizeof(CGFloat); 51 | setting[4].value = &floatValue[4]; 52 | 53 | setting[5].spec = kCTParagraphStyleSpecifierMaximumLineSpacing; 54 | setting[5].valueSize = sizeof(CGFloat); 55 | setting[5].value = &floatValue[5]; 56 | 57 | self.ctParagraphStyle = CTParagraphStyleCreate(setting, 6); 58 | } 59 | return self; 60 | } 61 | 62 | - (void)dealloc 63 | { 64 | if (self.ctParagraphStyle) { 65 | CFRelease(self.ctParagraphStyle); 66 | self.ctParagraphStyle = NULL; 67 | } 68 | } 69 | 70 | - (void)drawCoreTextWithRect:(CGRect)rect attributedString:(NSAttributedString *)attrStr 71 | { 72 | CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attrStr); 73 | CGPathRef framePath = [[UIBezierPath bezierPathWithRect:rect] CGPath]; 74 | CTFrameRef frame = CTFramesetterCreateFrame( 75 | framesetter, 76 | CFRangeMake(0.f, attrStr.length), 77 | framePath, 78 | NULL); 79 | 80 | [self drawCoreTextWithRect:rect ctFrame:frame]; 81 | CFRelease(frame); 82 | CFRelease(framesetter); 83 | } 84 | 85 | - (void)drawCoreTextWithRect:(CGRect)rect text:(NSString *)text attributedDictionary:(NSDictionary *)attrDict 86 | { 87 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:text attributes:attrDict]; 88 | // CFAttributedStringRef attrStr = CFAttributedStringCreate( 89 | // NULL, 90 | // (__bridge CFStringRef)self.text, 91 | // nil); 92 | 93 | CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attrStr); 94 | CGPathRef framePath = [[UIBezierPath bezierPathWithRect:rect] CGPath]; 95 | 96 | CTFrameRef frame = CTFramesetterCreateFrame( 97 | framesetter, 98 | CFRangeMake(0.f, attrStr.length), 99 | framePath, 100 | NULL); 101 | 102 | [self drawCoreTextWithRect:rect ctFrame:frame]; 103 | CFRelease(frame); 104 | CFRelease(framesetter); 105 | // CFRelease(attrStr); 106 | } 107 | 108 | - (void)drawCoreTextWithRect:(CGRect)rect ctFrame:(CTFrameRef)ctFrame 109 | { 110 | CGContextRef context = UIGraphicsGetCurrentContext(); 111 | 112 | // 座標を上下反転 113 | CGContextTranslateCTM(context, 0, rect.size.height); 114 | CGContextScaleCTM(context, 1.0, -1.0); 115 | 116 | CGContextSaveGState(context); 117 | 118 | // CoreTextの描画 119 | CTFrameDraw(ctFrame, context); 120 | 121 | CGContextRestoreGState(context); 122 | } 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /CoreTextSample/CoreTextViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CoreTextViewController.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import 10 | @class CoreTextView; 11 | 12 | @interface CoreTextViewController : UIViewController 13 | 14 | - (id)initWithContentView:(UIView*)view; 15 | 16 | @end -------------------------------------------------------------------------------- /CoreTextSample/CoreTextViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CoreTextViewController.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "CoreTextViewController.h" 10 | #import "CoreTextView.h" 11 | 12 | @interface CoreTextViewController () 13 | 14 | @property (nonatomic) UIView *coreTextView; 15 | 16 | @end 17 | 18 | @implementation CoreTextViewController 19 | 20 | - (id)initWithContentView:(UIView *)view 21 | { 22 | if (self = [super init]) { 23 | self.coreTextView = view; 24 | } 25 | return self; 26 | } 27 | 28 | - (void)viewDidLoad 29 | { 30 | [super viewDidLoad]; 31 | self.view.backgroundColor = [UIColor whiteColor]; 32 | [self.view addSubview:self.coreTextView]; 33 | } 34 | 35 | - (void)viewDidUnload 36 | { 37 | [super viewDidUnload]; 38 | _coreTextView = nil; 39 | } 40 | 41 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 42 | { 43 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /CoreTextSample/InfomationView.h: -------------------------------------------------------------------------------- 1 | // 2 | // InfomationView.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/09. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface InfomationView : UILabel 12 | 13 | @property (nonatomic) CGPoint touchPoint; 14 | @property (nonatomic) float ascent; 15 | @property (nonatomic) float descent; 16 | @property (nonatomic) float leading; 17 | @property (nonatomic) CGRect lineFrame; 18 | @property (nonatomic) NSRange touchRange; 19 | @property (nonatomic) long touchIndex; 20 | @property (nonatomic, strong) NSDictionary *attributedDictionary; 21 | @property (nonatomic, copy) NSString *touchText; 22 | 23 | - (void)redraw; 24 | 25 | @end -------------------------------------------------------------------------------- /CoreTextSample/InfomationView.m: -------------------------------------------------------------------------------- 1 | // 2 | // InfomationView.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/09. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "InfomationView.h" 10 | 11 | @implementation InfomationView 12 | 13 | @synthesize touchPoint, ascent, descent, leading, lineFrame, touchRange, touchIndex, touchText, attributedDictionary; 14 | 15 | - (void)redraw 16 | { 17 | self.text = [NSString stringWithFormat:@"タッチ座標: %@\nascent: %f\ndescent: %f\nleading: %f\n行のframe: %@\n属性文字列の範囲: %@\n文字の位置: %ld\n属性辞書: %@\nタッチした文字列: %@", NSStringFromCGPoint(self.touchPoint), self.ascent, self.descent, self.leading, NSStringFromCGRect(self.lineFrame), NSStringFromRange(self.touchRange), self.touchIndex, self.attributedDictionary, self.touchText]; 18 | } 19 | 20 | - (id)initWithFrame:(CGRect)frame 21 | { 22 | self = [super initWithFrame:frame]; 23 | if (self) { 24 | self.backgroundColor = [UIColor colorWithWhite:0.7f alpha:1.f]; 25 | self.font = [UIFont systemFontOfSize:12.f]; 26 | self.numberOfLines = 0; 27 | } 28 | return self; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /CoreTextSample/Sample0.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample0.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "CoreTextView.h" 10 | 11 | @interface Sample0 : CoreTextView 12 | 13 | @end -------------------------------------------------------------------------------- /CoreTextSample/Sample0.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample0.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample0.h" 10 | 11 | @implementation Sample0 12 | 13 | - (void)drawRect:(CGRect)rect 14 | { 15 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:self.text]; 16 | // CFAttributedStringRef attrStr = CFAttributedStringCreate( 17 | // NULL, 18 | // (__bridge CFStringRef)self.text, 19 | // nil); 20 | 21 | [self drawCoreTextWithRect:rect attributedString:attrStr]; 22 | // CFRelease(attrStr); 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /CoreTextSample/Sample1.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample1.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "CoreTextView.h" 10 | 11 | @interface Sample1 : CoreTextView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreTextSample/Sample1.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample1.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample1.h" 10 | 11 | @implementation Sample1 12 | 13 | - (void)drawRect:(CGRect)rect 14 | { 15 | CTFontRef font = CTFontCreateWithName(CFSTR("AmericanTypewriter"), 12, NULL); 16 | NSDictionary *attrDict = [NSDictionary dictionaryWithObjectsAndKeys: 17 | // フォント 18 | (__bridge id)font, kCTFontAttributeName, 19 | // 色 20 | (id)[UIColor blueColor].CGColor, kCTForegroundColorAttributeName, nil]; 21 | CFRelease(font); 22 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:self.text attributes:attrDict]; 23 | 24 | [self drawCoreTextWithRect:rect attributedString:attrStr]; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /CoreTextSample/Sample10.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample10.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/10. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "CoreTextView.h" 10 | 11 | @interface Sample10 : CoreTextView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreTextSample/Sample10.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample10.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/10. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample10.h" 10 | 11 | @interface Sample10 () 12 | 13 | @property (nonatomic) UIScrollView *scrollView; 14 | 15 | @end 16 | 17 | @implementation Sample10 18 | 19 | - (id)initWithFrame:(CGRect)frame 20 | { 21 | if (self = [super initWithFrame:frame]) { 22 | NSMutableString *mStr = [NSMutableString string]; 23 | /* 長い文章だと描画が乱れる。(下記だと i > 21以上すると乱れる) UITextViewのsample11では大丈夫 */ 24 | for (int i = 0; i < 20; i++) { 25 | [mStr appendString:self.text]; 26 | } 27 | self.text = [[NSString alloc] initWithString:mStr]; 28 | NSLog(@"text.length[%d]", self.text.length); 29 | self.scrollView = [[UIScrollView alloc] initWithFrame:frame]; 30 | [self.scrollView addSubview:self]; 31 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:self.text]; 32 | CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attrStr); 33 | 34 | // 属性付き文字列から描画に必要なサイズを取得 35 | CGSize contentSize = CGSizeZero; 36 | contentSize = CTFramesetterSuggestFrameSizeWithConstraints( 37 | framesetter, 38 | CFRangeMake(0, attrStr.length), 39 | nil, 40 | CGSizeMake(self.bounds.size.width, CGFLOAT_MAX), nil); 41 | CFRelease(framesetter); 42 | 43 | self.frame = CGRectMake(0.f, 0.f, self.bounds.size.width, contentSize.height); 44 | [self.scrollView setContentSize:CGSizeMake(self.bounds.size.width, contentSize.height)]; 45 | } 46 | return (Sample10*)self.scrollView; 47 | } 48 | 49 | - (void)drawRect:(CGRect)rect 50 | { 51 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:self.text]; 52 | [self drawCoreTextWithRect:rect attributedString:attrStr]; 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /CoreTextSample/Sample11.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample11.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/10. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Sample11 : UITextView 12 | 13 | @end -------------------------------------------------------------------------------- /CoreTextSample/Sample11.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample11.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/10. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample11.h" 10 | 11 | @implementation Sample11 12 | 13 | - (id)initWithFrame:(CGRect)frame 14 | { 15 | self = [super initWithFrame:frame]; 16 | if (self) { 17 | NSString *path = [[NSBundle mainBundle] pathForResource:@"Text" ofType:@"txt"]; 18 | NSString *tmpText = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; 19 | NSMutableString *mStr = [NSMutableString string]; 20 | for (int i = 0; i < 50; i++) { 21 | [mStr appendString:tmpText]; 22 | } 23 | self.text = [[NSString alloc] initWithString:mStr]; 24 | NSLog(@"text.length[%d]", self.text.length); 25 | } 26 | return self; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /CoreTextSample/Sample12.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample12.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/10. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "CoreTextView.h" 10 | 11 | @interface Sample12 : CoreTextView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreTextSample/Sample12.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample12.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/10. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample12.h" 10 | 11 | @interface Sample12 () 12 | 13 | @property (nonatomic) NSUInteger length; 14 | @property (nonatomic, strong) NSString *textToDraw; 15 | - (void)incrementText; 16 | - (void)drawAllText; 17 | 18 | @property (nonatomic, strong) NSTimer *timer; 19 | - (void)startAnimation; 20 | - (void)stopAnimation; 21 | 22 | @end 23 | 24 | @implementation Sample12 25 | 26 | - (id)initWithFrame:(CGRect)frame 27 | { 28 | if (self = [super initWithFrame:frame]) { 29 | self.textToDraw = @""; 30 | self.length = 1; 31 | } 32 | return self; 33 | } 34 | 35 | - (void)drawRect:(CGRect)rect 36 | { 37 | CTFontRef font = CTFontCreateWithName(CFSTR("HiraKakuProN-W3"), 12, NULL); 38 | 39 | NSDictionary *attrDict = [NSDictionary dictionaryWithObjectsAndKeys: 40 | (__bridge id)font, kCTFontAttributeName, 41 | (__bridge id)self.ctParagraphStyle, kCTParagraphStyleAttributeName, nil]; 42 | CFRelease(font); 43 | 44 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:self.textToDraw attributes:attrDict]; 45 | 46 | CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attrStr); 47 | 48 | CGPathRef framePath = [[UIBezierPath bezierPathWithRect:rect] CGPath]; 49 | CTFrameRef frame = CTFramesetterCreateFrame( 50 | framesetter, 51 | CFRangeMake(0.f, attrStr.length), 52 | framePath, 53 | NULL); 54 | 55 | NSArray *lines = (__bridge id)CTFrameGetLines(frame); 56 | 57 | // 全ての行のベースラインpointを取得 58 | CGPoint *origins = malloc(sizeof(CGPoint) * [lines count]); 59 | CTFrameGetLineOrigins(frame, CFRangeMake(0, [lines count]), origins); 60 | 61 | CGContextRef context = UIGraphicsGetCurrentContext(); 62 | 63 | // 座標を上下反転 64 | CGContextTranslateCTM(context, 0, rect.size.height); 65 | CGContextScaleCTM(context, 1.0, -1.0); 66 | 67 | CGContextSaveGState(context); 68 | // CoreTextを1行づつ描画 69 | for (int i = 0; i < [lines count]; i++) { 70 | CTLineRef line = (__bridge CTLineRef)[lines objectAtIndex:i]; 71 | // 行のベースラインpointを取得 72 | CGPoint origin = *(origins + i); 73 | // 行からdescentを取得 74 | CGFloat descent; 75 | CTLineGetTypographicBounds(line, nil, &descent, nil); 76 | // originはベースラインなのでdescentを引けば行の原点(その行の左上端)になる。 77 | CGContextSetTextPosition(context, origin.x, origin.y - descent); 78 | CTLineDraw(line, context); 79 | } 80 | if (origins) { 81 | free(origins); 82 | origins = NULL; 83 | } 84 | CGContextRestoreGState(context); 85 | 86 | CFRelease(frame); 87 | CFRelease(framesetter); 88 | } 89 | 90 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 91 | { 92 | [super touchesEnded:touches withEvent:event]; 93 | 94 | UITouch *touch = [touches anyObject]; 95 | if (touch.tapCount == 1) { 96 | static NSUInteger cnt; 97 | if (self.length < self.text.length) { 98 | cnt++; 99 | if (cnt % 2) { 100 | [self startAnimation]; 101 | } else { 102 | [self stopAnimation]; 103 | } 104 | } 105 | } else { 106 | [self drawAllText]; 107 | } 108 | } 109 | 110 | - (void)incrementText 111 | { 112 | self.length++; 113 | if (self.length >= self.text.length) { 114 | self.length = self.text.length; 115 | [self stopAnimation]; 116 | } 117 | self.textToDraw = [self.text substringWithRange:NSMakeRange(0, self.length)]; 118 | [self setNeedsDisplay]; 119 | NSLog(@"%@", self.textToDraw); 120 | } 121 | 122 | - (void)drawAllText 123 | { 124 | NSLog(@"%s", __func__); 125 | self.length = self.text.length; 126 | [self incrementText]; 127 | } 128 | 129 | - (void)startAnimation 130 | { 131 | NSLog(@"%s", __func__); 132 | self.timer = [NSTimer scheduledTimerWithTimeInterval:0.05f target:self selector:@selector(incrementText) userInfo:nil repeats:YES]; 133 | [self.timer fire]; 134 | } 135 | 136 | - (void)stopAnimation 137 | { 138 | NSLog(@"%s", __func__); 139 | [self.timer invalidate]; 140 | } 141 | 142 | @end 143 | -------------------------------------------------------------------------------- /CoreTextSample/Sample13.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample13.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 2012/11/05. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "CoreTextView.h" 10 | 11 | @interface Sample13 : CoreTextView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreTextSample/Sample13.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample13.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 2012/11/05. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample13.h" 10 | 11 | @interface Sample13 () 12 | 13 | @property (nonatomic) UIScrollView *scrollView; 14 | 15 | @end 16 | 17 | @implementation Sample13 18 | 19 | - (id)initWithFrame:(CGRect)frame 20 | { 21 | if (self = [super initWithFrame:frame]) { 22 | self.scrollView = [[UIScrollView alloc] initWithFrame:frame]; 23 | self.scrollView.alwaysBounceVertical = NO; 24 | [self.scrollView addSubview:self]; 25 | self.text = [self.text stringByAppendingString:self.text]; // 文書が短いのでとりあえず2倍にしているだけ 26 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:self.text]; 27 | CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attrStr); 28 | 29 | // 属性付き文字列から描画に必要なサイズを取得 30 | CGSize contentSize = CGSizeZero; 31 | contentSize = CTFramesetterSuggestFrameSizeWithConstraints( 32 | framesetter, 33 | CFRangeMake(0, attrStr.length), 34 | nil, 35 | CGSizeMake(self.bounds.size.width, CGFLOAT_MAX), 36 | nil); 37 | CFRelease(framesetter); 38 | 39 | /* 縦書きなので縦横のサイズを逆にする */ 40 | self.frame = CGRectMake(0.f, 0.f, contentSize.height, contentSize.width); 41 | [self.scrollView setContentSize:CGSizeMake(contentSize.height, contentSize.width)]; 42 | 43 | /* 右端から始まるようにoffsetを調整 */ 44 | self.scrollView.contentOffset = CGPointMake(contentSize.height - self.scrollView.bounds.size.width, 0.f); 45 | } 46 | return (Sample13*)self.scrollView; 47 | } 48 | 49 | - (void)drawRect:(CGRect)rect 50 | { 51 | CTFontRef font = CTFontCreateWithName(CFSTR("HiraKakuProN-W3"), 12, NULL); 52 | NSDictionary *attrDict = [NSDictionary dictionaryWithObjectsAndKeys: 53 | // フォント 54 | (__bridge id)font, kCTFontAttributeName, //nil]; 55 | // 縦書の指定 56 | [NSNumber numberWithBool:YES], kCTVerticalFormsAttributeName, nil]; 57 | CFRelease(font); 58 | 59 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:self.text attributes:attrDict]; 60 | 61 | CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attrStr); 62 | 63 | /* 縦書きなので縦横のサイズを逆にする */ 64 | CGPathRef framePath = [[UIBezierPath bezierPathWithRect:CGRectMake(0.f, 0.f, rect.size.height, rect.size.width)] CGPath]; 65 | CTFrameRef frame = CTFramesetterCreateFrame( 66 | framesetter, 67 | CFRangeMake(0.f, attrStr.length), 68 | framePath, 69 | NULL); 70 | 71 | CGContextRef context = UIGraphicsGetCurrentContext(); 72 | 73 | // 座標を上下反転 74 | CGContextTranslateCTM(context, 0, rect.size.height); 75 | CGContextScaleCTM(context, 1.0, -1.0); 76 | 77 | /* 90度右回りに回転 */ 78 | CGContextRotateCTM(context, -M_PI/2.0); 79 | CGContextTranslateCTM(context, -rect.size.height, 0); 80 | 81 | CGContextSaveGState(context); 82 | 83 | // CoreTextの描画 84 | CTFrameDraw(frame, context); 85 | 86 | CGContextRestoreGState(context); 87 | 88 | 89 | CFRelease(frame); 90 | CFRelease(framesetter); 91 | } 92 | 93 | @end -------------------------------------------------------------------------------- /CoreTextSample/Sample14.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample14.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 2012/11/11. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "CoreTextView.h" 10 | 11 | @interface Sample14 : CoreTextView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreTextSample/Sample14.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample14.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 2012/11/11. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample14.h" 10 | 11 | @interface Sample14 () 12 | 13 | @property (nonatomic) CTFontRef ctFont; 14 | 15 | @end 16 | 17 | @implementation Sample14 18 | 19 | - (id)initWithFrame:(CGRect)frame 20 | { 21 | if (self = [super initWithFrame:frame]) { 22 | self.backgroundColor = [[UIColor blueColor] colorWithAlphaComponent:0.4]; 23 | CGFloat fontSize = 50.f; 24 | 25 | // self.text = @"ygPGあア唖"; 26 | // self.text = @"gggggg\nあああああああ\nああああああ\nggggggggああああ\nggggggg"; 27 | // self.text = @"ygPGあア唖\nygPGあア唖\nygPGあア唖"; 28 | // self.text = @"あいabgj"; 29 | self.text = @"あいabgj\nあいabgj\nあいabgj"; 30 | 31 | // self.ctFont = CTFontCreateWithName(CFSTR("Helvetica"), fontSize, NULL); 32 | self.ctFont = CTFontCreateWithName(CFSTR("HiraKakuProN-W3"), fontSize, NULL); 33 | 34 | NSDictionary *attrDict = [NSDictionary dictionaryWithObjectsAndKeys: 35 | (__bridge id)self.ctFont, kCTFontAttributeName, 36 | (__bridge id)self.ctParagraphStyle, kCTParagraphStyleAttributeName, nil]; 37 | 38 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:self.text attributes:attrDict]; 39 | 40 | CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attrStr); 41 | CGSize contentSize = CTFramesetterSuggestFrameSizeWithConstraints( 42 | framesetter, 43 | CFRangeMake(0, attrStr.length), 44 | nil, 45 | CGSizeMake(self.bounds.size.width, CGFLOAT_MAX), 46 | nil); 47 | CFRelease(framesetter); 48 | NSLog(@"size[%@]", NSStringFromCGSize(contentSize)); 49 | /* descent1つ分足りない */ 50 | // self.frame = CGRectMake(0.f, 0.f, contentSize.width, contentSize.height); 51 | /* 横幅の解決 widthは切り上げないと末尾の文字が描画されない場合がある */ 52 | // self.frame = CGRectMake(0.f, 0.f, ceilf(contentSize.width), contentSize.height); 53 | /* 高幅の解決 desent分足りない*/ 54 | // self.frame = CGRectMake(0.f, 0.f, ceilf(contentSize.width), contentSize.height + ceilf(CTFontGetDescent(self.ctFont))); 55 | 56 | if (1) { 57 | CGFloat markWidth = 30.f; 58 | CGFloat markViewX = self.bounds.size.width/2.f - markWidth/2.f; 59 | UIView *asentView = [[UIView alloc] initWithFrame:CGRectMake(markViewX, 0.f, markWidth, ceilf(CTFontGetAscent(self.ctFont)))]; 60 | NSLog(@"asView %@", NSStringFromCGRect(asentView.frame)); 61 | asentView.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.3f]; 62 | [self addSubview:asentView]; 63 | 64 | UIView *desentView = [[UIView alloc] initWithFrame:CGRectMake(markViewX, asentView.bounds.size.height, markWidth, ceilf(CTFontGetDescent(self.ctFont)))]; 65 | NSLog(@"desView %@", NSStringFromCGRect(desentView.frame)); 66 | desentView.backgroundColor = [[UIColor yellowColor] colorWithAlphaComponent:0.8f]; 67 | [self addSubview:desentView]; 68 | 69 | UIView *adjustView = [[UIView alloc] initWithFrame:CGRectMake(markViewX, contentSize.height, markWidth, ceilf(CTFontGetDescent(self.ctFont)))]; 70 | NSLog(@"adjustView %@", NSStringFromCGRect(adjustView.frame)); 71 | adjustView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6f]; 72 | [self addSubview:adjustView]; 73 | } 74 | } 75 | return self; 76 | } 77 | 78 | /* 以下は使用する場合はCTParagraphStyleSettingで設定したleadingを毎行足せば多分高さが求まる 79 | [注意] CTLineGetTypographicBounds() はCTParagraphStyleSettingが考慮されず値が返る */ 80 | // http://stackoverflow.com/questions/2707710/core-texts-ctframesettersuggestframesizewithconstraints-returns-incorrect-siz 81 | +(CGFloat)heightForAttributedString:(NSAttributedString *)attrString forWidth:(CGFloat)inWidth 82 | { 83 | CGFloat H = 0; 84 | 85 | // Create the framesetter with the attributed string. 86 | CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString( (__bridge CFMutableAttributedStringRef) attrString); 87 | 88 | CGRect box = CGRectMake(0,0, inWidth, CGFLOAT_MAX); 89 | 90 | CFIndex startIndex = 0; 91 | 92 | CGMutablePathRef path = CGPathCreateMutable(); 93 | CGPathAddRect(path, NULL, box); 94 | 95 | // Create a frame for this column and draw it. 96 | CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(startIndex, 0), path, NULL); 97 | 98 | // Start the next frame at the first character not visible in this frame. 99 | //CFRange frameRange = CTFrameGetVisibleStringRange(frame); 100 | //startIndex += frameRange.length; 101 | 102 | CFArrayRef lineArray = CTFrameGetLines(frame); 103 | CFIndex j = 0, lineCount = CFArrayGetCount(lineArray); 104 | CGFloat h, ascent, descent, leading; 105 | NSLog(@"start line -> %ld", lineCount); 106 | for (j=0; j < lineCount; j++) 107 | { 108 | CTLineRef currentLine = (CTLineRef)CFArrayGetValueAtIndex(lineArray, j); 109 | CTLineGetTypographicBounds(currentLine, &ascent, &descent, &leading); 110 | h = ascent + descent;// + leading; 111 | NSLog(@"%f %f %f %f", ascent, descent, leading, h); 112 | H+=h; 113 | } 114 | 115 | CFRelease(frame); 116 | CFRelease(path); 117 | CFRelease(framesetter); 118 | 119 | 120 | return H; 121 | } 122 | 123 | - (void)drawRect:(CGRect)rect 124 | { 125 | NSLog(@"%@", NSStringFromCGRect(rect)); 126 | NSDictionary *attrDict = [NSDictionary dictionaryWithObjectsAndKeys: 127 | (__bridge id)self.ctFont, kCTFontAttributeName, 128 | (__bridge id)self.ctParagraphStyle, kCTParagraphStyleAttributeName, nil]; 129 | 130 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:self.text attributes:attrDict]; 131 | 132 | [self drawCoreTextWithRect:rect attributedString:attrStr]; 133 | } 134 | 135 | @end 136 | -------------------------------------------------------------------------------- /CoreTextSample/Sample2.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample2.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "CoreTextView.h" 10 | 11 | @interface Sample2 : CoreTextView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreTextSample/Sample2.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample2.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample2.h" 10 | 11 | @implementation Sample2 12 | 13 | - (void)drawRect:(CGRect)rect 14 | { 15 | CTFontRef font = CTFontCreateWithName(CFSTR("AmericanTypewriter"), 20, NULL); 16 | NSDictionary *attrDict = [NSDictionary dictionaryWithObjectsAndKeys: 17 | // フォント 18 | (__bridge id)font, kCTFontAttributeName, 19 | // 中抜き文字のライン幅 20 | [NSNumber numberWithFloat:4.0f], kCTStrokeWidthAttributeName, 21 | // 中抜き文字のライン色 22 | (id)[UIColor blueColor].CGColor, kCTStrokeColorAttributeName, 23 | // 下線スタイル 24 | [NSNumber numberWithInt:kCTUnderlineStyleDouble], kCTUnderlineStyleAttributeName, 25 | // 下線色 26 | (id)[UIColor redColor].CGColor, kCTUnderlineColorAttributeName, nil]; 27 | CFRelease(font); 28 | 29 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:self.text attributes:attrDict]; 30 | 31 | [self drawCoreTextWithRect:rect attributedString:attrStr]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /CoreTextSample/Sample3.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample3.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "CoreTextView.h" 10 | 11 | @interface Sample3 : CoreTextView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreTextSample/Sample3.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample3.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample3.h" 10 | 11 | @implementation Sample3 12 | 13 | - (void)drawRect:(CGRect)rect 14 | { 15 | NSDictionary *attrDict = [NSDictionary dictionaryWithObjectsAndKeys: 16 | // 段落スタイル 17 | (__bridge id)self.ctParagraphStyle, kCTParagraphStyleAttributeName, nil]; 18 | 19 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:self.text attributes:attrDict]; 20 | 21 | [self drawCoreTextWithRect:rect attributedString:attrStr]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /CoreTextSample/Sample4.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample4.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/10. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "CoreTextView.h" 10 | 11 | @interface Sample4 : CoreTextView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreTextSample/Sample4.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample4.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/10. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample4.h" 10 | 11 | @implementation Sample4 12 | 13 | - (void)drawRect:(CGRect)rect 14 | { 15 | // フォントを明示的にヒラギノフォントし、かつ段落スタイルを設定すると日本語行間問題は解決…たぶん 16 | // 段落スタイルを設定しないと英語のみで行間が広くなる 17 | 18 | CTFontRef font = CTFontCreateWithName(CFSTR("HiraKakuProN-W3"), 12, NULL); 19 | NSDictionary *attrDict = [NSDictionary dictionaryWithObjectsAndKeys: 20 | (__bridge id)font, kCTFontAttributeName, 21 | (__bridge id)self.ctParagraphStyle, kCTParagraphStyleAttributeName, nil]; 22 | 23 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:self.text attributes:attrDict]; 24 | 25 | [self drawCoreTextWithRect:rect attributedString:attrStr]; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /CoreTextSample/Sample5.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample5.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "CoreTextView.h" 10 | 11 | @interface Sample5 : CoreTextView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreTextSample/Sample5.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample5.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample5.h" 10 | 11 | @implementation Sample5 12 | 13 | - (void)drawRect:(CGRect)rect 14 | { 15 | NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:self.text]; 16 | 17 | // 正規表現でアルファベットを探し設定。 18 | NSError *error; 19 | NSRegularExpression *regexp = [NSRegularExpression regularExpressionWithPattern:@"([a-zA-Z]*)" options:0 error:&error]; 20 | if (!error) { 21 | NSArray *arr = [regexp matchesInString:self.text options:0 range:NSMakeRange(0, self.text.length)]; 22 | for (NSTextCheckingResult *match in arr) { 23 | [attrStr addAttribute:(NSString*)kCTForegroundColorAttributeName value:(id)[UIColor blueColor].CGColor range:[match rangeAtIndex:1]]; 24 | } 25 | } 26 | 27 | [self drawCoreTextWithRect:rect attributedString:attrStr]; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /CoreTextSample/Sample6.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample6.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "CoreTextView.h" 10 | 11 | @interface Sample6 : CoreTextView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreTextSample/Sample6.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample6.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample6.h" 10 | #import "InfomationView.h" 11 | 12 | @interface Sample6 () 13 | 14 | @property (nonatomic) NSMutableAttributedString *attributedString; 15 | @property (nonatomic) CTFrameRef ctFrame; 16 | @property (nonatomic) InfomationView *infomationView; 17 | 18 | @end 19 | 20 | @implementation Sample6 21 | 22 | - (id)initWithFrame:(CGRect)frame 23 | { 24 | if (self = [super initWithFrame:frame]) { 25 | self.attributedString = [[NSMutableAttributedString alloc] initWithString:self.text]; 26 | NSError *error; 27 | NSRegularExpression *regexp = [NSRegularExpression regularExpressionWithPattern:@"([a-zA-Z]*)" options:0 error:&error]; 28 | if (!error) { 29 | NSArray *arr = [regexp matchesInString:self.text options:0 range:NSMakeRange(0, self.text.length)]; 30 | for (NSTextCheckingResult *match in arr) { 31 | [self.attributedString addAttribute:(NSString*)kCTForegroundColorAttributeName value:(id)[UIColor blueColor].CGColor range:[match rangeAtIndex:1]]; 32 | } 33 | } 34 | 35 | self.infomationView = [[InfomationView alloc] initWithFrame:CGRectMake( 36 | 0.f, 37 | self.bounds.size.height/2.f, 38 | self.bounds.size.width, 39 | self.bounds.size.height/2.f)]; 40 | [self addSubview:self.infomationView]; 41 | } 42 | return self; 43 | } 44 | 45 | - (void)drawRect:(CGRect)rect 46 | { 47 | CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFMutableAttributedStringRef)self.attributedString); 48 | CGPathRef framePath = [[UIBezierPath bezierPathWithRect:rect] CGPath]; 49 | 50 | if (self.ctFrame) { 51 | CFRelease(self.ctFrame); 52 | self.ctFrame = NULL; 53 | } 54 | 55 | self.ctFrame = CTFramesetterCreateFrame( 56 | framesetter, 57 | CFRangeMake(0.f, self.attributedString.length), 58 | framePath, 59 | NULL); 60 | 61 | [self drawCoreTextWithRect:rect ctFrame:self.ctFrame]; 62 | CFRelease(framesetter); 63 | } 64 | 65 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 66 | { 67 | // タッチpointの取得 68 | UITouch *touch = [touches anyObject]; 69 | CGPoint point = [touch locationInView:self]; 70 | // 座標系が上下逆なのでタッチpoint.yを反転 71 | point.y = CGRectGetHeight(self.bounds) - point.y; 72 | 73 | // CTFrame内の全ての行(CTLineRef)を取得 74 | NSArray *lines = (__bridge id)CTFrameGetLines(self.ctFrame); 75 | // 全ての行のベースラインpointを取得 76 | CGPoint *origins = malloc(sizeof(CGPoint) * [lines count]); 77 | CTFrameGetLineOrigins(self.ctFrame, CFRangeMake(0, [lines count]), origins); 78 | 79 | // 全ての行をループ 80 | for (int i = 0; i < [lines count]; i++) { 81 | CTLineRef line = (__bridge CTLineRef)([lines objectAtIndex:i]); 82 | // CTLineRef line = CFArrayGetValueAtIndex((__bridge CFArrayRef)lines, i); 83 | 84 | // 行のベースラインpointを取得 85 | CGPoint origin = *(origins + i); 86 | // 行の横幅、ascent, descent, leadingを取得 87 | CGFloat ascent, descent, leading; 88 | double width; 89 | width = CTLineGetTypographicBounds(line, &ascent, &descent, &leading); 90 | // 行のframeを計算 91 | CGRect lineFrame = CGRectMake( 92 | origin.x, 93 | origin.y - descent, 94 | width, 95 | ascent + descent); 96 | 97 | // タッチpointと一致する行か 98 | if (CGRectContainsPoint(lineFrame, point)) { 99 | self.infomationView.ascent = ascent; 100 | self.infomationView.descent = descent; 101 | self.infomationView.leading = leading; 102 | self.infomationView.lineFrame = lineFrame; 103 | self.infomationView.touchPoint = point; 104 | 105 | // タッチpointにある文字のindexを取得 106 | CFIndex touchIndex = CTLineGetStringIndexForPosition(line, point); 107 | if (touchIndex == kCFNotFound) { 108 | continue; 109 | } 110 | self.infomationView.touchIndex = touchIndex; 111 | 112 | // 文字のindexから属性が設定してあるrangeと属性辞書を取得 113 | NSRange touchRange; 114 | self.infomationView.attributedDictionary = [_attributedString attributesAtIndex:touchIndex effectiveRange:&touchRange]; 115 | self.infomationView.touchRange = touchRange; 116 | self.infomationView.touchText = [self.text substringWithRange:touchRange]; 117 | [self.infomationView redraw]; 118 | break; 119 | } 120 | } 121 | // Release objects 122 | if (origins) { 123 | free(origins), origins = NULL; 124 | } 125 | } 126 | 127 | @end 128 | -------------------------------------------------------------------------------- /CoreTextSample/Sample7.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample7.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "CoreTextView.h" 10 | 11 | @interface Sample7 : CoreTextView 12 | 13 | @property (nonatomic) CTFrameRef ctFrame; 14 | @property (nonatomic) NSMutableAttributedString *attributedString; 15 | @property (nonatomic) UIView *markTextView; 16 | - (void)updateTextMarkViewWithTouches:(NSSet *)touches withEvent:(UIEvent *)event; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /CoreTextSample/Sample7.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample7.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample7.h" 10 | 11 | @interface Sample7 () 12 | 13 | @end 14 | 15 | @implementation Sample7 16 | 17 | - (id)initWithFrame:(CGRect)frame 18 | { 19 | if (self = [super initWithFrame:frame]) { 20 | self.attributedString = [[NSMutableAttributedString alloc] initWithString:self.text]; 21 | NSError *error; 22 | NSRegularExpression *regexp = [NSRegularExpression regularExpressionWithPattern:@"([a-zA-Z]*)" options:0 error:&error]; 23 | if (!error) { 24 | NSArray *arr = [regexp matchesInString:self.text options:0 range:NSMakeRange(0, self.text.length)]; 25 | for (NSTextCheckingResult *match in arr) { 26 | [self.attributedString addAttribute:(NSString*)kCTForegroundColorAttributeName value:(id)[UIColor blueColor].CGColor range:[match rangeAtIndex:1]]; 27 | } 28 | } 29 | } 30 | return self; 31 | } 32 | 33 | - (void)drawRect:(CGRect)rect 34 | { 35 | CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFMutableAttributedStringRef)self.attributedString); 36 | CGPathRef framePath = [[UIBezierPath bezierPathWithRect:rect] CGPath]; 37 | 38 | if (self.ctFrame) { 39 | CFRelease(self.ctFrame); 40 | self.ctFrame = NULL; 41 | } 42 | self.ctFrame = CTFramesetterCreateFrame( 43 | framesetter, 44 | CFRangeMake(0.f, self.attributedString.length), 45 | framePath, 46 | NULL); 47 | 48 | [self drawCoreTextWithRect:rect ctFrame:self.ctFrame]; 49 | CFRelease(framesetter); 50 | } 51 | 52 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 53 | { 54 | [self updateTextMarkViewWithTouches:touches withEvent:event]; 55 | } 56 | 57 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 58 | { 59 | [self updateTextMarkViewWithTouches:touches withEvent:event]; 60 | } 61 | 62 | - (void)updateTextMarkViewWithTouches:(NSSet *)touches withEvent:(UIEvent *)event 63 | { 64 | // タッチpointの取得 65 | UITouch *touch = [touches anyObject]; 66 | CGPoint touchPoint = [touch locationInView:self]; 67 | // 座標系が上下逆なのでタッチpoint.yを反転 68 | touchPoint.y = CGRectGetHeight(self.bounds) - touchPoint.y; 69 | 70 | // CTFrame内の全ての行(CTLineRef)を取得 71 | NSArray *lines = (__bridge id)CTFrameGetLines(self.ctFrame); 72 | // 全ての行のベースラインpointを取得 73 | CGPoint *origins = malloc(sizeof(CGPoint) * [lines count]); 74 | CTFrameGetLineOrigins(self.ctFrame, CFRangeMake(0, [lines count]), origins); 75 | 76 | // 全ての行をループ 77 | for (int i = 0; i < [lines count]; i++) { 78 | CTLineRef line = (__bridge CTLineRef)[lines objectAtIndex:i]; 79 | // 行のベースラインpointを取得 80 | CGPoint origin = *(origins + i); 81 | // 行の横幅、ascent, descent, leadingを取得 82 | CGFloat ascent, descent, leading; 83 | double width; 84 | width = CTLineGetTypographicBounds(line, &ascent, &descent, &leading); 85 | // 行のframeを計算 86 | CGRect lineFrame = CGRectMake( 87 | origin.x, 88 | origin.y - descent, 89 | width, 90 | ascent + descent); 91 | 92 | // タッチpointと一致する行か 93 | if (CGRectContainsPoint(lineFrame, touchPoint)) { 94 | // タッチpointにある文字のindexを取得 95 | CFIndex touchIndex = CTLineGetStringIndexForPosition(line, touchPoint); 96 | /* 文字列の最後の数ピクセルの範囲がself.text.lengthを超えた値になる */ 97 | /* [注意] self.text.length の位置がtouchIndexが返って来るので範囲外エラーのチェックが必要 (取得方法が間違っている?) */ 98 | if (touchIndex == kCFNotFound || touchIndex >= self.text.length) { 99 | continue; 100 | } 101 | 102 | // 文字のindexから属性が設定してあるrangeと属性辞書を取得 103 | NSRange touchRange; 104 | [self.attributedString attributesAtIndex:touchIndex effectiveRange:&touchRange]; 105 | // 属性付き文字列のrangeから文字列の開始と終了の座標を取得 106 | CFIndex startIndex = touchRange.location; 107 | CGFloat startOffset = CTLineGetOffsetForStringIndex(line, startIndex, NULL); 108 | CFIndex endIndex = startIndex + touchRange.length; 109 | CGFloat endOffset = CTLineGetOffsetForStringIndex(line, endIndex, NULL); 110 | CGFloat touchTextWidth = endOffset - startOffset; 111 | 112 | CGRect markFrame = CGRectMake( 113 | startOffset, 114 | self.bounds.size.height - origin.y - ascent, // 上下を反転したベースラインyからascentを引く 115 | touchTextWidth, 116 | lineFrame.size.height); 117 | NSLog(@"%f %f %f", self.bounds.size.height, origin.y, ascent); 118 | if (!self.markTextView) { 119 | self.markTextView = [[UIView alloc] init]; 120 | [self addSubview:self.markTextView]; 121 | } 122 | self.markTextView.frame = markFrame; 123 | self.markTextView.backgroundColor = [UIColor colorWithRed:0.f green:0.342f blue:1.f alpha:0.3f]; 124 | [self.markTextView setNeedsDisplay]; 125 | break; 126 | } 127 | } 128 | // Release objects 129 | if (origins) { 130 | free(origins), origins = NULL; 131 | } 132 | } 133 | 134 | @end 135 | -------------------------------------------------------------------------------- /CoreTextSample/Sample8.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample8.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/09. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample7.h" 10 | 11 | @interface Sample8 : Sample7 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreTextSample/Sample8.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample8.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/09. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample8.h" 10 | #import "InfomationView.h" 11 | 12 | @interface Sample8 () 13 | 14 | - (NSString*)cfStringTokenizerTokenTypeDescription:(CFStringTokenizerTokenType)type; 15 | 16 | @end 17 | 18 | @implementation Sample8 19 | 20 | - (id)initWithFrame:(CGRect)frame 21 | { 22 | self = [super initWithFrame:frame]; 23 | if (self) { 24 | NSString *path = [[NSBundle mainBundle] pathForResource:@"Sample8" ofType:@"txt"]; 25 | self.text = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; 26 | 27 | self.attributedString = [[NSMutableAttributedString alloc] initWithString:self.text]; 28 | CTFontRef font = CTFontCreateWithName(CFSTR("Helvetica"), 12.f, NULL); 29 | 30 | /* 属性付き文字列に形態素の範囲を追加 */ 31 | CFRange range = CFRangeMake(0, [self.text length]); 32 | CFStringTokenizerRef tokenizer = CFStringTokenizerCreate( 33 | NULL, 34 | (__bridge CFStringRef)self.text, 35 | range, 36 | kCFStringTokenizerUnitWordBoundary, 37 | NULL); 38 | CFStringTokenizerTokenType tokenType = CFStringTokenizerGoToTokenAtIndex(tokenizer, 0); 39 | 40 | NSUInteger cnt = 0; 41 | while (tokenType != kCFStringTokenizerTokenNone || range.location + range.length < [self.text length]) { 42 | range = CFStringTokenizerGetCurrentTokenRange(tokenizer); 43 | if (range.location != kCFNotFound) { 44 | NSLog(@"%@\n%@", [self.text substringWithRange:NSMakeRange(range.location, range.length)], [self cfStringTokenizerTokenTypeDescription:tokenType]); 45 | 46 | /* iOS5では下記が有効*/ 47 | // [_attributedString addAttribute:(NSString*)kCTFontAttributeName 48 | // value:(__bridge id)font 49 | // range:NSMakeRange(range.location, range.length)]; 50 | 51 | /* iOS6から -attributesAtIndex:effectiveRange: のaRangeが隣接する同じ属性文字辞書はひとまとまりのRangeを返すようになった 52 | とりあえず交互に属性文字辞書を設定し回避 */ 53 | if (cnt % 2) { 54 | [self.attributedString addAttribute:(NSString*)kCTFontAttributeName 55 | value:(__bridge id)font 56 | range:NSMakeRange(range.location, range.length)]; 57 | } 58 | cnt++; 59 | tokenType = CFStringTokenizerAdvanceToNextToken(tokenizer); 60 | } 61 | } 62 | CFRelease(tokenizer); 63 | } 64 | return self; 65 | } 66 | 67 | - (NSString *)cfStringTokenizerTokenTypeDescription:(CFStringTokenizerTokenType)type 68 | { 69 | if (type == 0) { 70 | return @"kCFStringTokenizerTokenNone"; // = 0 71 | } 72 | NSArray *typeStrings = [NSArray arrayWithObjects: 73 | @"kCFStringTokenizerTokenNormal", // = 1 74 | @"kCFStringTokenizerTokenHasSubTokensMask", // 1L << 1 75 | @"kCFStringTokenizerTokenHasDerivedSubTokensMask", // 1L << 2 76 | @"kCFStringTokenizerTokenHasHasNumbersMask", // 1L << 3 77 | @"kCFStringTokenizerTokenHasNonLettersMask", // 1L << 4 78 | @"kCFStringTokenizerTokenIsCJWordMask", nil]; // 1L << 5 79 | 80 | NSMutableString *mStr = [[NSMutableString alloc] initWithString:@"{\n"]; 81 | for (int i = 0; i < [typeStrings count]; i++) { 82 | if (type % 2 == 1) { 83 | [mStr appendFormat:@"%@\n", [typeStrings objectAtIndex:i]]; 84 | } 85 | type >>= 1; 86 | } 87 | [mStr appendString:@"}"]; 88 | return [[NSString alloc] initWithString:mStr]; 89 | } 90 | 91 | @end 92 | -------------------------------------------------------------------------------- /CoreTextSample/Sample8.txt: -------------------------------------------------------------------------------- 1 | iOS 6では、Siriがより多くの言語を理解し、より多くの国で使えるようになるうえ、 2 | 新しいiPadでも利用できるようになります。だから世界中のさらに多くの場所で、さらにたくさんのことができるようになる、というわけです。 3 | 例えばiOS 6では、お気に入りのチームや選手の今日のスコアや最新データなどを知りたい時もSiriにたのめます。 4 | CFStringTokenizer allows you tokenize strings into words, sentences 5 | or paragraphs in a language-neutral way. It supports languages such as Japanese and Chinese that do not delimit words by spaces, as well as de-compounding German compounds. 6 | You can obtain Latin transcription for tokens. It also provides language identification API -------------------------------------------------------------------------------- /CoreTextSample/Sample9.h: -------------------------------------------------------------------------------- 1 | // 2 | // Sample9.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/10. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "CoreTextView.h" 10 | 11 | @interface Sample9 : CoreTextView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreTextSample/Sample9.m: -------------------------------------------------------------------------------- 1 | // 2 | // Sample9.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/10. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "Sample9.h" 10 | 11 | @interface Sample9 () 12 | 13 | @property (nonatomic) NSUInteger lineNum; 14 | 15 | @end 16 | 17 | @implementation Sample9 18 | 19 | - (void)drawRect:(CGRect)rect 20 | { 21 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:self.text]; 22 | 23 | CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attrStr); 24 | 25 | CGPathRef framePath = [[UIBezierPath bezierPathWithRect:rect] CGPath]; 26 | CTFrameRef frame = CTFramesetterCreateFrame( 27 | framesetter, 28 | CFRangeMake(0.f, attrStr.length), 29 | framePath, 30 | NULL); 31 | 32 | NSArray *lines = (__bridge id)CTFrameGetLines(frame); 33 | 34 | self.lineNum++; 35 | if (self.lineNum > [lines count]) { 36 | self.lineNum = [lines count]; 37 | } 38 | 39 | // 全ての行のベースラインpointを取得 40 | CGPoint *origins = malloc(sizeof(CGPoint) * [lines count]); 41 | CTFrameGetLineOrigins(frame, CFRangeMake(0, [lines count]), origins); 42 | 43 | CGContextRef context = UIGraphicsGetCurrentContext(); 44 | 45 | // 座標を上下反転 46 | CGContextTranslateCTM(context, 0, rect.size.height); 47 | CGContextScaleCTM(context, 1.0, -1.0); 48 | 49 | CGContextSaveGState(context); 50 | // CoreTextを1行づつ描画 51 | for (int i = 0; i < self.lineNum; i++) { 52 | CTLineRef line = (__bridge CTLineRef)[lines objectAtIndex:i]; 53 | // 行のベースラインpointを取得 54 | CGPoint origin = *(origins + i); 55 | // 行からdescentを取得 56 | CGFloat descent; 57 | CTLineGetTypographicBounds(line, nil, &descent, nil); 58 | // originはベースラインなのでdescentを引けば行の原点(その行の左下端)になる(Core Graphicsの座標系) 59 | CGContextSetTextPosition(context, origin.x, origin.y - descent); 60 | NSLog(@"%f %f %f", origin.x, origin.y, descent); 61 | CTLineDraw(line, context); 62 | } 63 | if (origins) { 64 | free(origins); 65 | origins = NULL; 66 | } 67 | CGContextRestoreGState(context); 68 | 69 | CFRelease(frame); 70 | CFRelease(framesetter); 71 | } 72 | 73 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 74 | { 75 | [super touchesEnded:touches withEvent:event]; 76 | [self setNeedsDisplay]; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /CoreTextSample/TableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewController.h 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreTextSample/TableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewController.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/08. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import "TableViewController.h" 10 | #import "CoreTextViewController.h" 11 | 12 | #import "Sample0.h" 13 | #import "Sample1.h" 14 | #import "Sample2.h" 15 | #import "Sample3.h" 16 | #import "Sample4.h" 17 | #import "Sample5.h" 18 | #import "Sample6.h" 19 | #import "Sample7.h" 20 | #import "Sample8.h" 21 | #import "Sample9.h" 22 | #import "Sample10.h" 23 | #import "Sample11.h" 24 | #import "Sample12.h" 25 | #import "Sample13.h" 26 | #import "Sample14.h" 27 | 28 | @interface TableViewController () 29 | 30 | @property (nonatomic) NSArray *cellTexts; 31 | 32 | @end 33 | 34 | @implementation TableViewController 35 | 36 | - (id)initWithStyle:(UITableViewStyle)style 37 | { 38 | self = [super initWithStyle:style]; 39 | if (self) { 40 | self.title = @"CoreText Sample"; 41 | self.cellTexts = [[NSArray alloc] initWithObjects: 42 | @"0. 最小限のコードで描画", 43 | @"1. 属性の設定1", 44 | @"2. 属性の設定2", 45 | @"3. 日本語行間問題の一部解決", 46 | @"4. 日本語行間問題の解決", 47 | @"5. 英語のみ文字色を変更", 48 | @"6. タップで情報取得", 49 | @"7. タップ範囲を囲う", 50 | @"8. タップ範囲を形態素で囲う", 51 | @"9. タップで1行ずつ描画", 52 | @"10. スクロールビュー", 53 | @"11. 10をUITextViewで", 54 | @"12. 1文字ずつ描画", 55 | @"13. 縦書", 56 | @"14. sizeToFit", nil]; 57 | } 58 | return self; 59 | } 60 | 61 | - (void)viewDidLoad 62 | { 63 | [super viewDidLoad]; 64 | // Uncomment the following line to preserve selection between presentations. 65 | // self.clearsSelectionOnViewWillAppear = NO; 66 | 67 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 68 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 69 | } 70 | 71 | - (void)viewDidUnload 72 | { 73 | [super viewDidUnload]; 74 | } 75 | 76 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 77 | { 78 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 79 | } 80 | 81 | #pragma mark - Table view data source 82 | 83 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 84 | { 85 | return 1; 86 | } 87 | 88 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 89 | { 90 | return [self.cellTexts count]; 91 | } 92 | 93 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 94 | { 95 | static NSString *CellIdentifier = @"Cell"; 96 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 97 | if (!cell) { 98 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; 99 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 100 | } 101 | cell.textLabel.text = [self.cellTexts objectAtIndex:indexPath.row]; 102 | if (indexPath.row == 3) { 103 | cell.detailTextLabel.text = @"※まだ日本語のみの描画で行間がつまる"; 104 | } else { 105 | cell.detailTextLabel.text = nil; 106 | } 107 | return cell; 108 | } 109 | 110 | #pragma mark - Table view delegate 111 | 112 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 113 | { 114 | UIView *contentView; 115 | CGRect frame = self.tableView.frame; 116 | switch (indexPath.row) { 117 | case 0: 118 | contentView = [[Sample0 alloc] initWithFrame:frame]; 119 | break; 120 | case 1: 121 | contentView = [[Sample1 alloc] initWithFrame:frame]; 122 | break; 123 | case 2: 124 | contentView = [[Sample2 alloc] initWithFrame:frame]; 125 | break; 126 | case 3: 127 | contentView = [[Sample3 alloc] initWithFrame:frame]; 128 | break; 129 | case 4: 130 | contentView = [[Sample4 alloc] initWithFrame:frame]; 131 | break; 132 | case 5: 133 | contentView = [[Sample5 alloc] initWithFrame:frame]; 134 | break; 135 | case 6: 136 | contentView = [[Sample6 alloc] initWithFrame:frame]; 137 | break; 138 | case 7: 139 | contentView = [[Sample7 alloc] initWithFrame:frame]; 140 | break; 141 | case 8: 142 | contentView = [[Sample8 alloc] initWithFrame:frame]; 143 | break; 144 | case 9: 145 | contentView = [[Sample9 alloc] initWithFrame:frame]; 146 | break; 147 | case 10: 148 | contentView = [[Sample10 alloc] initWithFrame:frame]; 149 | break; 150 | case 11: 151 | contentView = [[Sample11 alloc] initWithFrame:frame]; 152 | break; 153 | case 12: 154 | contentView = [[Sample12 alloc] initWithFrame:frame]; 155 | break; 156 | case 13: 157 | contentView = [[Sample13 alloc] initWithFrame:frame]; 158 | break; 159 | case 14: 160 | contentView = [[Sample14 alloc] initWithFrame:frame]; 161 | break; 162 | default: 163 | break; 164 | } 165 | CoreTextViewController *vc = [[CoreTextViewController alloc] initWithContentView:contentView]; 166 | vc.title = [self.cellTexts objectAtIndex:indexPath.row]; 167 | [self.navigationController pushViewController:vc animated:YES]; 168 | } 169 | 170 | @end 171 | -------------------------------------------------------------------------------- /CoreTextSample/Text.txt: -------------------------------------------------------------------------------- 1 | >日本語と英語が混在 2 | 510万ピクセルを持つRetinaディスプレイ。すべてがフラッシュのアーキテクチャ。クアッドコアのIntel Core i7プロセッサ。そのすべてを、薄さわずか1.8cm、重さ2.02kgのボディに。 3 | 4 | >日本語のみ 5 | 日本語行間問題とは、欧文フォントを指定し日本語を描画すると日本語はヒラギノフォントで描画される為、欧文フォントとのアセントとディセント、リーディングの違いから行間が不均等になる問題。 6 | 7 | >英語のみ 8 | Apple’s Industrial Design team tested 124 different prototypes of the EarPods on over 600 people. 9 | 10 | > 日本語行間問題のわかりやすい例 11 | Hello 12 | World g 13 | 漢字123 14 | 感じ 15 | abcdefg 16 | HelloWorld g漢字123感じabcdefg -------------------------------------------------------------------------------- /CoreTextSample/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /CoreTextSample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CoreTextSample 4 | // 5 | // Created by Yu Sugawara on 12/07/07. 6 | // Copyright (c) 2012年 Yu Sugawara. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yusuga/CoreTextSample/166a20fab2cb202d9b14fb5abd85852e2b5a1747/Default-568h@2x.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 注意 2 | 3 | - iOS 6時代に**Objective-C**で書いたサンプルなため、より良い解決方法があると思います。 4 | 5 | ## 環境 6 | 7 | - Xcode 13.4.1 8 | - 一部UIの崩れはありますが、そのままでビルド可能になっています。 9 | 10 | ## 内容 11 | 12 | - 最小限のコードでの描画 13 | - 文字属性の設定 14 | - 日本語行間問題の解決 15 | - タップ情報の取得 16 | - タップ範囲をViewで囲う 17 | - 1行ずつ描画 18 | - 1文字ずつアニメーションで描画 19 | - 縦書 20 | - sizeToFit 21 | 22 | ## 参考サイト 23 | 24 | [欧文書体の基礎知識](http://www.akibatec.net/wabunfont/study/basic/basic2.html) 25 | 26 | [日本語行間の問題について](http://novis.jimdo.com/2011/07/02/coretextの日本語行間の問題-解決/) 27 | 28 | [タップした文字列の取得について](http://hmdt.jp/blog/?p=88) 29 | 30 | [日本語の形態素での分解](https://groups.google.com/forum/#!msg/cocoa-dev-japan/jbFe_GqXvrU/gLZ_5kdST_8J) 31 | 32 | --------------------------------------------------------------------------------