Ejemplo n.º 1
0
namespace HBFeature
{
	const hb_tag_t KernTag = HB_TAG('k', 'e', 'r', 'n'); // kerning operations
	const hb_tag_t LigaTag = HB_TAG('l', 'i', 'g', 'a'); // standard ligature substitution
	const hb_tag_t CligTag = HB_TAG('c', 'l', 'i', 'g'); // contextual ligature substitution

	static hb_feature_t LigatureOn = { LigaTag, 1, 0, std::numeric_limits<unsigned int>::max() };
	static hb_feature_t KerningOn = { KernTag, 1, 0, std::numeric_limits<unsigned int>::max() };
	static hb_feature_t CligOn = { CligTag, 1, 0, std::numeric_limits<unsigned int>::max() };
}
Ejemplo n.º 2
0
/**
 * \brief set up the HarfBuzz OpenType feature list with some
 * standard features.
 */
static void init_features(ASS_Shaper *shaper)
{
    shaper->features = calloc(sizeof(hb_feature_t), NUM_FEATURES);

    shaper->n_features = NUM_FEATURES;
    shaper->features[VERT].tag = HB_TAG('v', 'e', 'r', 't');
    shaper->features[VERT].end = INT_MAX;
    shaper->features[VKNA].tag = HB_TAG('v', 'k', 'n', 'a');
    shaper->features[VKNA].end = INT_MAX;
    shaper->features[KERN].tag = HB_TAG('k', 'e', 'r', 'n');
    shaper->features[KERN].end = INT_MAX;
}
Ejemplo n.º 3
0
void HarfBuzzShaper::setFontFeatures()
{
    const FontDescription& description = m_font->fontDescription();
    if (description.orientation() == Vertical) {
        static hb_feature_t vert = { HarfBuzzFace::vertTag, 1, 0, static_cast<unsigned>(-1) };
        static hb_feature_t vrt2 = { HarfBuzzFace::vrt2Tag, 1, 0, static_cast<unsigned>(-1) };
        m_features.append(vert);
        m_features.append(vrt2);
    }

    FontFeatureSettings* settings = description.featureSettings();
    if (!settings)
        return;

    unsigned numFeatures = settings->size();
    for (unsigned i = 0; i < numFeatures; ++i) {
        hb_feature_t feature;
        const UChar* tag = settings->at(i).tag().characters();
        feature.tag = HB_TAG(tag[0], tag[1], tag[2], tag[3]);
        feature.value = settings->at(i).value();
        feature.start = 0;
        feature.end = static_cast<unsigned>(-1);
        m_features.append(feature);
    }
}
static void
override_features_hangul (hb_ot_shape_planner_t *plan)
{
  /* Uniscribe does not apply 'calt' for Hangul, and certain fonts
   * (Noto Sans CJK, Source Sans Han, etc) apply all of jamo lookups
   * in calt, which is not desirable. */
  plan->map.add_feature (HB_TAG('c','a','l','t'), 0, F_GLOBAL);
}
Ejemplo n.º 5
0
static inline hb_feature_t createFeature(uint8_t c1,
                                         uint8_t c2,
                                         uint8_t c3,
                                         uint8_t c4,
                                         uint32_t value = 0) {
  return {HB_TAG(c1, c2, c3, c4), value, 0 /* start */,
          static_cast<unsigned>(-1) /* end */};
}
Ejemplo n.º 6
0
void CapsFeatureSettingsScopedOverlay::overlayCapsFeatures(
    FontDescription::FontVariantCaps variantCaps) {
    static hb_feature_t smcp = createFeature(HB_TAG('s', 'm', 'c', 'p'), 1);
    static hb_feature_t pcap = createFeature(HB_TAG('p', 'c', 'a', 'p'), 1);
    static hb_feature_t c2sc = createFeature(HB_TAG('c', '2', 's', 'c'), 1);
    static hb_feature_t c2pc = createFeature(HB_TAG('c', '2', 'p', 'c'), 1);
    static hb_feature_t unic = createFeature(HB_TAG('u', 'n', 'i', 'c'), 1);
    static hb_feature_t titl = createFeature(HB_TAG('t', 'i', 't', 'l'), 1);
    if (variantCaps == FontDescription::SmallCaps ||
            variantCaps == FontDescription::AllSmallCaps) {
        prependCounting(smcp);
        if (variantCaps == FontDescription::AllSmallCaps) {
            prependCounting(c2sc);
        }
    }
    if (variantCaps == FontDescription::PetiteCaps ||
            variantCaps == FontDescription::AllPetiteCaps) {
        prependCounting(pcap);
        if (variantCaps == FontDescription::AllPetiteCaps) {
            prependCounting(c2pc);
        }
    }
    if (variantCaps == FontDescription::Unicase) {
        prependCounting(unic);
    }
    if (variantCaps == FontDescription::TitlingCaps) {
        prependCounting(titl);
    }
}
static void
collect_features_arabic (hb_ot_shape_planner_t *plan)
{
  hb_ot_map_builder_t *map = &plan->map;

  /* We apply features according to the Arabic spec, with pauses
   * in between most.
   *
   * The pause between init/medi/... and rlig is required.  See eg:
   * https://bugzilla.mozilla.org/show_bug.cgi?id=644184
   *
   * The pauses between init/medi/... themselves are not necessarily
   * needed as only one of those features is applied to any character.
   * The only difference it makes is when fonts have contextual
   * substitutions.  We now follow the order of the spec, which makes
   * for better experience if that's what Uniscribe is doing.
   *
   * At least for Arabic, looks like Uniscribe has a pause between
   * rlig and calt.  Otherwise the IranNastaliq's ALLAH ligature won't
   * work.  However, testing shows that rlig and calt are applied
   * together for Mongolian in Uniscribe.  As such, we only add a
   * pause for Arabic, not other scripts.
   */

  map->add_gsub_pause (nuke_joiners);

  map->add_global_bool_feature (HB_TAG('s','t','c','h'));
  map->add_gsub_pause (record_stch);

  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
  map->add_global_bool_feature (HB_TAG('l','o','c','l'));

  map->add_gsub_pause (NULL);

  for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++)
  {
    bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]);
    map->add_feature (arabic_features[i], 1, has_fallback ? F_HAS_FALLBACK : F_NONE);
    map->add_gsub_pause (NULL);
  }

  map->add_feature (HB_TAG('r','l','i','g'), 1, F_GLOBAL|F_HAS_FALLBACK);
  if (plan->props.script == HB_SCRIPT_ARABIC)
    map->add_gsub_pause (arabic_fallback_shape);

  map->add_global_bool_feature (HB_TAG('c','a','l','t'));

  /* The spec includes 'cswh'.  Earlier versions of Windows
   * used to enable this by default, but testing suggests
   * that Windows 8 and later do not enable it by default,
   * and spec now says 'Off by default'.
   * We disabled this in ae23c24c32.
   * Note that IranNastaliq uses this feature extensively
   * to fixup broken glyph sequences.  Oh well...
   * Test case: U+0643,U+0640,U+0631. */
  //map->add_gsub_pause (NULL);
  //map->add_global_bool_feature (HB_TAG('c','s','w','h'));
  map->add_global_bool_feature (HB_TAG('m','s','e','t'));
}
Ejemplo n.º 8
0
void HarfBuzzShaper::setFontFeatures()
{
    FontFeatureSettings* settings = m_font->fontDescription().featureSettings();
    if (!settings)
        return;

    unsigned numFeatures = settings->size();
    m_features.resize(numFeatures);
    for (unsigned i = 0; i < numFeatures; ++i) {
        const UChar* tag = settings->at(i).tag().characters();
        m_features[i].tag = HB_TAG(tag[0], tag[1], tag[2], tag[3]);
        m_features[i].value = settings->at(i).value();
        m_features[i].start = 0;
        m_features[i].end = static_cast<unsigned>(-1);
    }
}
void *
data_create_arabic (const hb_ot_shape_plan_t *plan)
{
  arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) calloc (1, sizeof (arabic_shape_plan_t));
  if (unlikely (!arabic_plan))
    return NULL;

  arabic_plan->do_fallback = plan->props.script == HB_SCRIPT_ARABIC;
  arabic_plan->has_stch = !!plan->map.get_1_mask (HB_TAG ('s','t','c','h'));
  for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) {
    arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]);
    arabic_plan->do_fallback = arabic_plan->do_fallback &&
                               (FEATURE_IS_SYRIAC (arabic_features[i]) ||
                                plan->map.needs_fallback (arabic_features[i]));
  }

  return arabic_plan;
}
Ejemplo n.º 10
0
static void
test_subset_cff1_seac (void)
{
  hb_face_t *face = hb_test_open_font_file ("fonts/cff1_seac.otf");
  hb_face_t *face_subset = hb_test_open_font_file ("fonts/cff1_seac.C0.otf");
  hb_face_t *face_test;

  hb_set_t *codepoints = hb_set_create ();
  hb_set_add (codepoints, 0xC0);  /* Agrave */
  face_test = hb_subset_test_create_subset (face, hb_subset_test_create_input (codepoints));
  hb_set_destroy (codepoints);

  hb_subset_test_check (face_subset, face_test, HB_TAG ('C','F','F',' '));

  hb_face_destroy (face_test);
  hb_face_destroy (face_subset);
  hb_face_destroy (face);
}
Ejemplo n.º 11
0
static void
test_subset_cff1_noop (void)
{
  hb_face_t *face_abc = hb_test_open_font_file("fonts/SourceSansPro-Regular.abc.otf");

  hb_set_t *codepoints = hb_set_create ();
  hb_face_t *face_abc_subset;
  hb_set_add (codepoints, 'a');
  hb_set_add (codepoints, 'b');
  hb_set_add (codepoints, 'c');
  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
  hb_set_destroy (codepoints);

  hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('C','F','F',' '));

  hb_face_destroy (face_abc_subset);
  hb_face_destroy (face_abc);
}
Ejemplo n.º 12
0
static void
test_subset_hdmx_multiple_device_records (void)
{
  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.multihdmx.abc.ttf");
  hb_face_t *face_a = hb_test_open_font_file ("fonts/Roboto-Regular.multihdmx.a.ttf");

  hb_set_t *codepoints = hb_set_create ();
  hb_face_t *face_abc_subset;
  hb_set_add (codepoints, 'a');
  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
  hb_set_destroy (codepoints);

  hb_subset_test_check (face_a, face_abc_subset, HB_TAG ('h','d','m','x'));

  hb_face_destroy (face_abc_subset);
  hb_face_destroy (face_abc);
  hb_face_destroy (face_a);
}
Ejemplo n.º 13
0
/**
 * hb_ot_layout_get_size_params:
 *
 * Since: 0.9.10
 **/
