< prev index next >
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-coretext.cc
Print this page
*** 24,42 ****
*
* Mozilla Author(s): Jonathan Kew
* Google Author(s): Behdad Esfahbod
*/
! #define HB_SHAPER coretext
!
! #include "hb-private.hh"
! #include "hb-debug.hh"
! #include "hb-shaper-impl-private.hh"
#include "hb-coretext.h"
#include <math.h>
/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
static CGFloat
coretext_font_size_from_ptem (float ptem)
--- 24,50 ----
*
* Mozilla Author(s): Jonathan Kew
* Google Author(s): Behdad Esfahbod
*/
! #include "hb.hh"
! #include "hb-shaper-impl.hh"
#include "hb-coretext.h"
+ #include "hb-aat-layout.hh"
#include <math.h>
+
+ /**
+ * SECTION:hb-coretext
+ * @title: hb-coretext
+ * @short_description: CoreText integration
+ * @include: hb-coretext.h
+ *
+ * Functions for using HarfBuzz with the CoreText fonts.
+ **/
+
/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
static CGFloat
coretext_font_size_from_ptem (float ptem)
*** 89,105 ****
{
CGFontRelease ((CGFontRef) data);
}
- HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face)
- HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font,
- fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) <= .5
- )
-
static CTFontDescriptorRef
! get_last_resort_font_desc (void)
{
// TODO Handle allocation failures?
CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize (CFSTR("LastResort"), 0);
CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault,
(const void **) &last_resort,
--- 97,108 ----
{
CGFontRelease ((CGFontRef) data);
}
static CTFontDescriptorRef
! get_last_resort_font_desc ()
{
// TODO Handle allocation failures?
CTFontDescriptorRef last_resort = CTFontDescriptorCreateWithNameAndSize (CFSTR("LastResort"), 0);
CFArrayRef cascade_list = CFArrayCreate (kCFAllocatorDefault,
(const void **) &last_resort,
*** 209,219 ****
if (!isEmojiFont)
return ct_font;
}
CFURLRef original_url = nullptr;
! #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
ATSFontRef atsFont;
FSRef fsref;
OSStatus status;
atsFont = CTFontGetPlatformFont (ct_font, NULL);
status = ATSFontGetFileReference (atsFont, &fsref);
--- 212,222 ----
if (!isEmojiFont)
return ct_font;
}
CFURLRef original_url = nullptr;
! #if TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
ATSFontRef atsFont;
FSRef fsref;
OSStatus status;
atsFont = CTFontGetPlatformFont (ct_font, NULL);
status = ATSFontGetFileReference (atsFont, &fsref);
*** 239,249 ****
* Avoid reconfiguring the cascade lists if the new font is outside the
* system locations that we cannot access from the sandboxed renderer
* process in Blink. This can be detected by the new file URL location
* that the newly found font points to. */
CFURLRef new_url = nullptr;
! #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
atsFont = CTFontGetPlatformFont (new_ct_font, NULL);
status = ATSFontGetFileReference (atsFont, &fsref);
if (status == noErr)
new_url = CFURLCreateFromFSRef (NULL, &fsref);
#else
--- 242,252 ----
* Avoid reconfiguring the cascade lists if the new font is outside the
* system locations that we cannot access from the sandboxed renderer
* process in Blink. This can be detected by the new file URL location
* that the newly found font points to. */
CFURLRef new_url = nullptr;
! #if TARGET_OS_OSX && MAC_OS_X_VERSION_MIN_REQUIRED < 1060
atsFont = CTFontGetPlatformFont (new_ct_font, NULL);
status = ATSFontGetFileReference (atsFont, &fsref);
if (status == noErr)
new_url = CFURLCreateFromFSRef (NULL, &fsref);
#else
*** 268,293 ****
if (original_url)
CFRelease (original_url);
return ct_font;
}
! hb_coretext_shaper_face_data_t *
_hb_coretext_shaper_face_data_create (hb_face_t *face)
{
CGFontRef cg_font = create_cg_font (face);
if (unlikely (!cg_font))
{
DEBUG_MSG (CORETEXT, face, "CGFont creation failed..");
return nullptr;
}
! return (hb_coretext_shaper_face_data_t *) cg_font;
}
void
! _hb_coretext_shaper_face_data_destroy (hb_coretext_shaper_face_data_t *data)
{
CFRelease ((CGFontRef) data);
}
hb_face_t *
--- 271,296 ----
if (original_url)
CFRelease (original_url);
return ct_font;
}
! hb_coretext_face_data_t *
_hb_coretext_shaper_face_data_create (hb_face_t *face)
{
CGFontRef cg_font = create_cg_font (face);
if (unlikely (!cg_font))
{
DEBUG_MSG (CORETEXT, face, "CGFont creation failed..");
return nullptr;
}
! return (hb_coretext_face_data_t *) cg_font;
}
void
! _hb_coretext_shaper_face_data_destroy (hb_coretext_face_data_t *data)
{
CFRelease ((CGFontRef) data);
}
hb_face_t *
*** 300,338 ****
* Since: 0.9.10
*/
CGFontRef
hb_coretext_face_get_cg_font (hb_face_t *face)
{
! if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
! return (CGFontRef) HB_SHAPER_DATA_GET (face);
}
! hb_coretext_shaper_font_data_t *
_hb_coretext_shaper_font_data_create (hb_font_t *font)
{
hb_face_t *face = font->face;
! if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
! CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size_from_ptem (font->ptem));
if (unlikely (!ct_font))
{
DEBUG_MSG (CORETEXT, font, "CGFont creation failed..");
return nullptr;
}
! return (hb_coretext_shaper_font_data_t *) ct_font;
}
void
! _hb_coretext_shaper_font_data_destroy (hb_coretext_shaper_font_data_t *data)
{
CFRelease ((CTFontRef) data);
}
/*
* Since: 1.7.2
*/
hb_font_t *
hb_coretext_font_create (CTFontRef ct_font)
--- 303,373 ----
* Since: 0.9.10
*/
CGFontRef
hb_coretext_face_get_cg_font (hb_face_t *face)
{
! return (CGFontRef) (const void *) face->data.coretext;
}
! hb_coretext_font_data_t *
_hb_coretext_shaper_font_data_create (hb_font_t *font)
{
hb_face_t *face = font->face;
! const hb_coretext_face_data_t *face_data = face->data.coretext;
! if (unlikely (!face_data)) return nullptr;
! CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size_from_ptem (font->ptem));
if (unlikely (!ct_font))
{
DEBUG_MSG (CORETEXT, font, "CGFont creation failed..");
return nullptr;
}
! return (hb_coretext_font_data_t *) ct_font;
}
void
! _hb_coretext_shaper_font_data_destroy (hb_coretext_font_data_t *data)
{
CFRelease ((CTFontRef) data);
}
+ static const hb_coretext_font_data_t *
+ hb_coretext_font_data_sync (hb_font_t *font)
+ {
+ retry:
+ const hb_coretext_font_data_t *data = font->data.coretext;
+ if (unlikely (!data)) return nullptr;
+
+ if (fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) > .5)
+ {
+ /* XXX-MT-bug
+ * Note that evaluating condition above can be dangerous if another thread
+ * got here first and destructed data. That's, as always, bad use pattern.
+ * If you modify the font (change font size), other threads must not be
+ * using it at the same time. However, since this check is delayed to
+ * when one actually tries to shape something, this is a XXX race condition
+ * (and the only one we have that I know of) right now. Ie. you modify the
+ * font size in one thread, then (supposedly safely) try to use it from two
+ * or more threads and BOOM! I'm not sure how to fix this. We want RCU.
+ */
+
+ /* Drop and recreate. */
+ /* If someone dropped it in the mean time, throw it away and don't touch it.
+ * Otherwise, destruct it. */
+ if (likely (font->data.coretext.cmpexch (const_cast<hb_coretext_font_data_t *> (data), nullptr)))
+ _hb_coretext_shaper_font_data_destroy (const_cast<hb_coretext_font_data_t *> (data));
+ else
+ goto retry;
+ }
+ return font->data.coretext;
+ }
+
+
/*
* Since: 1.7.2
*/
hb_font_t *
hb_coretext_font_create (CTFontRef ct_font)
*** 341,389 ****
hb_face_t *face = hb_coretext_face_create (cg_font);
CFRelease (cg_font);
hb_font_t *font = hb_font_create (face);
hb_face_destroy (face);
! if (unlikely (hb_object_is_inert (font)))
return font;
hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font)));
/* Let there be dragons here... */
! HB_SHAPER_DATA_GET (font) = (hb_coretext_shaper_font_data_t *) CFRetain (ct_font);
return font;
}
CTFontRef
hb_coretext_font_get_ct_font (hb_font_t *font)
{
! if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return nullptr;
! return (CTFontRef) HB_SHAPER_DATA_GET (font);
! }
!
!
!
! /*
! * shaper shape_plan data
! */
!
! struct hb_coretext_shaper_shape_plan_data_t {};
!
! hb_coretext_shaper_shape_plan_data_t *
! _hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
! const hb_feature_t *user_features HB_UNUSED,
! unsigned int num_user_features HB_UNUSED,
! const int *coords HB_UNUSED,
! unsigned int num_coords HB_UNUSED)
! {
! return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
! }
!
! void
! _hb_coretext_shaper_shape_plan_data_destroy (hb_coretext_shaper_shape_plan_data_t *data HB_UNUSED)
! {
}
/*
* shaper
--- 376,401 ----
hb_face_t *face = hb_coretext_face_create (cg_font);
CFRelease (cg_font);
hb_font_t *font = hb_font_create (face);
hb_face_destroy (face);
! if (unlikely (hb_object_is_immutable (font)))
return font;
hb_font_set_ptem (font, coretext_font_size_to_ptem (CTFontGetSize(ct_font)));
/* Let there be dragons here... */
! font->data.coretext.cmpexch (nullptr, (hb_coretext_font_data_t *) CFRetain (ct_font));
return font;
}
CTFontRef
hb_coretext_font_get_ct_font (hb_font_t *font)
{
! const hb_coretext_font_data_t *data = hb_coretext_font_data_sync (font);
! return data ? (CTFontRef) data : nullptr;
}
/*
* shaper
*** 430,633 ****
unsigned int index_first; /* == start */
unsigned int index_last; /* == end - 1 */
};
- /* The following enum members are added in OS X 10.8. */
- #define kAltHalfWidthTextSelector 6
- #define kAltProportionalTextSelector 5
- #define kAlternateHorizKanaOffSelector 1
- #define kAlternateHorizKanaOnSelector 0
- #define kAlternateKanaType 34
- #define kAlternateVertKanaOffSelector 3
- #define kAlternateVertKanaOnSelector 2
- #define kCaseSensitiveLayoutOffSelector 1
- #define kCaseSensitiveLayoutOnSelector 0
- #define kCaseSensitiveLayoutType 33
- #define kCaseSensitiveSpacingOffSelector 3
- #define kCaseSensitiveSpacingOnSelector 2
- #define kContextualAlternatesOffSelector 1
- #define kContextualAlternatesOnSelector 0
- #define kContextualAlternatesType 36
- #define kContextualLigaturesOffSelector 19
- #define kContextualLigaturesOnSelector 18
- #define kContextualSwashAlternatesOffSelector 5
- #define kContextualSwashAlternatesOnSelector 4
- #define kDefaultLowerCaseSelector 0
- #define kDefaultUpperCaseSelector 0
- #define kHistoricalLigaturesOffSelector 21
- #define kHistoricalLigaturesOnSelector 20
- #define kHojoCharactersSelector 12
- #define kJIS2004CharactersSelector 11
- #define kLowerCasePetiteCapsSelector 2
- #define kLowerCaseSmallCapsSelector 1
- #define kLowerCaseType 37
- #define kMathematicalGreekOffSelector 11
- #define kMathematicalGreekOnSelector 10
- #define kNLCCharactersSelector 13
- #define kQuarterWidthTextSelector 4
- #define kScientificInferiorsSelector 4
- #define kStylisticAltEightOffSelector 17
- #define kStylisticAltEightOnSelector 16
- #define kStylisticAltEighteenOffSelector 37
- #define kStylisticAltEighteenOnSelector 36
- #define kStylisticAltElevenOffSelector 23
- #define kStylisticAltElevenOnSelector 22
- #define kStylisticAltFifteenOffSelector 31
- #define kStylisticAltFifteenOnSelector 30
- #define kStylisticAltFiveOffSelector 11
- #define kStylisticAltFiveOnSelector 10
- #define kStylisticAltFourOffSelector 9
- #define kStylisticAltFourOnSelector 8
- #define kStylisticAltFourteenOffSelector 29
- #define kStylisticAltFourteenOnSelector 28
- #define kStylisticAltNineOffSelector 19
- #define kStylisticAltNineOnSelector 18
- #define kStylisticAltNineteenOffSelector 39
- #define kStylisticAltNineteenOnSelector 38
- #define kStylisticAltOneOffSelector 3
- #define kStylisticAltOneOnSelector 2
- #define kStylisticAltSevenOffSelector 15
- #define kStylisticAltSevenOnSelector 14
- #define kStylisticAltSeventeenOffSelector 35
- #define kStylisticAltSeventeenOnSelector 34
- #define kStylisticAltSixOffSelector 13
- #define kStylisticAltSixOnSelector 12
- #define kStylisticAltSixteenOffSelector 33
- #define kStylisticAltSixteenOnSelector 32
- #define kStylisticAltTenOffSelector 21
- #define kStylisticAltTenOnSelector 20
- #define kStylisticAltThirteenOffSelector 27
- #define kStylisticAltThirteenOnSelector 26
- #define kStylisticAltThreeOffSelector 7
- #define kStylisticAltThreeOnSelector 6
- #define kStylisticAltTwelveOffSelector 25
- #define kStylisticAltTwelveOnSelector 24
- #define kStylisticAltTwentyOffSelector 41
- #define kStylisticAltTwentyOnSelector 40
- #define kStylisticAltTwoOffSelector 5
- #define kStylisticAltTwoOnSelector 4
- #define kStylisticAlternativesType 35
- #define kSwashAlternatesOffSelector 3
- #define kSwashAlternatesOnSelector 2
- #define kThirdWidthTextSelector 3
- #define kTraditionalNamesCharactersSelector 14
- #define kUpperCasePetiteCapsSelector 2
- #define kUpperCaseSmallCapsSelector 1
- #define kUpperCaseType 38
-
- /* Table data courtesy of Apple. */
- static const struct feature_mapping_t {
- FourCharCode otFeatureTag;
- uint16_t aatFeatureType;
- uint16_t selectorToEnable;
- uint16_t selectorToDisable;
- } feature_mappings[] = {
- { 'c2pc', kUpperCaseType, kUpperCasePetiteCapsSelector, kDefaultUpperCaseSelector },
- { 'c2sc', kUpperCaseType, kUpperCaseSmallCapsSelector, kDefaultUpperCaseSelector },
- { 'calt', kContextualAlternatesType, kContextualAlternatesOnSelector, kContextualAlternatesOffSelector },
- { 'case', kCaseSensitiveLayoutType, kCaseSensitiveLayoutOnSelector, kCaseSensitiveLayoutOffSelector },
- { 'clig', kLigaturesType, kContextualLigaturesOnSelector, kContextualLigaturesOffSelector },
- { 'cpsp', kCaseSensitiveLayoutType, kCaseSensitiveSpacingOnSelector, kCaseSensitiveSpacingOffSelector },
- { 'cswh', kContextualAlternatesType, kContextualSwashAlternatesOnSelector, kContextualSwashAlternatesOffSelector },
- { 'dlig', kLigaturesType, kRareLigaturesOnSelector, kRareLigaturesOffSelector },
- { 'expt', kCharacterShapeType, kExpertCharactersSelector, 16 },
- { 'frac', kFractionsType, kDiagonalFractionsSelector, kNoFractionsSelector },
- { 'fwid', kTextSpacingType, kMonospacedTextSelector, 7 },
- { 'halt', kTextSpacingType, kAltHalfWidthTextSelector, 7 },
- { 'hist', kLigaturesType, kHistoricalLigaturesOnSelector, kHistoricalLigaturesOffSelector },
- { 'hkna', kAlternateKanaType, kAlternateHorizKanaOnSelector, kAlternateHorizKanaOffSelector, },
- { 'hlig', kLigaturesType, kHistoricalLigaturesOnSelector, kHistoricalLigaturesOffSelector },
- { 'hngl', kTransliterationType, kHanjaToHangulSelector, kNoTransliterationSelector },
- { 'hojo', kCharacterShapeType, kHojoCharactersSelector, 16 },
- { 'hwid', kTextSpacingType, kHalfWidthTextSelector, 7 },
- { 'ital', kItalicCJKRomanType, kCJKItalicRomanOnSelector, kCJKItalicRomanOffSelector },
- { 'jp04', kCharacterShapeType, kJIS2004CharactersSelector, 16 },
- { 'jp78', kCharacterShapeType, kJIS1978CharactersSelector, 16 },
- { 'jp83', kCharacterShapeType, kJIS1983CharactersSelector, 16 },
- { 'jp90', kCharacterShapeType, kJIS1990CharactersSelector, 16 },
- { 'liga', kLigaturesType, kCommonLigaturesOnSelector, kCommonLigaturesOffSelector },
- { 'lnum', kNumberCaseType, kUpperCaseNumbersSelector, 2 },
- { 'mgrk', kMathematicalExtrasType, kMathematicalGreekOnSelector, kMathematicalGreekOffSelector },
- { 'nlck', kCharacterShapeType, kNLCCharactersSelector, 16 },
- { 'onum', kNumberCaseType, kLowerCaseNumbersSelector, 2 },
- { 'ordn', kVerticalPositionType, kOrdinalsSelector, kNormalPositionSelector },
- { 'palt', kTextSpacingType, kAltProportionalTextSelector, 7 },
- { 'pcap', kLowerCaseType, kLowerCasePetiteCapsSelector, kDefaultLowerCaseSelector },
- { 'pkna', kTextSpacingType, kProportionalTextSelector, 7 },
- { 'pnum', kNumberSpacingType, kProportionalNumbersSelector, 4 },
- { 'pwid', kTextSpacingType, kProportionalTextSelector, 7 },
- { 'qwid', kTextSpacingType, kQuarterWidthTextSelector, 7 },
- { 'ruby', kRubyKanaType, kRubyKanaOnSelector, kRubyKanaOffSelector },
- { 'sinf', kVerticalPositionType, kScientificInferiorsSelector, kNormalPositionSelector },
- { 'smcp', kLowerCaseType, kLowerCaseSmallCapsSelector, kDefaultLowerCaseSelector },
- { 'smpl', kCharacterShapeType, kSimplifiedCharactersSelector, 16 },
- { 'ss01', kStylisticAlternativesType, kStylisticAltOneOnSelector, kStylisticAltOneOffSelector },
- { 'ss02', kStylisticAlternativesType, kStylisticAltTwoOnSelector, kStylisticAltTwoOffSelector },
- { 'ss03', kStylisticAlternativesType, kStylisticAltThreeOnSelector, kStylisticAltThreeOffSelector },
- { 'ss04', kStylisticAlternativesType, kStylisticAltFourOnSelector, kStylisticAltFourOffSelector },
- { 'ss05', kStylisticAlternativesType, kStylisticAltFiveOnSelector, kStylisticAltFiveOffSelector },
- { 'ss06', kStylisticAlternativesType, kStylisticAltSixOnSelector, kStylisticAltSixOffSelector },
- { 'ss07', kStylisticAlternativesType, kStylisticAltSevenOnSelector, kStylisticAltSevenOffSelector },
- { 'ss08', kStylisticAlternativesType, kStylisticAltEightOnSelector, kStylisticAltEightOffSelector },
- { 'ss09', kStylisticAlternativesType, kStylisticAltNineOnSelector, kStylisticAltNineOffSelector },
- { 'ss10', kStylisticAlternativesType, kStylisticAltTenOnSelector, kStylisticAltTenOffSelector },
- { 'ss11', kStylisticAlternativesType, kStylisticAltElevenOnSelector, kStylisticAltElevenOffSelector },
- { 'ss12', kStylisticAlternativesType, kStylisticAltTwelveOnSelector, kStylisticAltTwelveOffSelector },
- { 'ss13', kStylisticAlternativesType, kStylisticAltThirteenOnSelector, kStylisticAltThirteenOffSelector },
- { 'ss14', kStylisticAlternativesType, kStylisticAltFourteenOnSelector, kStylisticAltFourteenOffSelector },
- { 'ss15', kStylisticAlternativesType, kStylisticAltFifteenOnSelector, kStylisticAltFifteenOffSelector },
- { 'ss16', kStylisticAlternativesType, kStylisticAltSixteenOnSelector, kStylisticAltSixteenOffSelector },
- { 'ss17', kStylisticAlternativesType, kStylisticAltSeventeenOnSelector, kStylisticAltSeventeenOffSelector },
- { 'ss18', kStylisticAlternativesType, kStylisticAltEighteenOnSelector, kStylisticAltEighteenOffSelector },
- { 'ss19', kStylisticAlternativesType, kStylisticAltNineteenOnSelector, kStylisticAltNineteenOffSelector },
- { 'ss20', kStylisticAlternativesType, kStylisticAltTwentyOnSelector, kStylisticAltTwentyOffSelector },
- { 'subs', kVerticalPositionType, kInferiorsSelector, kNormalPositionSelector },
- { 'sups', kVerticalPositionType, kSuperiorsSelector, kNormalPositionSelector },
- { 'swsh', kContextualAlternatesType, kSwashAlternatesOnSelector, kSwashAlternatesOffSelector },
- { 'titl', kStyleOptionsType, kTitlingCapsSelector, kNoStyleOptionsSelector },
- { 'tnam', kCharacterShapeType, kTraditionalNamesCharactersSelector, 16 },
- { 'tnum', kNumberSpacingType, kMonospacedNumbersSelector, 4 },
- { 'trad', kCharacterShapeType, kTraditionalCharactersSelector, 16 },
- { 'twid', kTextSpacingType, kThirdWidthTextSelector, 7 },
- { 'unic', kLetterCaseType, 14, 15 },
- { 'valt', kTextSpacingType, kAltProportionalTextSelector, 7 },
- { 'vert', kVerticalSubstitutionType, kSubstituteVerticalFormsOnSelector, kSubstituteVerticalFormsOffSelector },
- { 'vhal', kTextSpacingType, kAltHalfWidthTextSelector, 7 },
- { 'vkna', kAlternateKanaType, kAlternateVertKanaOnSelector, kAlternateVertKanaOffSelector },
- { 'vpal', kTextSpacingType, kAltProportionalTextSelector, 7 },
- { 'vrt2', kVerticalSubstitutionType, kSubstituteVerticalFormsOnSelector, kSubstituteVerticalFormsOffSelector },
- { 'zero', kTypographicExtrasType, kSlashedZeroOnSelector, kSlashedZeroOffSelector },
- };
-
- static int
- _hb_feature_mapping_cmp (const void *key_, const void *entry_)
- {
- unsigned int key = * (unsigned int *) key_;
- const feature_mapping_t * entry = (const feature_mapping_t *) entry_;
- return key < entry->otFeatureTag ? -1 :
- key > entry->otFeatureTag ? 1 :
- 0;
- }
-
hb_bool_t
_hb_coretext_shape (hb_shape_plan_t *shape_plan,
hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
unsigned int num_features)
{
hb_face_t *face = font->face;
! CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
! CTFontRef ct_font = (CTFontRef) HB_SHAPER_DATA_GET (font);
CGFloat ct_font_size = CTFontGetSize (ct_font);
CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size;
/* Attach marks to their bases, to match the 'ot' shaper.
! * Adapted from hb-ot-shape:hb_form_clusters().
* Note that this only makes us be closer to the 'ot' shaper,
* but by no means the same. For example, if there's
* B1 M1 B2 M2, and B1-B2 form a ligature, M2's cluster will
* continue pointing to B2 even though B2 was merged into B1's
* cluster... */
--- 442,468 ----
unsigned int index_first; /* == start */
unsigned int index_last; /* == end - 1 */
};
hb_bool_t
_hb_coretext_shape (hb_shape_plan_t *shape_plan,
hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
unsigned int num_features)
{
hb_face_t *face = font->face;
! CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
! CTFontRef ct_font = (CTFontRef) hb_coretext_font_data_sync (font);
CGFloat ct_font_size = CTFontGetSize (ct_font);
CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
CGFloat y_mult = (CGFloat) font->y_scale / ct_font_size;
/* Attach marks to their bases, to match the 'ot' shaper.
! * Adapted from a very old version of hb-ot-shape:hb_form_clusters().
* Note that this only makes us be closer to the 'ot' shaper,
* but by no means the same. For example, if there's
* B1 M1 B2 M2, and B1-B2 form a ligature, M2's cluster will
* continue pointing to B2 even though B2 was merged into B1's
* cluster... */
*** 639,666 ****
for (unsigned int i = 1; i < count; i++)
if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (unicode->general_category (info[i].codepoint)))
buffer->merge_clusters (i - 1, i + 1);
}
! hb_auto_t<hb_vector_t<feature_record_t> > feature_records;
! hb_auto_t<hb_vector_t<range_record_t> > range_records;
/*
* Set up features.
* (copied + modified from code from hb-uniscribe.cc)
*/
if (num_features)
{
/* Sort features by start/end events. */
! hb_auto_t<hb_vector_t<feature_event_t> > feature_events;
for (unsigned int i = 0; i < num_features; i++)
{
! const feature_mapping_t * mapping = (const feature_mapping_t *) bsearch (&features[i].tag,
! feature_mappings,
! ARRAY_LENGTH (feature_mappings),
! sizeof (feature_mappings[0]),
! _hb_feature_mapping_cmp);
if (!mapping)
continue;
active_feature_t feature;
feature.rec.feature = mapping->aatFeatureType;
--- 474,497 ----
for (unsigned int i = 1; i < count; i++)
if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (unicode->general_category (info[i].codepoint)))
buffer->merge_clusters (i - 1, i + 1);
}
! hb_vector_t<feature_record_t> feature_records;
! hb_vector_t<range_record_t> range_records;
/*
* Set up features.
* (copied + modified from code from hb-uniscribe.cc)
*/
if (num_features)
{
/* Sort features by start/end events. */
! hb_vector_t<feature_event_t> feature_events;
for (unsigned int i = 0; i < num_features; i++)
{
! const hb_aat_feature_mapping_t * mapping = hb_aat_layout_find_feature_mapping (features[i].tag);
if (!mapping)
continue;
active_feature_t feature;
feature.rec.feature = mapping->aatFeatureType;
*** 692,719 ****
event->start = false;
event->feature = feature;
}
/* Scan events and save features for each range. */
! hb_auto_t<hb_vector_t<active_feature_t> > active_features;
unsigned int last_index = 0;
! for (unsigned int i = 0; i < feature_events.len; i++)
{
feature_event_t *event = &feature_events[i];
if (event->index != last_index)
{
/* Save a snapshot of active features and the range. */
range_record_t *range = range_records.push ();
! if (active_features.len)
{
CFMutableArrayRef features_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
/* TODO sort and resolve conflicting features? */
/* active_features.qsort (); */
! for (unsigned int j = 0; j < active_features.len; j++)
{
CFStringRef keys[] = {
kCTFontFeatureTypeIdentifierKey,
kCTFontFeatureSelectorIdentifierKey
};
--- 523,550 ----
event->start = false;
event->feature = feature;
}
/* Scan events and save features for each range. */
! hb_vector_t<active_feature_t> active_features;
unsigned int last_index = 0;
! for (unsigned int i = 0; i < feature_events.length; i++)
{
feature_event_t *event = &feature_events[i];
if (event->index != last_index)
{
/* Save a snapshot of active features and the range. */
range_record_t *range = range_records.push ();
! if (active_features.length)
{
CFMutableArrayRef features_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
/* TODO sort and resolve conflicting features? */
/* active_features.qsort (); */
! for (unsigned int j = 0; j < active_features.length; j++)
{
CFStringRef keys[] = {
kCTFontFeatureTypeIdentifierKey,
kCTFontFeatureSelectorIdentifierKey
};
*** 765,775 ****
{
active_features.push (event->feature);
} else {
active_feature_t *feature = active_features.find (&event->feature);
if (feature)
! active_features.remove (feature - active_features.arrayZ);
}
}
}
unsigned int scratch_size;
--- 596,606 ----
{
active_features.push (event->feature);
} else {
active_feature_t *feature = active_features.find (&event->feature);
if (feature)
! active_features.remove (feature - active_features.arrayZ ());
}
}
}
unsigned int scratch_size;
*** 822,832 ****
bool ret = true;
CFStringRef string_ref = nullptr;
CTLineRef line = nullptr;
! if (0)
{
resize_and_retry:
DEBUG_MSG (CORETEXT, buffer, "Buffer resize");
/* string_ref uses the scratch-buffer for backing store, and line references
* string_ref (via attr_string). We must release those before resizing buffer. */
--- 653,663 ----
bool ret = true;
CFStringRef string_ref = nullptr;
CTLineRef line = nullptr;
! if (false)
{
resize_and_retry:
DEBUG_MSG (CORETEXT, buffer, "Buffer resize");
/* string_ref uses the scratch-buffer for backing store, and line references
* string_ref (via attr_string). We must release those before resizing buffer. */
*** 897,907 ****
CFRelease (lang);
}
CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
kCTFontAttributeName, ct_font);
! if (num_features && range_records.len)
{
unsigned int start = 0;
range_record_t *last_range = &range_records[0];
for (unsigned int k = 0; k < chars_len; k++)
{
--- 728,738 ----
CFRelease (lang);
}
CFAttributedStringSetAttribute (attr_string, CFRangeMake (0, chars_len),
kCTFontAttributeName, ct_font);
! if (num_features && range_records.length)
{
unsigned int start = 0;
range_record_t *last_range = &range_records[0];
for (unsigned int k = 0; k < chars_len; k++)
{
*** 1046,1056 ****
* See: https://github.com/harfbuzz/harfbuzz/pull/36
*
* Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098
*/
bool matched = false;
! for (unsigned int i = 0; i < range_records.len; i++)
if (range_records[i].font && CFEqual (run_ct_font, range_records[i].font))
{
matched = true;
break;
}
--- 877,887 ----
* See: https://github.com/harfbuzz/harfbuzz/pull/36
*
* Also see: https://bugs.chromium.org/p/chromium/issues/detail?id=597098
*/
bool matched = false;
! for (unsigned int i = 0; i < range_records.length; i++)
if (range_records[i].font && CFEqual (run_ct_font, range_records[i].font))
{
matched = true;
break;
}
*** 1233,1243 ****
* directions. As such, disable the assert... It wouldn't crash, but
* cursoring will be off...
*
* https://crbug.com/419769
*/
! if (0)
{
/* Make sure all runs had the expected direction. */
bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
assert (bool (status_and & kCTRunStatusRightToLeft) == backward);
assert (bool (status_or & kCTRunStatusRightToLeft) == backward);
--- 1064,1074 ----
* directions. As such, disable the assert... It wouldn't crash, but
* cursoring will be off...
*
* https://crbug.com/419769
*/
! if (false)
{
/* Make sure all runs had the expected direction. */
bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
assert (bool (status_and & kCTRunStatusRightToLeft) == backward);
assert (bool (status_or & kCTRunStatusRightToLeft) == backward);
*** 1309,1319 ****
if (string_ref)
CFRelease (string_ref);
if (line)
CFRelease (line);
! for (unsigned int i = 0; i < range_records.len; i++)
if (range_records[i].font)
CFRelease (range_records[i].font);
return ret;
}
--- 1140,1150 ----
if (string_ref)
CFRelease (string_ref);
if (line)
CFRelease (line);
! for (unsigned int i = 0; i < range_records.length; i++)
if (range_records[i].font)
CFRelease (range_records[i].font);
return ret;
}
*** 1321,1400 ****
/*
* AAT shaper
*/
- HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, face)
- HB_SHAPER_DATA_ENSURE_DEFINE(coretext_aat, font)
-
/*
* shaper face data
*/
! struct hb_coretext_aat_shaper_face_data_t {};
! hb_coretext_aat_shaper_face_data_t *
_hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
{
! static const hb_tag_t tags[] = {HB_CORETEXT_TAG_MORX, HB_CORETEXT_TAG_MORT, HB_CORETEXT_TAG_KERX};
!
! for (unsigned int i = 0; i < ARRAY_LENGTH (tags); i++)
! {
! hb_blob_t *blob = face->reference_table (tags[i]);
! if (hb_blob_get_length (blob))
! {
! hb_blob_destroy (blob);
! return hb_coretext_shaper_face_data_ensure (face) ? (hb_coretext_aat_shaper_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
! }
! hb_blob_destroy (blob);
! }
!
! return nullptr;
}
void
! _hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_shaper_face_data_t *data HB_UNUSED)
{
}
/*
* shaper font data
*/
! struct hb_coretext_aat_shaper_font_data_t {};
! hb_coretext_aat_shaper_font_data_t *
_hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
{
! return hb_coretext_shaper_font_data_ensure (font) ? (hb_coretext_aat_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
! }
!
! void
! _hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_shaper_font_data_t *data HB_UNUSED)
! {
! }
!
!
! /*
! * shaper shape_plan data
! */
!
! struct hb_coretext_aat_shaper_shape_plan_data_t {};
!
! hb_coretext_aat_shaper_shape_plan_data_t *
! _hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED,
! const hb_feature_t *user_features HB_UNUSED,
! unsigned int num_user_features HB_UNUSED,
! const int *coords HB_UNUSED,
! unsigned int num_coords HB_UNUSED)
! {
! return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
! _hb_coretext_aat_shaper_shape_plan_data_destroy (hb_coretext_aat_shaper_shape_plan_data_t *data HB_UNUSED)
{
}
/*
--- 1152,1194 ----
/*
* AAT shaper
*/
/*
* shaper face data
*/
! struct hb_coretext_aat_face_data_t {};
! hb_coretext_aat_face_data_t *
_hb_coretext_aat_shaper_face_data_create (hb_face_t *face)
{
! return hb_aat_layout_has_substitution (face) || hb_aat_layout_has_positioning (face) ?
! (hb_coretext_aat_face_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
}
void
! _hb_coretext_aat_shaper_face_data_destroy (hb_coretext_aat_face_data_t *data HB_UNUSED)
{
}
/*
* shaper font data
*/
! struct hb_coretext_aat_font_data_t {};
! hb_coretext_aat_font_data_t *
_hb_coretext_aat_shaper_font_data_create (hb_font_t *font)
{
! return font->data.coretext ? (hb_coretext_aat_font_data_t *) HB_SHAPER_DATA_SUCCEEDED : nullptr;
}
void
! _hb_coretext_aat_shaper_font_data_destroy (hb_coretext_aat_font_data_t *data HB_UNUSED)
{
}
/*
< prev index next >