src/java.desktop/share/native/libfontmanager/harfbuzz/hb-coretext.cc
changeset 50352 25db2c8f3cf8
parent 48274 51772bf1fb0c
child 50826 f5b95be8b6e2
equal deleted inserted replaced
50351:9289c4214a35 50352:25db2c8f3cf8
    37 
    37 
    38 /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
    38 /* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
    39 #define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
    39 #define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
    40 
    40 
    41 static CGFloat
    41 static CGFloat
    42 coretext_font_size (float ptem)
    42 coretext_font_size_from_ptem (float ptem)
    43 {
    43 {
    44   /* CoreText points are CSS pixels (96 per inch),
    44   /* CoreText points are CSS pixels (96 per inch),
    45    * NOT typographic points (72 per inch).
    45    * NOT typographic points (72 per inch).
    46    *
    46    *
    47    * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
    47    * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
    48    */
    48    */
    49   ptem *= 96.f / 72.f;
    49   ptem *= 96.f / 72.f;
    50   return ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem;
    50   return ptem <= 0.f ? HB_CORETEXT_DEFAULT_FONT_SIZE : ptem;
    51 }
    51 }
       
    52 static float
       
    53 coretext_font_size_to_ptem (CGFloat size)
       
    54 {
       
    55   size *= 72.f / 96.f;
       
    56   return size <= 0.f ? 0 : size;
       
    57 }
    52 
    58 
    53 static void
    59 static void
    54 release_table_data (void *user_data)
    60 release_table_data (void *user_data)
    55 {
    61 {
    56   CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data);
    62   CFDataRef cf_data = reinterpret_cast<CFDataRef> (user_data);
    66     return nullptr;
    72     return nullptr;
    67 
    73 
    68   const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data));
    74   const char *data = reinterpret_cast<const char*> (CFDataGetBytePtr (cf_data));
    69   const size_t length = CFDataGetLength (cf_data);
    75   const size_t length = CFDataGetLength (cf_data);
    70   if (!data || !length)
    76   if (!data || !length)
       
    77   {
       
    78     CFRelease (cf_data);
    71     return nullptr;
    79     return nullptr;
       
    80   }
    72 
    81 
    73   return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY,
    82   return hb_blob_create (data, length, HB_MEMORY_MODE_READONLY,
    74                          reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)),
    83                          reinterpret_cast<void *> (const_cast<__CFData *> (cf_data)),
    75                          release_table_data);
    84                          release_table_data);
    76 }
    85 }
    79 _hb_cg_font_release (void *data)
    88 _hb_cg_font_release (void *data)
    80 {
    89 {
    81   CGFontRelease ((CGFontRef) data);
    90   CGFontRelease ((CGFontRef) data);
    82 }
    91 }
    83 
    92 
    84 hb_face_t *
       
    85 hb_coretext_face_create (CGFontRef cg_font)
       
    86 {
       
    87   return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
       
    88 }
       
    89 
    93 
    90 HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face)
    94 HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face)
    91 HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font,
    95 HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font,
    92         fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size (font->ptem)) <= .5
    96         fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) <= .5
    93 )
    97 )
    94 
       
    95 /*
       
    96  * shaper face data
       
    97  */
       
    98 
    98 
    99 static CTFontDescriptorRef
    99 static CTFontDescriptorRef
   100 get_last_resort_font_desc (void)
   100 get_last_resort_font_desc (void)
   101 {
   101 {
   102   // TODO Handle allocation failures?
   102   // TODO Handle allocation failures?
   265 _hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
   265 _hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
   266 {
   266 {
   267   CFRelease ((CGFontRef) data);
   267   CFRelease ((CGFontRef) data);
   268 }
   268 }
   269 
   269 
       
   270 hb_face_t *
       
   271 hb_coretext_face_create (CGFontRef cg_font)
       
   272 {
       
   273   return hb_face_create_for_tables (reference_table, CGFontRetain (cg_font), _hb_cg_font_release);
       
   274 }
       
   275 
   270 /*
   276 /*
   271  * Since: 0.9.10
   277  * Since: 0.9.10
   272  */
   278  */
   273 CGFontRef
   279 CGFontRef
   274 hb_coretext_face_get_cg_font (hb_face_t *face)
   280 hb_coretext_face_get_cg_font (hb_face_t *face)
   276   if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
   282   if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
   277   return (CGFontRef) HB_SHAPER_DATA_GET (face);
   283   return (CGFontRef) HB_SHAPER_DATA_GET (face);
   278 }
   284 }
   279 
   285 
   280 
   286 
   281 /*
       
   282  * shaper font data
       
   283  */
       
   284 
       
   285 hb_coretext_shaper_font_data_t *
   287 hb_coretext_shaper_font_data_t *
   286 _hb_coretext_shaper_font_data_create (hb_font_t *font)
   288 _hb_coretext_shaper_font_data_create (hb_font_t *font)
   287 {
   289 {
   288   hb_face_t *face = font->face;
   290   hb_face_t *face = font->face;
   289   if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
   291   if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
   290   CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
   292   CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
   291 
   293 
   292   CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size (font->ptem));
   294   CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size_from_ptem (font->ptem));
   293 
   295 
   294   if (unlikely (!ct_font))
   296   if (unlikely (!ct_font))
   295   {
   297   {
   296     DEBUG_MSG (CORETEXT, font, "CGFont creation failed..");
   298     DEBUG_MSG (CORETEXT, font, "CGFont creation failed..");
   297     return nullptr;
   299     return nullptr;
   303 void
   305 void
   304 _hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
   306 _hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
   305 {
   307 {
   306   CFRelease ((CTFontRef) data);
   308   CFRelease ((CTFontRef) data);
   307 }
   309 }
       
   310 
       
   311 /*
       
   312  * Since: 1.7.2
       
   313  */
       
   314 hb_font_t *
       
   315 hb_coretext_font_create (CTFontRef ct_font)
       
   316 {
       
   317   CGFontRef cg_font = CTFontCopyGraphicsFont (ct_font, nullptr);
       
   318   hb_face_t *face = hb_coretext_face_create (cg_font);
       
   319   CFRelease (cg_font);
       
   320   hb_font_t *font = hb_font_create (face);
       
   321   hb_face_destroy (face);
       
   322 
       
   323   if (unlikely (hb_object_is_inert (font)))
       
   324     return font;
       
   325 
       
   326   hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font)));
       
   327 
       
   328   /* Let there be dragons here... */
       
   329   HB_SHAPER_DATA_GET (font) = (hb_coretext_shaper_font_data_t *) CFRetain (ct_font);
       
   330 
       
   331   return font;
       
   332 }
       
   333 
       
   334 CTFontRef
       
   335 hb_coretext_font_get_ct_font (hb_font_t *font)
       
   336 {
       
   337   if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return nullptr;
       
   338   return (CTFontRef) HB_SHAPER_DATA_GET (font);
       
   339 }
       
   340 
   308 
   341 
   309 
   342 
   310 /*
   343 /*
   311  * shaper shape_plan data
   344  * shaper shape_plan data
   312  */
   345  */
   324 }
   357 }
   325 
   358 
   326 void
   359 void
   327 _hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED)
   360 _hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED)
   328 {
   361 {
   329 }
       
   330 
       
   331 CTFontRef
       
   332 hb_coretext_font_get_ct_font (hb_font_t *font)
       
   333 {
       
   334   if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return nullptr;
       
   335   return (CTFontRef)HB_SHAPER_DATA_GET (font);
       
   336 }
   362 }
   337 
   363 
   338 
   364 
   339 /*
   365 /*
   340  * shaper
   366  * shaper
   852         CFStringRef lang = CFStringCreateWithCStringNoCopy (kCFAllocatorDefault,
   878         CFStringRef lang = CFStringCreateWithCStringNoCopy (kCFAllocatorDefault,
   853                                                             hb_language_to_string (buffer->props.language),
   879                                                             hb_language_to_string (buffer->props.language),
   854                                                             kCFStringEncodingUTF8,
   880                                                             kCFStringEncodingUTF8,
   855                                                             kCFAllocatorNull);
   881                                                             kCFAllocatorNull);
   856         if (unlikely (!lang))
   882         if (unlikely (!lang))
       
   883         {
       
   884           CFRelease (attr_string);
   857           FAIL ("CFStringCreateWithCStringNoCopy failed");
   885           FAIL ("CFStringCreateWithCStringNoCopy failed");
       
   886         }
   858         CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
   887         CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
   859                                         kCTLanguageAttributeName, lang);
   888                                         kCTLanguageAttributeName, lang);
   860         CFRelease (lang);
   889         CFRelease (lang);
   861       }
   890       }
   862       CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
   891       CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
   921                                                     1,
   950                                                     1,
   922                                                     &kCFTypeDictionaryKeyCallBacks,
   951                                                     &kCFTypeDictionaryKeyCallBacks,
   923                                                     &kCFTypeDictionaryValueCallBacks);
   952                                                     &kCFTypeDictionaryValueCallBacks);
   924       CFRelease (level_number);
   953       CFRelease (level_number);
   925       if (unlikely (!options))
   954       if (unlikely (!options))
       
   955       {
       
   956         CFRelease (attr_string);
   926         FAIL ("CFDictionaryCreate failed");
   957         FAIL ("CFDictionaryCreate failed");
       
   958       }
   927 
   959 
   928       CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedStringAndOptions (attr_string, options);
   960       CTTypesetterRef typesetter = CTTypesetterCreateWithAttributedStringAndOptions (attr_string, options);
   929       CFRelease (options);
   961       CFRelease (options);
   930       CFRelease (attr_string);
   962       CFRelease (attr_string);
   931       if (unlikely (!typesetter))
   963       if (unlikely (!typesetter))
   998          * backend.
  1030          * backend.
   999          *
  1031          *
  1000          * However, even that wouldn't work if we were passed in the CGFont to
  1032          * However, even that wouldn't work if we were passed in the CGFont to
  1001          * construct a hb_face to begin with.
  1033          * construct a hb_face to begin with.
  1002          *
  1034          *
  1003          * See: http://github.com/behdad/harfbuzz/pull/36
  1035          * See: http://github.com/harfbuzz/harfbuzz/pull/36
  1004          *
  1036          *
  1005          * Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098
  1037          * Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098
  1006          */
  1038          */
  1007         bool matched = false;
  1039         bool matched = false;
  1008         for (unsigned int i = 0; i < range_records.len; i++)
  1040         for (unsigned int i = 0; i < range_records.len; i++)
  1011             matched = true;
  1043             matched = true;
  1012             break;
  1044             break;
  1013           }
  1045           }
  1014         if (!matched)
  1046         if (!matched)
  1015         {
  1047         {
  1016           CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, 0);
  1048           CGFontRef run_cg_font = CTFontCopyGraphicsFont (run_ct_font, nullptr);
  1017           if (run_cg_font)
  1049           if (run_cg_font)
  1018           {
  1050           {
  1019             matched = CFEqual (run_cg_font, cg_font);
  1051             matched = CFEqual (run_cg_font, cg_font);
  1020             CFRelease (run_cg_font);
  1052             CFRelease (run_cg_font);
  1021           }
  1053           }
  1184 
  1216 
  1185       buffer->len += num_glyphs;
  1217       buffer->len += num_glyphs;
  1186     }
  1218     }
  1187 
  1219 
  1188     /* Mac OS 10.6 doesn't have kCTTypesetterOptionForcedEmbeddingLevel,
  1220     /* Mac OS 10.6 doesn't have kCTTypesetterOptionForcedEmbeddingLevel,
  1189      * or if it does, it doesn't resepct it.  So we get runs with wrong
  1221      * or if it does, it doesn't respect it.  So we get runs with wrong
  1190      * directions.  As such, disable the assert...  It wouldn't crash, but
  1222      * directions.  As such, disable the assert...  It wouldn't crash, but
  1191      * cursoring will be off...
  1223      * cursoring will be off...
  1192      *
  1224      *
  1193      * http://crbug.com/419769
  1225      * http://crbug.com/419769
  1194      */
  1226      */
  1210       {
  1242       {
  1211         pos->x_advance = info->mask;
  1243         pos->x_advance = info->mask;
  1212         pos->x_offset = info->var1.i32;
  1244         pos->x_offset = info->var1.i32;
  1213         pos->y_offset = info->var2.i32;
  1245         pos->y_offset = info->var2.i32;
  1214 
  1246 
  1215         info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
       
  1216 
       
  1217         info++, pos++;
  1247         info++, pos++;
  1218       }
  1248       }
  1219     else
  1249     else
  1220       for (unsigned int i = 0; i < count; i++)
  1250       for (unsigned int i = 0; i < count; i++)
  1221       {
  1251       {
  1222         pos->y_advance = info->mask;
  1252         pos->y_advance = info->mask;
  1223         pos->x_offset = info->var1.i32;
  1253         pos->x_offset = info->var1.i32;
  1224         pos->y_offset = info->var2.i32;
  1254         pos->y_offset = info->var2.i32;
  1225 
       
  1226         info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
       
  1227 
  1255 
  1228         info++, pos++;
  1256         info++, pos++;
  1229       }
  1257       }
  1230 
  1258 
  1231     /* Fix up clusters so that we never return out-of-order indices;
  1259     /* Fix up clusters so that we never return out-of-order indices;