hb_bool_t
hb_ot_layout_get_size_params (hb_face_t    *face,
                              unsigned int *design_size,       /* OUT.  May be NULL */
                              unsigned int *subfamily_id,      /* OUT.  May be NULL */
                              unsigned int *subfamily_name_id, /* OUT.  May be NULL */
                              unsigned int *range_start,       /* OUT.  May be NULL */
                              unsigned int *range_end          /* OUT.  May be NULL */)
{
  const OT::GPOS &gpos = _get_gpos (face);
  const hb_tag_t tag = HB_TAG ('s','i','z','e');

  unsigned int num_features = gpos.get_feature_count ();
  for (unsigned int i = 0; i < num_features; i++)
  {
    if (tag == gpos.get_feature_tag (i))
    {
      const OT::Feature &f = gpos.get_feature (i);
      const OT::FeatureParamsSize &params = f.get_feature_params ().get_size_params (tag);

      if (params.designSize)
      {
#define PARAM(a, A) if (a) *a = params.A
        PARAM (design_size, designSize);
        PARAM (subfamily_id, subfamilyID);
        PARAM (subfamily_name_id, subfamilyNameID);
        PARAM (range_start, rangeStart);
        PARAM (range_end, rangeEnd);
#undef PARAM

        return true;
      }
    }
  }

#define PARAM(a, A) if (a) *a = 0
  PARAM (design_size, designSize);
  PARAM (subfamily_id, subfamilyID);
  PARAM (subfamily_name_id, subfamilyNameID);
  PARAM (range_start, rangeStart);
  PARAM (range_end, rangeEnd);
#undef PARAM

  return false;
}
Ejemplo n.º 14
0
static void
test_subset_hdmx_simple_subset (void)
{
  hb_face_t *face_abc = hb_test_open_font_file ("fonts/Roboto-Regular.abc.ttf");
  hb_face_t *face_ac = hb_test_open_font_file ("fonts/Roboto-Regular.ac.ttf");

  hb_set_t *codepoints = hb_set_create ();
  hb_face_t *face_abc_subset;
  hb_set_add (codepoints, 'a');
  hb_set_add (codepoints, 'c');
  face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
  hb_set_destroy (codepoints);

  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('h','d','m','x'));

  hb_face_destroy (face_abc_subset);
  hb_face_destroy (face_abc);
  hb_face_destroy (face_ac);
}
Ejemplo n.º 15
0
static void
test_post_drops_glyph_names (void)
{
  hb_face_t *face_full = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E,6975,73E0,5EA6,8F38,6E05.ttf");
  hb_face_t *face_subset = hb_subset_test_open_font ("fonts/Mplus1p-Regular.660E.ttf");
  hb_face_t *face_full_subset;

  hb_set_t *codepoints = hb_set_create ();
  hb_set_add (codepoints, 0x660E);

  face_full_subset = hb_subset_test_create_subset (face_full, hb_subset_test_create_input (codepoints));
  hb_set_destroy (codepoints);

  hb_subset_test_check (face_subset, face_full_subset, HB_TAG ('p','o','s','t'));

  hb_face_destroy (face_full_subset);
  hb_face_destroy (face_full);
  hb_face_destroy (face_subset);
}
Ejemplo n.º 16
0
static void
test_subset_cff1_j (void)
{
  hb_face_t *face_41_3041_4c2e = hb_test_open_font_file ("fonts/SourceHanSans-Regular.41,3041,4C2E.otf");
  hb_face_t *face_41_4c2e = hb_test_open_font_file ("fonts/SourceHanSans-Regular.41,4C2E.otf");

  hb_set_t *codepoints = hb_set_create ();
  hb_face_t *face_41_3041_4c2e_subset;
  hb_set_add (codepoints, 0x41);
  hb_set_add (codepoints, 0x4C2E);
  face_41_3041_4c2e_subset = hb_subset_test_create_subset (face_41_3041_4c2e, hb_subset_test_create_input (codepoints));
  hb_set_destroy (codepoints);

  hb_subset_test_check (face_41_4c2e, face_41_3041_4c2e_subset, HB_TAG ('C','F','F',' '));

  hb_face_destroy (face_41_3041_4c2e_subset);
  hb_face_destroy (face_41_3041_4c2e);
  hb_face_destroy (face_41_4c2e);
}
Ejemplo n.º 17
0
static void
test_subset_cff1_expert (void)
{
  hb_face_t *face = hb_test_open_font_file ("fonts/cff1_expert.otf");
  hb_face_t *face_subset = hb_test_open_font_file ("fonts/cff1_expert.2D,F6E9,FB00.otf");

  hb_set_t *codepoints = hb_set_create ();
  hb_face_t *face_test;
  hb_set_add (codepoints, 0x2D);
  hb_set_add (codepoints, 0xF6E9);
  hb_set_add (codepoints, 0xFB00);
  face_test = hb_subset_test_create_subset (face, hb_subset_test_create_input (codepoints));
  hb_set_destroy (codepoints);

  hb_subset_test_check (face_subset, face_test, HB_TAG ('C','F','F',' '));

  hb_face_destroy (face_test);
  hb_face_destroy (face_subset);
  hb_face_destroy (face);
}
Ejemplo n.º 18
0
void HarfBuzzShaper::setFontFeatures()
{
    const FontDescription& description = m_font->fontDescription();
    if (description.orientation() == Vertical) {
        static hb_feature_t vert = { HarfBuzzFace::vertTag, 1, 0, static_cast<unsigned>(-1) };
        static hb_feature_t vrt2 = { HarfBuzzFace::vrt2Tag, 1, 0, static_cast<unsigned>(-1) };
        m_features.append(vert);
        m_features.append(vrt2);
    }

    hb_feature_t kerning = { HarfBuzzFace::kernTag, 0, 0, static_cast<unsigned>(-1) };
    switch (description.kerning()) {
    case FontDescription::NormalKerning:
        kerning.value = 1;
        m_features.append(kerning);
        break;
    case FontDescription::NoneKerning:
        kerning.value = 0;
        m_features.append(kerning);
        break;
    case FontDescription::AutoKerning:
        break;
    default:
        ASSERT_NOT_REACHED();
    }

    FontFeatureSettings* settings = description.featureSettings();
    if (!settings)
        return;

    unsigned numFeatures = settings->size();
    for (unsigned i = 0; i < numFeatures; ++i) {
        hb_feature_t feature;
        auto& tag = settings->at(i).tag();
        feature.tag = HB_TAG(tag[0], tag[1], tag[2], tag[3]);
        feature.value = settings->at(i).value();
        feature.start = 0;
        feature.end = static_cast<unsigned>(-1);
        m_features.append(feature);
    }
}
Ejemplo n.º 19
0
static void
test_subset_cff1_dotsection (void)
{
  hb_face_t *face = hb_test_open_font_file ("fonts/cff1_dotsect.otf");
  hb_face_t *face_subset = hb_test_open_font_file ("fonts/cff1_dotsect.nohints.otf");

  hb_set_t *codepoints = hb_set_create ();
  hb_subset_input_t *input;
  hb_face_t *face_test;
  hb_set_add (codepoints, 0x69);  /* i */
  input = hb_subset_test_create_input (codepoints);
  hb_subset_input_set_drop_hints (input, true);
  face_test = hb_subset_test_create_subset (face, input);
  hb_set_destroy (codepoints);

  hb_subset_test_check (face_subset, face_test, HB_TAG ('C','F','F',' '));

  hb_face_destroy (face_test);
  hb_face_destroy (face_subset);
  hb_face_destroy (face);
}
Ejemplo n.º 20
0
static void *
data_create_use (const hb_ot_shape_plan_t *plan)
{
  use_shape_plan_t *use_plan = (use_shape_plan_t *) calloc (1, sizeof (use_shape_plan_t));
  if (unlikely (!use_plan))
    return NULL;

  use_plan->rphf_mask = plan->map.get_1_mask (HB_TAG('r','p','h','f'));

  if (has_arabic_joining (plan->props.script))
  {
    use_plan->arabic_plan = (arabic_shape_plan_t *) data_create_arabic (plan);
    if (unlikely (!use_plan->arabic_plan))
    {
      free (use_plan);
      return NULL;
    }
  }

  return use_plan;
}
Ejemplo n.º 21
0
static void
test_subset_cff1_desubr (void)
{
  hb_face_t *face_abc = hb_test_open_font_file ("fonts/SourceSansPro-Regular.abc.otf");
  hb_face_t *face_ac = hb_test_open_font_file ("fonts/SourceSansPro-Regular.ac.nosubrs.otf");

  hb_set_t *codepoints = hb_set_create ();
  hb_subset_input_t *input;
  hb_face_t *face_abc_subset;
  hb_set_add (codepoints, 'a');
  hb_set_add (codepoints, 'c');
  input = hb_subset_test_create_input (codepoints);
  hb_subset_input_set_desubroutinize (input, true);
  face_abc_subset = hb_subset_test_create_subset (face_abc, input);
  hb_set_destroy (codepoints);

  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('C','F','F',' '));

  hb_face_destroy (face_abc_subset);
  hb_face_destroy (face_abc);
  hb_face_destroy (face_ac);
}
Ejemplo n.º 22
0
static void
test_subset_cff1_j_desubr_strip_hints (void)
{
  hb_face_t *face_41_3041_4c2e = hb_test_open_font_file ("fonts/SourceHanSans-Regular.41,3041,4C2E.otf");
  hb_face_t *face_41_4c2e = hb_test_open_font_file ("fonts/SourceHanSans-Regular.41,4C2E.nosubrs.nohints.otf");

  hb_set_t *codepoints = hb_set_create ();
  hb_face_t *face_41_3041_4c2e_subset;
  hb_subset_input_t *input;
  hb_set_add (codepoints, 0x41);
  hb_set_add (codepoints, 0x4C2E);
  input = hb_subset_test_create_input (codepoints);
  hb_subset_input_set_drop_hints (input, true);
  hb_subset_input_set_desubroutinize (input, true);
  face_41_3041_4c2e_subset = hb_subset_test_create_subset (face_41_3041_4c2e, input);
  hb_set_destroy (codepoints);

  hb_subset_test_check (face_41_4c2e, face_41_3041_4c2e_subset, HB_TAG ('C','F','F',' '));

  hb_face_destroy (face_41_3041_4c2e_subset);
  hb_face_destroy (face_41_3041_4c2e);
  hb_face_destroy (face_41_4c2e);
}
Ejemplo n.º 23
0
static void
collect_features_use (hb_ot_shape_planner_t *plan)
{
  hb_ot_map_builder_t *map = &plan->map;

  /* Do this before any lookups have been applied. */
  map->add_gsub_pause (setup_syllables);

  /* "Default glyph pre-processing group" */
  map->add_global_bool_feature (HB_TAG('l','o','c','l'));
  map->add_global_bool_feature (HB_TAG('c','c','m','p'));
  map->add_global_bool_feature (HB_TAG('n','u','k','t'));
  map->add_global_bool_feature (HB_TAG('a','k','h','n'));

  /* "Reordering group" */
  map->add_gsub_pause (clear_substitution_flags);
  map->add_feature (HB_TAG('r','p','h','f'), 1, F_MANUAL_ZWJ);
  map->add_gsub_pause (record_rphf);
  map->add_gsub_pause (clear_substitution_flags);
  map->add_feature (HB_TAG('p','r','e','f'), 1, F_GLOBAL | F_MANUAL_ZWJ);
  map->add_gsub_pause (record_pref);

  /* "Orthographic unit shaping group" */
  for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
    map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);

  map->add_gsub_pause (reorder);

  /* "Topographical features" */
  for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++)
    map->add_feature (arabic_features[i], 1, F_NONE);
  map->add_gsub_pause (NULL);

  /* "Standard typographic presentation" and "Positional feature application" */
  for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
    map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
}
void HarfBuzzShaper::setFontFeatures()
{
    const FontDescription& description = m_font->getFontDescription();

    static hb_feature_t noKern = createFeature('k', 'e', 'r', 'n');
    static hb_feature_t noVkrn = createFeature('v', 'k', 'r', 'n');
    switch (description.getKerning()) {
    case FontDescription::NormalKerning:
        // kern/vkrn are enabled by default
        break;
    case FontDescription::NoneKerning:
        m_features.append(description.isVerticalAnyUpright() ? noVkrn : noKern);
        break;
    case FontDescription::AutoKerning:
        break;
    }

    static hb_feature_t noClig = createFeature('c', 'l', 'i', 'g');
    static hb_feature_t noLiga = createFeature('l', 'i', 'g', 'a');
    switch (description.commonLigaturesState()) {
    case FontDescription::DisabledLigaturesState:
        m_features.append(noLiga);
        m_features.append(noClig);
        break;
    case FontDescription::EnabledLigaturesState:
        // liga and clig are on by default
        break;
    case FontDescription::NormalLigaturesState:
        break;
    }
    static hb_feature_t dlig = createFeature('d', 'l', 'i', 'g', 1);
    switch (description.discretionaryLigaturesState()) {
    case FontDescription::DisabledLigaturesState:
        // dlig is off by default
        break;
    case FontDescription::EnabledLigaturesState:
        m_features.append(dlig);
        break;
    case FontDescription::NormalLigaturesState:
        break;
    }
    static hb_feature_t hlig = createFeature('h', 'l', 'i', 'g', 1);
    switch (description.historicalLigaturesState()) {
    case FontDescription::DisabledLigaturesState:
        // hlig is off by default
        break;
    case FontDescription::EnabledLigaturesState:
        m_features.append(hlig);
        break;
    case FontDescription::NormalLigaturesState:
        break;
    }
    static hb_feature_t noCalt = createFeature('c', 'a', 'l', 't');
    switch (description.contextualLigaturesState()) {
    case FontDescription::DisabledLigaturesState:
        m_features.append(noCalt);
        break;
    case FontDescription::EnabledLigaturesState:
        // calt is on by default
        break;
    case FontDescription::NormalLigaturesState:
        break;
    }

    static hb_feature_t hwid = createFeature('h', 'w', 'i', 'd', 1);
    static hb_feature_t twid = createFeature('t', 'w', 'i', 'd', 1);
    static hb_feature_t qwid = createFeature('q', 'w', 'i', 'd', 1);
    switch (description.widthVariant()) {
    case HalfWidth:
        m_features.append(hwid);
        break;
    case ThirdWidth:
        m_features.append(twid);
        break;
    case QuarterWidth:
        m_features.append(qwid);
        break;
    case RegularWidth:
        break;
    }

    FontFeatureSettings* settings = description.featureSettings();
    if (!settings)
        return;

    unsigned numFeatures = settings->size();
    for (unsigned i = 0; i < numFeatures; ++i) {
        hb_feature_t feature;
        const AtomicString& tag = settings->at(i).tag();
        feature.tag = HB_TAG(tag[0], tag[1], tag[2], tag[3]);
        feature.value = settings->at(i).value();
        feature.start = 0;
        feature.end = static_cast<unsigned>(-1);
        m_features.append(feature);
    }
}
  unsigned int j_type = joining_type(u);
  if (likely (j_type != JOINING_TYPE_X))
    return j_type;

  return (FLAG_SAFE(gen_cat) &
          (FLAG(HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) |
           FLAG(HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
           FLAG(HB_UNICODE_GENERAL_CATEGORY_FORMAT))
         ) ?  JOINING_TYPE_T : JOINING_TYPE_U;
}

