[HarfBuzz] harfbuzz: Branch 'master' - 6 commits
Behdad Esfahbod
behdad at kemper.freedesktop.org
Wed Dec 12 08:39:26 PST 2012
src/hb-open-type-private.hh | 33 ++++++---
src/hb-ot-layout-common-private.hh | 133 +++++++++++++++++++++++++++++++++++--
src/hb-ot-layout.cc | 107 ++++++++++++++++++++++++++---
src/hb-ot-layout.h | 8 +-
src/hb-private.hh | 4 +
src/test-size-params.cc | 13 +--
6 files changed, 259 insertions(+), 39 deletions(-)
New commits:
commit 85bc44b90a19c6a669ed567a9cd8513448600afe
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Wed Dec 12 11:38:49 2012 -0500
[OTLayout] More 'size' feature sanity checking
We still don't look for the old incorrect place of the featureParams.
I'll wait till someone actually complains about it...
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 61ba31a..f7a54bb 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -658,33 +658,92 @@ hb_ot_layout_get_size_params (hb_face_t *face,
const OT::Feature &f = gpos.get_feature (i);
const OT::FeatureParamsSize ¶ms = f.get_feature_params ().u.size;
-#define PARAM(a, A) if (a) *a = params.A
+ /* This subtable has some "history", if you will. Some earlier versions of
+ * Adobe tools calculated the offset of the FeatureParams sutable from the
+ * beginning of the FeatureList table! Now, we don't check for that possibility,
+ * but we want to at least detect junk data and reject it.
+ *
+ * Read Roberts wrote on 9/15/06 on opentype-list at indx.co.uk :
+ *
+ * Yes, it is correct that a new version of the AFDKO (version 2.0) will be
+ * coming out soon, and that the makeotf program will build a font with a
+ * 'size' feature that is correct by the specification.
+ *
+ * The specification for this feature tag is in the "OpenType Layout Tag
+ * Registry". You can see a copy of this at:
+ * http://partners.adobe.com/public/developer/opentype/index_tag8.html#size
+ *
+ * Here is one set of rules to determine if the 'size' feature is built
+ * correctly, or as by the older versions of MakeOTF. You may be able to do
+ * better.
+ *
+ * Assume that the offset to the size feature is according to specification,
+ * and make the following value checks. If it fails, assume the the size
+ * feature is calculated as versions of MakeOTF before the AFDKO 2.0 built it.
+ * If this fails, reject the 'size' feature. The older makeOTF's calculated the
+ * offset from the beginning of the FeatureList table, rather than from the
+ * beginning of the 'size' Feature table.
+ *
+ * If "design size" == 0:
+ * fails check
+ *
+ * Else if ("subfamily identifier" == 0 and
+ * "range start" == 0 and
+ * "range end" == 0 and
+ * "range start" == 0 and
+ * "menu name ID" == 0)
+ * passes check: this is the format used when there is a design size
+ * specified, but there is no recommended size range.
+ *
+ * Else if ("design size" < "range start" or
+ * "design size" > "range end" or
+ * "range end" <= "range start" or
+ * "menu name ID" < 256 or
+ * "menu name ID" > 32767 or
+ * menu name ID is not a name ID which is actually in the name table)
+ * fails test
+ * Else
+ * passes test.
+ */
+
if (!params.designSize)
- goto zero_all;
- PARAM (design_size, designSize);
- if (!params.subfamilyID)
- {
+ ret = false;
+ else if (params.subfamilyID == 0 &&
+ params.subfamilyNameID == 0 &&
+ params.rangeStart == 0 &&
+ params.rangeEnd == 0)
+ ret = true;
+ else if (params.designSize < params.rangeStart ||
+ params.designSize > params.rangeEnd ||
+ params.subfamilyNameID < 256 ||
+ params.subfamilyNameID > 32767)
+ ret = false;
+ else
ret = true;
- goto zero_most;
- };
- 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 = params.A
+ if (ret)
+ {
+ PARAM (design_size, designSize);
+ PARAM (subfamily_id, subfamilyID);
+ PARAM (subfamily_name_id, subfamilyNameID);
+ PARAM (range_start, rangeStart);
+ PARAM (range_end, rangeEnd);
+ break;
+ }
+#undef PARAM
}
}
#define PARAM(a, A) if (a) *a = 0
-zero_all:
- PARAM (design_size, designSize);
-zero_most:
- PARAM (subfamily_id, subfamilyID);
- PARAM (subfamily_name_id, subfamilyNameID);
- PARAM (range_start, rangeStart);
- PARAM (range_end, rangeEnd);
+ if (!ret)
+ {
+ PARAM (design_size, designSize);
+ PARAM (subfamily_id, subfamilyID);
+ PARAM (subfamily_name_id, subfamilyNameID);
+ PARAM (range_start, rangeStart);
+ PARAM (range_end, rangeEnd);
+ }
#undef PARAM
return ret;
commit 0bae50a36f3022f9bb6b2c001c191eeaaa4ef954
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Tue Dec 11 16:01:31 2012 -0500
[OTLayout] Add FeatureParamsCharacterVariants struct
No API yet.
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 4a8116e..da6c8f9 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -329,6 +329,48 @@ struct FeatureParamsStylisticSet
DEFINE_SIZE_STATIC (4);
};
+struct FeatureParamsCharacterVariants
+{
+ inline bool sanitize (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE (this);
+ return TRACE_RETURN (c->check_struct (this) &&
+ characters.sanitize (c));
+ }
+ /* TODO: This is made private since we don't have the facilities in
+ * FeatureParams to correctly sanitize this. */
+ private:
+ USHORT format; /* Format number is set to 0. */
+ USHORT featUILableNameID; /* The ânameâ table name ID that
+ * specifies a string (or strings,
+ * for multiple languages) for a
+ * user-interface label for this
+ * feature. (May be NULL.) */
+ USHORT featUITooltipTextNameID;/* The ânameâ table name ID that
+ * specifies a string (or strings,
+ * for multiple languages) that an
+ * application can use for tooltip
+ * text for this feature. (May be
+ * NULL.) */
+ USHORT sampleTextNameID; /* The ânameâ table name ID that
+ * specifies sample text that
+ * illustrates the effect of this
+ * feature. (May be NULL.) */
+ USHORT numNamedParameters; /* Number of named parameters. (May
+ * be zero.) */
+ USHORT firstParamUILabelNameID;/* The first ânameâ table name ID
+ * used to specify strings for
+ * user-interface labels for the
+ * feature parameters. (Must be zero
+ * if numParameters is zero.) */
+ ArrayOf<UINT24>
+ characters; /* Array of the Unicode Scalar Value
+ * of the characters for which this
+ * feature provides glyph variants.
+ * (May be zero.) */
+ public:
+ DEFINE_SIZE_ARRAY (14, characters);
+};
+
struct FeatureParams
{
/* Note:
@@ -339,6 +381,9 @@ struct FeatureParams
* subtable possible. This may nuke a possibly valid subtable if it's unfortunate
* enough to happen at the very end of the GSUB/GPOS table. But that's very
* unlikely (I hope!).
+ *
+ * When we fully implement FeatureParamsCharacterVariants, we should fix this
+ * shortcoming...
*/
inline bool sanitize (hb_sanitize_context_t *c) {
@@ -347,10 +392,11 @@ struct FeatureParams
}
union {
- FeatureParamsSize size;
- FeatureParamsStylisticSet stylisticSet;
+ FeatureParamsSize size;
+ FeatureParamsStylisticSet stylisticSet;
+ FeatureParamsCharacterVariants characterVariants;
} u;
- DEFINE_SIZE_STATIC (10);
+ DEFINE_SIZE_STATIC (17);
};
struct Feature
commit bd61bc13ea8ff350ada5449b2cfeb612e66ecafa
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Tue Dec 11 16:00:43 2012 -0500
[OTLayout] Add UINT24 type
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index e57558e..347e299 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -534,32 +534,43 @@ struct BEInt<Type, 4>
inline bool operator != (const BEInt<Type, 4>& o) const { return !(*this == o); }
private: uint8_t v[4];
};
+template <typename Type>
+struct BEInt<Type, 3>
+{
+ public:
+ inline void set (Type i) { hb_be_uint24_put (v,i); }
+ inline operator Type (void) const { return hb_be_uint24_get (v); }
+ inline bool operator == (const BEInt<Type, 3>& o) const { return hb_be_uint24_eq (v, o.v); }
+ inline bool operator != (const BEInt<Type, 3>& o) const { return !(*this == o); }
+ private: uint8_t v[3];
+};
/* Integer types in big-endian order and no alignment requirement */
-template <typename Type>
+template <typename Type, unsigned int Size>
struct IntType
{
inline void set (Type i) { v.set (i); }
inline operator Type(void) const { return v; }
- inline bool operator == (const IntType<Type> &o) const { return v == o.v; }
- inline bool operator != (const IntType<Type> &o) const { return v != o.v; }
- static inline int cmp (const IntType<Type> *a, const IntType<Type> *b) { return b->cmp (*a); }
- inline int cmp (IntType<Type> va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
+ inline bool operator == (const IntType<Type,Size> &o) const { return v == o.v; }
+ inline bool operator != (const IntType<Type,Size> &o) const { return v != o.v; }
+ static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *b) { return b->cmp (*a); }
+ inline int cmp (IntType<Type,Size> va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; }
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
return TRACE_RETURN (likely (c->check_struct (this)));
}
protected:
- BEInt<Type, sizeof (Type)> v;
+ BEInt<Type, Size> v;
public:
- DEFINE_SIZE_STATIC (sizeof (Type));
+ DEFINE_SIZE_STATIC (Size);
};
-typedef IntType<uint16_t> USHORT; /* 16-bit unsigned integer. */
-typedef IntType<int16_t> SHORT; /* 16-bit signed integer. */
-typedef IntType<uint32_t> ULONG; /* 32-bit unsigned integer. */
-typedef IntType<int32_t> LONG; /* 32-bit signed integer. */
+typedef IntType<uint16_t, 2> USHORT; /* 16-bit unsigned integer. */
+typedef IntType<int16_t, 2> SHORT; /* 16-bit signed integer. */
+typedef IntType<uint32_t, 4> ULONG; /* 32-bit unsigned integer. */
+typedef IntType<int32_t, 4> LONG; /* 32-bit signed integer. */
+typedef IntType<uint32_t, 3> UINT24; /* 24-bit unsigned integer. */
/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
typedef SHORT FWORD;
diff --git a/src/hb-private.hh b/src/hb-private.hh
index 3a62c67..be0d505 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -509,6 +509,10 @@ static inline uint32_t hb_uint32_swap (const uint32_t v)
#define hb_be_uint32_get(v) (uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3])
#define hb_be_uint32_eq(a,b) (a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3])
+#define hb_be_uint24_put(v,V) HB_STMT_START { v[0] = (V>>16); v[1] = (V>>8); v[2] (V); } HB_STMT_END
+#define hb_be_uint24_get(v) (uint32_t) ((v[0] << 16) + (v[1] << 8) + v[2])
+#define hb_be_uint24_eq(a,b) (a[0] == b[0] && a[1] == b[1] && a[2] == b[2])
+
/* ASCII tag/character handling */
commit 9cf7f9d4f61741932570afbefdee5edf61f79ae4
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Tue Dec 11 14:31:13 2012 -0500
Make test-size-params write size in points
diff --git a/src/test-size-params.cc b/src/test-size-params.cc
index 0caef97..947b566 100644
--- a/src/test-size-params.cc
+++ b/src/test-size-params.cc
@@ -84,20 +84,10 @@ main (int argc, char **argv)
hb_blob_destroy (blob);
blob = NULL;
- unsigned int params[5];
- if (!hb_ot_layout_get_size_params (face,
- params,
- params+1,
- params+2,
- params+3,
- params+4))
- return 1;
+ unsigned int p[5];
+ bool ret = hb_ot_layout_get_size_params (face, p, p+1, p+2, p+3, p+4);
- for (unsigned int i = 0; i < 5; i++) {
- if (i) printf (" ");
- printf ("%u", params[i]);
- }
- printf ("\n");
+ printf ("%g %u %u %g %g\n", p[0]/10., p[1], p[2], p[3]/10., p[4]/10.);
- return 0;
+ return !ret;
}
commit 372fe2b67b1757e809bf33e1e9055a00c5bed304
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Tue Dec 11 14:30:57 2012 -0500
[OTLayout] Make hb_ot_layout_get_size_params() do some checks
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index cf485bd..61ba31a 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -647,6 +647,7 @@ hb_ot_layout_get_size_params (hb_face_t *face,
unsigned int *range_start, /* OUT. May be NULL */
unsigned int *range_end /* OUT. May be NULL */)
{
+ bool ret = false;
const OT::GPOS &gpos = _get_gpos (face);
unsigned int num_features = gpos.get_feature_count ();
@@ -658,7 +659,14 @@ hb_ot_layout_get_size_params (hb_face_t *face,
const OT::FeatureParamsSize ¶ms = f.get_feature_params ().u.size;
#define PARAM(a, A) if (a) *a = params.A
+ if (!params.designSize)
+ goto zero_all;
PARAM (design_size, designSize);
+ if (!params.subfamilyID)
+ {
+ ret = true;
+ goto zero_most;
+ };
PARAM (subfamily_id, subfamilyID);
PARAM (subfamily_name_id, subfamilyNameID);
PARAM (range_start, rangeStart);
@@ -670,12 +678,14 @@ hb_ot_layout_get_size_params (hb_face_t *face,
}
#define PARAM(a, A) if (a) *a = 0
+zero_all:
PARAM (design_size, designSize);
+zero_most:
PARAM (subfamily_id, subfamilyID);
PARAM (subfamily_name_id, subfamilyNameID);
PARAM (range_start, rangeStart);
PARAM (range_end, rangeEnd);
#undef PARAM
- return false;
+ return ret;
}
commit 875a5cbc9c37f4264241c43b80afad2628eab749
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Tue Dec 11 14:17:01 2012 -0500
[OTLayout] Change hb_ot_layout_get_params() API
And add implementation for StylisticSet UINameID. No API yet.
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 0b753b8..4a8116e 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -248,6 +248,8 @@ struct Script
typedef RecordListOf<Script> ScriptList;
+
+/* http://www.microsoft.com/typography/otspec/features_pt.htm#size */
struct FeatureParamsSize
{
inline bool sanitize (hb_sanitize_context_t *c) {
@@ -255,15 +257,89 @@ struct FeatureParamsSize
return TRACE_RETURN (c->check_struct (this));
}
- USHORT params[5];
+ USHORT designSize; /* Represents the design size in 720/inch
+ * units (decipoints). The design size entry
+ * must be non-zero. When there is a design
+ * size but no recommended size range, the
+ * rest of the array will consist of zeros. */
+ USHORT subfamilyID; /* Has no independent meaning, but serves
+ * as an identifier that associates fonts
+ * in a subfamily. All fonts which share a
+ * Preferred or Font Family name and which
+ * differ only by size range shall have the
+ * same subfamily value, and no fonts which
+ * differ in weight or style shall have the
+ * same subfamily value. If this value is
+ * zero, the remaining fields in the array
+ * will be ignored. */
+ USHORT subfamilyNameID;/* If the preceding value is non-zero, this
+ * value must be set in the range 256 - 32767
+ * (inclusive). It records the value of a
+ * field in the name table, which must
+ * contain English-language strings encoded
+ * in Windows Unicode and Macintosh Roman,
+ * and may contain additional strings
+ * localized to other scripts and languages.
+ * Each of these strings is the name an
+ * application should use, in combination
+ * with the family name, to represent the
+ * subfamily in a menu. Applications will
+ * choose the appropriate version based on
+ * their selection criteria. */
+ USHORT rangeStart; /* Large end of the recommended usage range
+ * (inclusive), stored in 720/inch units
+ * (decipoints). */
+ USHORT rangeEnd; /* Small end of the recommended usage range
+ (exclusive), stored in 720/inch units
+ * (decipoints). */
public:
DEFINE_SIZE_STATIC (10);
};
+/* http://www.microsoft.com/typography/otspec/features_pt.htm#ssxx */
+struct FeatureParamsStylisticSet
+{
+ inline bool sanitize (hb_sanitize_context_t *c) {
+ TRACE_SANITIZE (this);
+ /* Right now minorVersion is at zero. Which means, any table supports
+ * the uiNameID field. */
+ return TRACE_RETURN (c->check_struct (this));
+ }
+
+ USHORT minorVersion; /* (set to 0): This corresponds to a âminorâ
+ * version number. Additional data may be
+ * added to the end of this Feature Parameters
+ * table in the future. */
+
+ USHORT uiNameID; /* The 'name' table name ID that specifies a
+ * string (or strings, for multiple languages)
+ * for a user-interface label for this
+ * feature. The values of uiLabelNameId and
+ * sampleTextNameId are expected to be in the
+ * font-specific name ID range (256-32767),
+ * though that is not a requirement in this
+ * Feature Parameters specification. The
+ * user-interface label for the feature can
+ * be provided in multiple languages. An
+ * English string should be included as a
+ * fallback. The string should be kept to a
+ * minimal length to fit comfortably with
+ * different application interfaces. */
+ public:
+ DEFINE_SIZE_STATIC (4);
+};
+
struct FeatureParams
{
- /* Note: currently the only feature with params is 'size', so we hardcode
- * the length of the table to that of the FeatureParamsSize. */
+ /* Note:
+ *
+ * FeatureParams structures unfortunately don't have a generic length argument,
+ * so their length depends on the feature name / requested use. We don't have
+ * that information at sanitize time. As such, we sanitize for the longest
+ * subtable possible. This may nuke a possibly valid subtable if it's unfortunate
+ * enough to happen at the very end of the GSUB/GPOS table. But that's very
+ * unlikely (I hope!).
+ */
inline bool sanitize (hb_sanitize_context_t *c) {
TRACE_SANITIZE (this);
@@ -271,7 +347,8 @@ struct FeatureParams
}
union {
- FeatureParamsSize size;
+ FeatureParamsSize size;
+ FeatureParamsStylisticSet stylisticSet;
} u;
DEFINE_SIZE_STATIC (10);
};
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 441b3ea..cf485bd 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -640,8 +640,12 @@ hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer, hb_bool_t ze
}
hb_bool_t
-hb_ot_layout_get_size_params (hb_face_t *face,
- uint16_t *data /* OUT, 5 items */)
+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);
@@ -651,17 +655,27 @@ hb_ot_layout_get_size_params (hb_face_t *face,
if (HB_TAG ('s','i','z','e') == gpos.get_feature_tag (i))
{
const OT::Feature &f = gpos.get_feature (i);
- const OT::FeatureParams ¶ms = f.get_feature_params ();
+ const OT::FeatureParamsSize ¶ms = f.get_feature_params ().u.size;
- for (unsigned int i = 0; i < 5; i++)
- data[i] = params.u.size.params[i];
+#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;
}
}
- for (unsigned int i = 0; i < 5; i++)
- data[i] = 0;
+#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;
}
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index f8fab24..134f1a6 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -280,8 +280,12 @@ Xhb_ot_layout_lookup_position (hb_font_t *font,
/* Optical 'size' feature info. Returns true if found.
* http://www.microsoft.com/typography/otspec/features_pt.htm#size */
hb_bool_t
-hb_ot_layout_get_size_params (hb_face_t *face,
- uint16_t *data /* OUT, 5 items */);
+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 */);
HB_END_DECLS
diff --git a/src/test-size-params.cc b/src/test-size-params.cc
index a60aa10..0caef97 100644
--- a/src/test-size-params.cc
+++ b/src/test-size-params.cc
@@ -84,8 +84,13 @@ main (int argc, char **argv)
hb_blob_destroy (blob);
blob = NULL;
- uint16_t params[5];
- if (!hb_ot_layout_get_size_params (face, params))
+ unsigned int params[5];
+ if (!hb_ot_layout_get_size_params (face,
+ params,
+ params+1,
+ params+2,
+ params+3,
+ params+4))
return 1;
for (unsigned int i = 0; i < 5; i++) {
More information about the HarfBuzz
mailing list