PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/vcl/ios/source/gdi/salcoretextfontutils.cxx

https://bitbucket.org/markjenkins/libreoffice_ubuntu-debian-fixes
C++ | 611 lines | 531 code | 48 blank | 32 comment | 118 complexity | 99587329cb5c4d1b55dfdaa675febd9f MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause-No-Nuclear-License-2014
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /*
  3. * This file is part of the LibreOffice project.
  4. *
  5. * This Source Code Form is subject to the terms of the Mozilla Public
  6. * License, v. 2.0. If a copy of the MPL was not distributed with this
  7. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  8. *
  9. * This file incorporates work covered by the following license notice:
  10. *
  11. * Licensed to the Apache Software Foundation (ASF) under one or more
  12. * contributor license agreements. See the NOTICE file distributed
  13. * with this work for additional information regarding copyright
  14. * ownership. The ASF licenses this file to you under the Apache
  15. * License, Version 2.0 (the "License"); you may not use this file
  16. * except in compliance with the License. You may obtain a copy of
  17. * the License at http://www.apache.org/licenses/LICENSE-2.0 .
  18. */
  19. #include "ios/common.h"
  20. #include "ios/salcoretextfontutils.hxx"
  21. #include "ios/salgdi.h"
  22. #include "sft.hxx"
  23. #include "ios/salinst.h"
  24. static bool GetDevFontAttributes( CTFontDescriptorRef font_descriptor, ImplDevFontAttributes& rDFA )
  25. {
  26. // reset the attributes
  27. rDFA.meFamily = FAMILY_DONTKNOW;
  28. rDFA.mePitch = PITCH_VARIABLE;
  29. rDFA.meWidthType = WIDTH_NORMAL;
  30. rDFA.meWeight = WEIGHT_NORMAL;
  31. rDFA.meItalic = ITALIC_NONE;
  32. rDFA.mbSymbolFlag = false;
  33. rDFA.mbOrientation = true;
  34. rDFA.mbDevice = true;
  35. rDFA.mnQuality = 0;
  36. CFNumberRef format = (CFNumberRef)CTFontDescriptorCopyAttribute(font_descriptor, kCTFontFormatAttribute);
  37. int value = 0;
  38. CFNumberGetValue(format, kCFNumberIntType, &value);
  39. CFRelease(format);
  40. if (value == kCTFontFormatBitmap)
  41. {
  42. /* we don't want bitmap fonts */
  43. return false;
  44. }
  45. rDFA.mbSubsettable = true;
  46. rDFA.mbEmbeddable = false;
  47. CFStringRef family_name = (CFStringRef)CTFontDescriptorCopyAttribute(font_descriptor, kCTFontFamilyNameAttribute);
  48. rDFA.maName = GetOUString(family_name);
  49. CFRelease(family_name);
  50. CFDictionaryRef traits = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font_descriptor, kCTFontTraitsAttribute);
  51. CFNumberRef symbolics = (CFNumberRef)CFDictionaryGetValue(traits, kCTFontSymbolicTrait);
  52. value = 0;
  53. CFNumberGetValue(symbolics, kCFNumberIntType, &value);
  54. CFRelease(symbolics);
  55. if (value & kCTFontMonoSpaceTrait)
  56. {
  57. rDFA.mePitch = PITCH_FIXED;
  58. }
  59. if (value & kCTFontItalicTrait)
  60. {
  61. rDFA.meItalic = ITALIC_NORMAL;
  62. }
  63. if (value & kCTFontBoldTrait)
  64. {
  65. rDFA.meWeight = WEIGHT_BOLD;
  66. }
  67. if (value & kCTFontCondensedTrait)
  68. {
  69. rDFA.meWidthType = WIDTH_CONDENSED;
  70. }
  71. else if (value & kCTFontExpandedTrait)
  72. {
  73. rDFA.meWidthType = WIDTH_EXPANDED;
  74. }
  75. switch(value & kCTFontClassMaskTrait)
  76. {
  77. case kCTFontOldStyleSerifsClass:
  78. rDFA.meFamily = FAMILY_ROMAN;
  79. break;
  80. case kCTFontTransitionalSerifsClass:
  81. case kCTFontModernSerifsClass:
  82. case kCTFontClarendonSerifsClass:
  83. case kCTFontSlabSerifsClass:
  84. case kCTFontFreeformSerifsClass:
  85. break;
  86. case kCTFontSansSerifClass:
  87. rDFA.meFamily = FAMILY_SWISS;
  88. case kCTFontOrnamentalsClass:
  89. rDFA.meFamily = FAMILY_DECORATIVE;
  90. break;
  91. case kCTFontScriptsClass:
  92. rDFA.meFamily = FAMILY_SCRIPT;
  93. break;
  94. case kCTFontSymbolicClass:
  95. rDFA.mbSymbolFlag = true;
  96. break;
  97. }
  98. CFNumberRef weight = (CFNumberRef)CFDictionaryGetValue(traits, kCTFontWeightTrait);
  99. float fdval = 0.0;
  100. CFNumberGetValue(weight, kCFNumberFloatType, &fdval);
  101. if (fdval > 0.6)
  102. {
  103. rDFA.meWeight = WEIGHT_BLACK;
  104. }
  105. else if (fdval > 0.4)
  106. {
  107. rDFA.meWeight = WEIGHT_ULTRABOLD;
  108. }
  109. else if (fdval > 0.3)
  110. {
  111. rDFA.meWeight = WEIGHT_BOLD;
  112. }
  113. else if (fdval > 0.0)
  114. {
  115. rDFA.meWeight = WEIGHT_SEMIBOLD;
  116. }
  117. else if (fdval <= -0.8)
  118. {
  119. rDFA.meWeight = WEIGHT_ULTRALIGHT;
  120. }
  121. else if (fdval <= -0.4)
  122. {
  123. rDFA.meWeight = WEIGHT_LIGHT;
  124. }
  125. else if (fdval <= -0.3)
  126. {
  127. rDFA.meWeight = WEIGHT_SEMILIGHT;
  128. }
  129. else if (fdval <= -0.2)
  130. {
  131. rDFA.meWeight = WEIGHT_THIN;
  132. }
  133. else
  134. {
  135. rDFA.meWeight = WEIGHT_NORMAL;
  136. }
  137. CFStringRef string_ref = (CFStringRef)CTFontDescriptorCopyAttribute(font_descriptor, kCTFontStyleNameAttribute);
  138. rtl::OUString font_name = GetOUString(string_ref);
  139. rtl::OUString font_name_lc(font_name.toAsciiLowerCase());
  140. CFRelease(string_ref);
  141. // heuristics to adjust font slant
  142. if ( (font_name_lc.indexOf("oblique") != -1) ||
  143. (font_name_lc.indexOf("inclined") != -1) ||
  144. (font_name_lc.indexOf("slanted") != -1) )
  145. {
  146. rDFA.meItalic = ITALIC_OBLIQUE;
  147. }
  148. // heuristics to adjust font width
  149. if (font_name_lc.indexOf("narrow") != -1)
  150. {
  151. rDFA.meWidthType = WIDTH_SEMI_CONDENSED;
  152. }
  153. // heuristics for font family type
  154. if ( (font_name_lc.indexOf("script") != -1) ||
  155. (font_name_lc.indexOf("chancery") != -1) ||
  156. (font_name_lc.indexOf("zapfino") != -1))
  157. {
  158. rDFA.meFamily = FAMILY_SCRIPT;
  159. }
  160. else if ( (font_name_lc.indexOf("comic") != -1) ||
  161. (font_name_lc.indexOf("outline") != -1) ||
  162. (font_name_lc.indexOf("pinpoint") != -1) )
  163. {
  164. rDFA.meFamily = FAMILY_DECORATIVE;
  165. }
  166. else if ( (font_name_lc.indexOf("sans") != -1) ||
  167. (font_name_lc.indexOf("arial") != -1) )
  168. {
  169. rDFA.meFamily = FAMILY_SWISS;
  170. }
  171. else if ( (font_name_lc.indexOf("roman") != -1) ||
  172. (font_name_lc.indexOf("times") != -1) )
  173. {
  174. rDFA.meFamily = FAMILY_ROMAN;
  175. }
  176. return true;
  177. }
  178. SystemFontList::SystemFontList()
  179. {
  180. CTFontCollectionRef font_collection = CTFontCollectionCreateFromAvailableFonts(NULL);
  181. if (font_collection)
  182. {
  183. CFArrayRef font_descriptors = CTFontCollectionCreateMatchingFontDescriptors(font_collection);
  184. for(int i = 0; i < CFArrayGetCount(font_descriptors); i++)
  185. {
  186. CTFontDescriptorRef font_descriptor = (CTFontDescriptorRef)CFArrayGetValueAtIndex(font_descriptors, i);
  187. CTFontRef font = CTFontCreateWithFontDescriptor(font_descriptor, 0, NULL);
  188. ImplDevFontAttributes devfont_attr;
  189. if (GetDevFontAttributes( font_descriptor, devfont_attr ) )
  190. {
  191. ImplCoreTextFontData* font_data = new ImplCoreTextFontData(devfont_attr, font);
  192. if (font_data && font_data->GetCTFont())
  193. {
  194. m_aFontContainer [ font_data->GetCTFont() ] = font_data;
  195. }
  196. }
  197. CFRelease(font);
  198. }
  199. CFRelease(font_descriptors);
  200. }
  201. CFRelease(font_collection);
  202. }
  203. SystemFontList::~SystemFontList()
  204. {
  205. CoreTextFontContainer::const_iterator it = m_aFontContainer.begin();
  206. for(; it != m_aFontContainer.end(); ++it )
  207. delete (*it).second;
  208. m_aFontContainer.clear();
  209. }
  210. ImplCoreTextFontData* SystemFontList::GetFontDataFromRef( CTFontRef font ) const
  211. {
  212. CoreTextFontContainer::const_iterator it = m_aFontContainer.find( font );
  213. return it == m_aFontContainer.end() ? NULL : (*it).second;
  214. }
  215. void SystemFontList::AnnounceFonts( ImplDevFontList& rFontList ) const
  216. {
  217. CoreTextFontContainer::const_iterator it = m_aFontContainer.begin();
  218. for(; it != m_aFontContainer.end(); ++it )
  219. {
  220. rFontList.Add( (*it).second->Clone() );
  221. }
  222. }
  223. ImplCoreTextFontData::ImplCoreTextFontData( const ImplDevFontAttributes& rDFA, CTFontRef font )
  224. : PhysicalFontFace( rDFA, 0 )
  225. , m_CTFontRef((CTFontRef)CFRetain(font))
  226. , m_pCharMap( NULL )
  227. , m_bHasOs2Table( false )
  228. , m_bOs2TableRead( false )
  229. , m_bCmapTableRead( false )
  230. , m_bHasCJKSupport( false )
  231. , m_bFontCapabilitiesRead( false )
  232. {
  233. }
  234. ImplCoreTextFontData::~ImplCoreTextFontData()
  235. {
  236. if ( m_pCharMap )
  237. {
  238. m_pCharMap->DeReference();
  239. }
  240. if ( m_CTFontRef )
  241. {
  242. CFRelease(m_CTFontRef);
  243. }
  244. }
  245. PhysicalFontFace* ImplCoreTextFontData::Clone() const
  246. {
  247. ImplCoreTextFontData* pClone = new ImplCoreTextFontData(*this);
  248. if ( m_pCharMap )
  249. {
  250. m_pCharMap->AddReference();
  251. }
  252. if ( m_CTFontRef )
  253. {
  254. pClone->m_CTFontRef = (CTFontRef)CFRetain(m_CTFontRef);
  255. }
  256. return pClone;
  257. }
  258. ImplFontEntry* ImplCoreTextFontData::CreateFontInstance(FontSelectPattern& rFSD) const
  259. {
  260. return new ImplFontEntry(rFSD);
  261. }
  262. const ImplFontCharMap* ImplCoreTextFontData::GetImplFontCharMap()
  263. {
  264. // return the cached charmap
  265. if ( m_pCharMap )
  266. {
  267. return m_pCharMap;
  268. }
  269. // set the default charmap
  270. m_pCharMap = ImplFontCharMap::GetDefaultMap();
  271. m_pCharMap->AddReference();
  272. // get the CMAP byte size
  273. CFDataRef rCmapTable = CTFontCopyTable( m_CTFontRef, kCTFontTableCmap, kCTFontTableOptionNoOptions);
  274. if (!rCmapTable)
  275. {
  276. return m_pCharMap;
  277. }
  278. if (!m_bCmapTableRead)
  279. {
  280. m_bCmapTableRead = true;
  281. DetermineCJKSupport_cmap(rCmapTable);
  282. }
  283. // parse the CMAP
  284. CmapResult aCmapResult;
  285. if (ParseCMAP( CFDataGetBytePtr(rCmapTable), CFDataGetLength(rCmapTable), aCmapResult ) )
  286. {
  287. m_pCharMap = new ImplFontCharMap( aCmapResult );
  288. m_pCharMap->AddReference();
  289. }
  290. CFRelease(rCmapTable);
  291. return m_pCharMap;
  292. }
  293. bool ImplCoreTextFontData::GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities)
  294. {
  295. // read this only once per font
  296. if ( m_bFontCapabilitiesRead )
  297. {
  298. rFontCapabilities = m_aFontCapabilities;
  299. return !rFontCapabilities.maUnicodeRange.empty() || !rFontCapabilities.maCodePageRange.empty();
  300. }
  301. m_bFontCapabilitiesRead = true;
  302. // get the GSUB table raw data
  303. CFDataRef rGSUBTable = CTFontCopyTable( m_CTFontRef, kCTFontTableGSUB, kCTFontTableOptionNoOptions);
  304. if (rGSUBTable)
  305. {
  306. vcl::getTTScripts(m_aFontCapabilities.maGSUBScriptTags,
  307. CFDataGetBytePtr(rGSUBTable), CFDataGetLength(rGSUBTable));
  308. CFRelease(rGSUBTable);
  309. }
  310. CFDataRef OS2_Table = CTFontCopyTable( m_CTFontRef, kCTFontTableOS2, kCTFontTableOptionNoOptions);
  311. if (OS2_Table)
  312. {
  313. vcl::getTTCoverage(
  314. m_aFontCapabilities.maUnicodeRange,
  315. m_aFontCapabilities.maCodePageRange,
  316. CFDataGetBytePtr(OS2_Table), CFDataGetLength(OS2_Table));
  317. /* while we are at it let's solve HasCJK for the same price */
  318. if (!m_bOs2TableRead )
  319. {
  320. m_bOs2TableRead = true;
  321. m_bHasOs2Table = true;
  322. DetermineCJKSupport_OS2(OS2_Table);
  323. }
  324. CFRelease(OS2_Table);
  325. }
  326. rFontCapabilities = m_aFontCapabilities;
  327. return !rFontCapabilities.maUnicodeRange.empty() || !rFontCapabilities.maCodePageRange.empty();
  328. }
  329. struct font_table
  330. {
  331. unsigned char* table;
  332. unsigned char* dir_entry;
  333. unsigned char* cursor;
  334. };
  335. void addTable(struct font_table* table, CTFontTableTag tag, CFDataRef data)
  336. {
  337. if (data && CFDataGetLength(data) > 0)
  338. {
  339. *(uint32_t*)table->dir_entry = CFSwapInt32HostToBig(tag);
  340. table->dir_entry += 4;
  341. *(uint32_t*)table->dir_entry = 0; /* TODO: checksum */
  342. table->dir_entry += 4;
  343. *(uint32_t*)table->dir_entry = CFSwapInt32HostToBig((uint32_t)((uintptr_t)table->cursor - (uintptr_t)table));
  344. table->dir_entry += 4;
  345. *(uint32_t*)table->dir_entry = CFSwapInt32HostToBig(CFDataGetLength(data));
  346. table->dir_entry += 4;
  347. memcpy(table->cursor, CFDataGetBytePtr(data), CFDataGetLength(data));
  348. table->cursor += CFDataGetLength(data);
  349. }
  350. }
  351. bool ImplCoreTextFontData::GetRawFontData( std::vector<unsigned char>& rBuffer, bool* pJustCFF ) const
  352. {
  353. bool rc;
  354. int table_count = 0;
  355. CFDataRef CFF_table = CTFontCopyTable( m_CTFontRef, kCTFontTableCFF, kCTFontTableOptionNoOptions);
  356. if (pJustCFF)
  357. {
  358. if (CFF_table)
  359. {
  360. *pJustCFF = CFDataGetLength(CFF_table) ? true : false;
  361. }
  362. if (CFF_table)
  363. {
  364. CFRelease(CFF_table);
  365. return true;
  366. }
  367. else
  368. {
  369. return false;
  370. }
  371. }
  372. size_t total_len = 0;
  373. CFDataRef head_table = CTFontCopyTable( m_CTFontRef, kCTFontTableHead, kCTFontTableOptionNoOptions);
  374. CFDataRef maxp_table = CTFontCopyTable( m_CTFontRef, kCTFontTableMaxp, kCTFontTableOptionNoOptions);
  375. CFDataRef cmap_table = CTFontCopyTable( m_CTFontRef, kCTFontTableHead, kCTFontTableOptionNoOptions);
  376. CFDataRef name_table = CTFontCopyTable( m_CTFontRef, kCTFontTableName, kCTFontTableOptionNoOptions);
  377. CFDataRef hhea_table = CTFontCopyTable( m_CTFontRef, kCTFontTableHhea, kCTFontTableOptionNoOptions);
  378. CFDataRef hmtx_table = CTFontCopyTable( m_CTFontRef, kCTFontTableHmtx, kCTFontTableOptionNoOptions);
  379. rc = false;
  380. if (head_table && maxp_table && cmap_table && name_table && hhea_table && hmtx_table)
  381. {
  382. if (CFDataGetLength(head_table) &&
  383. CFDataGetLength(maxp_table) &&
  384. CFDataGetLength(name_table) &&
  385. CFDataGetLength(hhea_table) &&
  386. CFDataGetLength(hmtx_table))
  387. {
  388. table_count += 6;
  389. total_len = CFDataGetLength(head_table) +
  390. CFDataGetLength(maxp_table) +
  391. CFDataGetLength(name_table) +
  392. CFDataGetLength(hhea_table) +
  393. CFDataGetLength(hmtx_table);
  394. rc = true;
  395. }
  396. }
  397. CFDataRef loca_table = NULL;
  398. CFDataRef glyf_table = NULL;
  399. CFDataRef prep_table = NULL;
  400. CFDataRef cvt_table = NULL;
  401. CFDataRef fpgm_table = NULL;
  402. if (rc)
  403. {
  404. if (!CFF_table || CFDataGetLength(CFF_table) == 0)
  405. {
  406. loca_table = CTFontCopyTable( m_CTFontRef, kCTFontTableLoca, kCTFontTableOptionNoOptions);
  407. glyf_table = CTFontCopyTable( m_CTFontRef, kCTFontTableGlyf, kCTFontTableOptionNoOptions);
  408. if (!loca_table || !glyf_table || !CFDataGetLength(loca_table) || !CFDataGetLength(glyf_table))
  409. {
  410. rc = false;
  411. }
  412. else
  413. {
  414. table_count += 2;
  415. total_len += CFDataGetLength(loca_table) + CFDataGetLength(glyf_table);
  416. prep_table = CTFontCopyTable( m_CTFontRef, kCTFontTablePrep, kCTFontTableOptionNoOptions);
  417. cvt_table = CTFontCopyTable( m_CTFontRef, kCTFontTableCvt, kCTFontTableOptionNoOptions);
  418. fpgm_table = CTFontCopyTable( m_CTFontRef, kCTFontTableFpgm, kCTFontTableOptionNoOptions);
  419. if (prep_table || CFDataGetLength(prep_table) > 0)
  420. {
  421. table_count += 1;
  422. total_len += CFDataGetLength(prep_table);
  423. }
  424. if (cvt_table || CFDataGetLength(cvt_table) > 0)
  425. {
  426. table_count += 1;
  427. total_len += CFDataGetLength(cvt_table);
  428. }
  429. if (fpgm_table || CFDataGetLength(fpgm_table) > 0)
  430. {
  431. table_count += 1;
  432. total_len += CFDataGetLength(fpgm_table);
  433. }
  434. }
  435. }
  436. else
  437. {
  438. table_count += 1;
  439. total_len += CFDataGetLength(CFF_table);
  440. }
  441. }
  442. if (rc)
  443. {
  444. total_len += 12 + 16 * table_count;
  445. rBuffer.resize(total_len);
  446. struct font_table table;
  447. unsigned char* cursor = &rBuffer[0];
  448. int nLog2 = 0;
  449. while( (table_count >> nLog2) > 1 ) ++nLog2;
  450. table.table = cursor;
  451. *(uint16_t*)cursor = CFSwapInt16HostToBig(1);
  452. cursor += 2;
  453. *(uint16_t*)cursor = 0;
  454. cursor += 2;
  455. *(uint16_t*)cursor = CFSwapInt16HostToBig(table_count);
  456. cursor += 2;
  457. *(uint16_t*)cursor = CFSwapInt16HostToBig(nLog2 * 16);
  458. cursor += 2;
  459. *(uint16_t*)cursor = CFSwapInt16HostToBig(nLog2);
  460. cursor += 2;
  461. *(uint16_t*)cursor = CFSwapInt16HostToBig((table_count - nLog2) * 16); // rangeShift
  462. cursor += 2;
  463. table.dir_entry = cursor;
  464. cursor += (16 * table_count);
  465. table.cursor = cursor;
  466. addTable(&table, kCTFontTableCmap, cmap_table);
  467. addTable(&table, kCTFontTableCvt, cvt_table);
  468. addTable(&table, kCTFontTableFpgm, fpgm_table);
  469. addTable(&table, kCTFontTableCFF, CFF_table);
  470. addTable(&table, kCTFontTableGlyf, glyf_table);
  471. addTable(&table, kCTFontTableLoca, loca_table);
  472. addTable(&table, kCTFontTableHead, head_table);
  473. addTable(&table, kCTFontTableHhea, hhea_table);
  474. addTable(&table, kCTFontTableHmtx, hmtx_table);
  475. addTable(&table, kCTFontTableMaxp, maxp_table);
  476. addTable(&table, kCTFontTableName, name_table);
  477. addTable(&table, kCTFontTablePrep, prep_table);
  478. }
  479. SafeCFRelease(cmap_table);
  480. SafeCFRelease(cvt_table);
  481. SafeCFRelease(fpgm_table);
  482. SafeCFRelease(CFF_table);
  483. SafeCFRelease(glyf_table);
  484. SafeCFRelease(loca_table);
  485. SafeCFRelease(head_table);
  486. SafeCFRelease(hhea_table);
  487. SafeCFRelease(hmtx_table);
  488. SafeCFRelease(maxp_table);
  489. SafeCFRelease(name_table);
  490. SafeCFRelease(prep_table);
  491. return rc;
  492. }
  493. void ImplCoreTextFontData::DetermineCJKSupport_OS2(CFDataRef rOS2Table)
  494. {
  495. if (CFDataGetLength(rOS2Table) >= 48)
  496. {
  497. const unsigned short* pOS2buffer = (const unsigned short*)CFDataGetBytePtr(rOS2Table);
  498. const unsigned short version = CFSwapInt16BigToHost(pOS2buffer[0]);
  499. if ( version >= 1)
  500. {
  501. const unsigned short unicode_range = CFSwapInt16BigToHost(pOS2buffer[23]);
  502. if ( unicode_range & 0x2DF0)
  503. {
  504. m_bHasCJKSupport = true;
  505. }
  506. }
  507. }
  508. }
  509. void ImplCoreTextFontData::DetermineCJKSupport_cmap(CFDataRef rCmapTable)
  510. {
  511. int table_len = CFDataGetLength(rCmapTable) / 2;
  512. if (table_len >= 12)
  513. {
  514. const unsigned short* pCmap = (const unsigned short*)CFDataGetBytePtr(rCmapTable);
  515. if (pCmap[0] == 0)
  516. {
  517. short nb_sub_tables = CFSwapInt16BigToHost(pCmap[1]);
  518. for(int i = 2; --nb_sub_tables >= 0 && i < table_len; i += 4)
  519. {
  520. short platform = CFSwapInt16BigToHost(pCmap[i]);
  521. if ( platform == kFontMacintoshPlatform )
  522. {
  523. short encoding = CFSwapInt16BigToHost(pCmap[i+1]);
  524. if ( encoding == kFontJapaneseScript ||
  525. encoding == kFontTraditionalChineseScript ||
  526. encoding == kFontKoreanScript ||
  527. encoding == kFontSimpleChineseScript )
  528. {
  529. m_bHasCJKSupport = true;
  530. break;
  531. }
  532. }
  533. }
  534. }
  535. }
  536. }
  537. bool ImplCoreTextFontData::HasCJKSupport( void )
  538. {
  539. // read this only once per font
  540. if (!m_bOs2TableRead )
  541. {
  542. m_bOs2TableRead = true;
  543. CFDataRef rOS2Table = CTFontCopyTable( m_CTFontRef, kCTFontTableOS2, kCTFontTableOptionNoOptions);
  544. if (rOS2Table)
  545. {
  546. m_bHasOs2Table = true;
  547. DetermineCJKSupport_OS2(rOS2Table);
  548. CFRelease(rOS2Table);
  549. }
  550. }
  551. if ( !m_bCmapTableRead && !m_bHasOs2Table && !m_bHasCJKSupport )
  552. {
  553. m_bCmapTableRead = true;
  554. CFDataRef rCmapTable = CTFontCopyTable( m_CTFontRef, kCTFontTableCmap, kCTFontTableOptionNoOptions);
  555. if (rCmapTable)
  556. {
  557. DetermineCJKSupport_cmap(rCmapTable);
  558. CFRelease(rCmapTable);
  559. }
  560. }
  561. return m_bHasCJKSupport;
  562. }
  563. /* vim:set shiftwidth=4 softtabstop=4 expandtab: */