#define FEATURE_IS_SYRIAC(tag) hb_in_range<unsigned char> ((unsigned char) (tag), '2', '3')

static const hb_tag_t arabic_features[] =
{
  HB_TAG('i','s','o','l'),
  HB_TAG('f','i','n','a'),
  HB_TAG('f','i','n','2'),
  HB_TAG('f','i','n','3'),
  HB_TAG('m','e','d','i'),
  HB_TAG('m','e','d','2'),
  HB_TAG('i','n','i','t'),
  HB_TAG_NONE
};


/* Same order as the feature array */
enum arabic_action_t {
  ISOL,
  FINA,
  FIN2,
/* Same order as the feature array below */
enum {
  NONE,

  LJMO,
  VJMO,
  TJMO,

  FIRST_HANGUL_FEATURE = LJMO,
  HANGUL_FEATURE_COUNT = TJMO + 1
};

static const hb_tag_t hangul_features[HANGUL_FEATURE_COUNT] =
{
  HB_TAG_NONE,
  HB_TAG('l','j','m','o'),
  HB_TAG('v','j','m','o'),
  HB_TAG('t','j','m','o')
};

static void
collect_features_hangul (hb_ot_shape_planner_t *plan)
{
  hb_ot_map_builder_t *map = &plan->map;

  for (unsigned int i = FIRST_HANGUL_FEATURE; i < HANGUL_FEATURE_COUNT; i++)
    map->add_feature (hangul_features[i], 1, F_NONE);
}

static void
override_features_hangul (hb_ot_shape_planner_t *plan)
Ejemplo n.º 27
0
bool OpenTypeCapsSupport::supportsOpenTypeFeature(
    hb_script_t script,
    uint32_t tag) const
{
    hb_face_t* face = hb_font_get_face(m_harfBuzzFace->getScaledFont());
    ASSERT(face);

    ASSERT((tag == HB_TAG('s', 'm', 'c', 'p')
        || tag == HB_TAG('c', '2', 's', 'c')
        || tag == HB_TAG('p', 'c', 'a', 'p')
        || tag == HB_TAG('c', '2', 'p', 'c')
        || tag == HB_TAG('s', 'u', 'p', 's')
        || tag == HB_TAG('s', 'u', 'b', 's')
        || tag == HB_TAG('t', 'i', 't', 'l')
        || tag == HB_TAG('u', 'n', 'i', 'c')
        || tag == HB_TAG('v', 'e', 'r', 't')));

    bool result = false;

    if (!hb_ot_layout_has_substitution(face))
        return false;

    // Get the OpenType tag(s) that match this script code
    const size_t kMaxScriptTags = 4;
    hb_tag_t scriptTags[kMaxScriptTags] = {
        HB_TAG_NONE,
        HB_TAG_NONE,
        HB_TAG_NONE,
        HB_TAG_NONE
    };
    hb_ot_tags_from_script(static_cast<hb_script_t>(script),
        &scriptTags[0],
        &scriptTags[1]);

    // Replace the first remaining NONE with DEFAULT
    for (size_t i = 0; i < kMaxScriptTags; ++i) {
        if (scriptTags[i] == HB_TAG_NONE) {
            scriptTags[i] = HB_OT_TAG_DEFAULT_SCRIPT;
            break;
        }
    }

    // Now check for 'smcp' under the first of those scripts that is present
    const hb_tag_t kGSUB = HB_TAG('G', 'S', 'U', 'B');
    for (size_t j = 0; j < kMaxScriptTags; ++j) {
        if (scriptTags[j] == HB_TAG_NONE)
            break;

        unsigned scriptIndex;
        if (hb_ot_layout_table_find_script(face,
            kGSUB,
            scriptTags[j],
            &scriptIndex)) {
            if (hb_ot_layout_language_find_feature(face, kGSUB,
                scriptIndex,
                HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX,
                tag, nullptr)) {
                result = true;
            }
            break;
        }
    }
    return result;
}
Ejemplo n.º 28
0
void HarfBuzzShaper::setFontFeatures()
{
    const FontDescription& description = m_font->getFontDescription();

    static hb_feature_t noKern = createFeature('k', 'e', 'r', 'n');
    static hb_feature_t noVkrn = createFeature('v', 'k', 'r', 'n');
    switch (description.getKerning()) {
    case FontDescription::NormalKerning:
        // kern/vkrn are enabled by default
        break;
    case FontDescription::NoneKerning:
        m_features.append(description.isVerticalAnyUpright() ? noVkrn : noKern);
        break;
    case FontDescription::AutoKerning:
        break;
    }

    static hb_feature_t noClig = createFeature('c', 'l', 'i', 'g');
    static hb_feature_t noLiga = createFeature('l', 'i', 'g', 'a');
    switch (description.commonLigaturesState()) {
    case FontDescription::DisabledLigaturesState:
        m_features.append(noLiga);
        m_features.append(noClig);
        break;
    case FontDescription::EnabledLigaturesState:
        // liga and clig are on by default
        break;
    case FontDescription::NormalLigaturesState:
        break;
    }
    static hb_feature_t dlig = createFeature('d', 'l', 'i', 'g', 1);
    switch (description.discretionaryLigaturesState()) {
    case FontDescription::DisabledLigaturesState:
        // dlig is off by default
        break;
    case FontDescription::EnabledLigaturesState:
        m_features.append(dlig);
        break;
    case FontDescription::NormalLigaturesState:
        break;
    }
    static hb_feature_t hlig = createFeature('h', 'l', 'i', 'g', 1);
    switch (description.historicalLigaturesState()) {
    case FontDescription::DisabledLigaturesState:
        // hlig is off by default
        break;
    case FontDescription::EnabledLigaturesState:
        m_features.append(hlig);
        break;
    case FontDescription::NormalLigaturesState:
        break;
    }
    static hb_feature_t noCalt = createFeature('c', 'a', 'l', 't');
    switch (description.contextualLigaturesState()) {
    case FontDescription::DisabledLigaturesState:
        m_features.append(noCalt);
        break;
    case FontDescription::EnabledLigaturesState:
        // calt is on by default
        break;
    case FontDescription::NormalLigaturesState:
        break;
    }

    static hb_feature_t hwid = createFeature('h', 'w', 'i', 'd', 1);
    static hb_feature_t twid = createFeature('t', 'w', 'i', 'd', 1);
    static hb_feature_t qwid = createFeature('q', 'w', 'i', 'd', 1);
    switch (description.widthVariant()) {
    case HalfWidth:
        m_features.append(hwid);
        break;
    case ThirdWidth:
        m_features.append(twid);
        break;
    case QuarterWidth:
        m_features.append(qwid);
        break;
    case RegularWidth:
        break;
    }

    // font-variant-numeric:
    static hb_feature_t lnum = createFeature('l', 'n', 'u', 'm', 1);
    if (description.variantNumeric().numericFigureValue() == FontVariantNumeric::LiningNums)
        m_features.append(lnum);

    static hb_feature_t onum = createFeature('o', 'n', 'u', 'm', 1);
    if (description.variantNumeric().numericFigureValue() == FontVariantNumeric::OldstyleNums)
        m_features.append(onum);

    static hb_feature_t pnum = createFeature('p', 'n', 'u', 'm', 1);
    if (description.variantNumeric().numericSpacingValue() == FontVariantNumeric::ProportionalNums)
        m_features.append(pnum);
    static hb_feature_t tnum = createFeature('t', 'n', 'u', 'm', 1);
    if (description.variantNumeric().numericSpacingValue() == FontVariantNumeric::TabularNums)
        m_features.append(tnum);

    static hb_feature_t afrc = createFeature('a', 'f', 'r', 'c', 1);
    if (description.variantNumeric().numericFractionValue() == FontVariantNumeric::StackedFractions)
        m_features.append(afrc);
    static hb_feature_t frac = createFeature('f', 'r', 'a', 'c', 1);
    if (description.variantNumeric().numericFractionValue() == FontVariantNumeric::DiagonalFractions)
        m_features.append(frac);

    static hb_feature_t ordn = createFeature('o', 'r', 'd', 'n', 1);
    if (description.variantNumeric().ordinalValue() == FontVariantNumeric::OrdinalOn)
        m_features.append(ordn);

    static hb_feature_t zero = createFeature('z', 'e', 'r', 'o', 1);
    if (description.variantNumeric().slashedZeroValue() == FontVariantNumeric::SlashedZeroOn)
        m_features.append(zero);


    FontFeatureSettings* settings = description.featureSettings();
    if (!settings)
        return;

    // TODO(drott): crbug.com/450619 Implement feature resolution instead of
    // just appending the font-feature-settings.
    unsigned numFeatures = settings->size();
    for (unsigned i = 0; i < numFeatures; ++i) {
        hb_feature_t feature;
        const AtomicString& tag = settings->at(i).tag();
        feature.tag = HB_TAG(tag[0], tag[1], tag[2], tag[3]);
        feature.value = settings->at(i).value();
        feature.start = 0;
        feature.end = static_cast<unsigned>(-1);
        m_features.append(feature);
    }
}
Ejemplo n.º 29
0
#define use_category() complex_var_u8_0()


/*
 * Universal Shaping Engine.
 * https://www.microsoft.com/typography/OpenTypeDev/USE/intro.htm
 */

static const hb_tag_t
basic_features[] =
{
  /*
   * Basic features.
   * These features are applied all at once, before reordering.
   */
  HB_TAG('r','k','r','f'),
  HB_TAG('a','b','v','f'),
  HB_TAG('b','l','w','f'),
  HB_TAG('h','a','l','f'),
  HB_TAG('p','s','t','f'),
  HB_TAG('v','a','t','u'),
  HB_TAG('c','j','c','t'),
};
static const hb_tag_t
arabic_features[] =
{
  HB_TAG('i','s','o','l'),
  HB_TAG('i','n','i','t'),
  HB_TAG('m','e','d','i'),
  HB_TAG('f','i','n','a'),
  /* The spec doesn't specify these but we apply anyway, since our Arabic shaper