* Google Author(s): Behdad Esfahbod
*/
-#include "hb-private.hh"
-#include "hb-debug.hh"
-#define HB_SHAPER uniscribe
-#include "hb-shaper-impl-private.hh"
+#include "hb.hh"
+#include "hb-shaper-impl.hh"
#include <windows.h>
#include <usp10.h>
#include "hb-uniscribe.h"
-#include "hb-open-file-private.hh"
+#include "hb-open-file.hh"
#include "hb-ot-name-table.hh"
-#include "hb-ot-tag.h"
+#include "hb-ot-layout.h"
+
+
+/**
+ * SECTION:hb-uniscribe
+ * @title: hb-uniscribe
+ * @short_description: Windows integration
+ * @include: hb-uniscribe.h
+ *
+ * Functions for using HarfBuzz with the Windows fonts.
+ **/
static inline uint16_t hb_uint16_swap (const uint16_t v)
}
-struct hb_uniscribe_shaper_funcs_t {
+struct hb_uniscribe_shaper_funcs_t
+{
SIOT ScriptItemizeOpenType;
SSOT ScriptShapeOpenType;
SPOT ScriptPlaceOpenType;
- inline void init (void)
+ void init ()
{
HMODULE hinstLib;
this->ScriptItemizeOpenType = nullptr;
hinstLib = GetModuleHandle (TEXT ("usp10.dll"));
if (hinstLib)
{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-function-type"
this->ScriptItemizeOpenType = (SIOT) GetProcAddress (hinstLib, "ScriptItemizeOpenType");
this->ScriptShapeOpenType = (SSOT) GetProcAddress (hinstLib, "ScriptShapeOpenType");
this->ScriptPlaceOpenType = (SPOT) GetProcAddress (hinstLib, "ScriptPlaceOpenType");
+#pragma GCC diagnostic pop
}
if (!this->ScriptItemizeOpenType ||
!this->ScriptShapeOpenType ||
}
}
};
-static hb_uniscribe_shaper_funcs_t *uniscribe_funcs;
-#ifdef HB_USE_ATEXIT
-static inline void
-free_uniscribe_funcs (void)
-{
-retry:
- hb_uniscribe_shaper_funcs_t *local_uniscribe_funcs =
- (hb_uniscribe_shaper_funcs_t *) hb_atomic_ptr_get (&uniscribe_funcs);
- if (!hb_atomic_ptr_cmpexch (&uniscribe_funcs, local_uniscribe_funcs, nullptr))
- goto retry;
- free (uniscribe_funcs);
-}
-#endif
+static void free_static_uniscribe_shaper_funcs ();
-static hb_uniscribe_shaper_funcs_t *
-hb_uniscribe_shaper_get_funcs (void)
+static struct hb_uniscribe_shaper_funcs_lazy_loader_t : hb_lazy_loader_t<hb_uniscribe_shaper_funcs_t,
+ hb_uniscribe_shaper_funcs_lazy_loader_t>
{
-retry:
- hb_uniscribe_shaper_funcs_t *funcs = (hb_uniscribe_shaper_funcs_t *) hb_atomic_ptr_get (&uniscribe_funcs);
-
- if (unlikely (!funcs))
+ static hb_uniscribe_shaper_funcs_t *create ()
{
- funcs = (hb_uniscribe_shaper_funcs_t *) calloc (1, sizeof (hb_uniscribe_shaper_funcs_t));
+ hb_uniscribe_shaper_funcs_t *funcs = (hb_uniscribe_shaper_funcs_t *) calloc (1, sizeof (hb_uniscribe_shaper_funcs_t));
if (unlikely (!funcs))
return nullptr;
funcs->init ();
- if (!hb_atomic_ptr_cmpexch (&uniscribe_funcs, nullptr, funcs)) {
- free (funcs);
- goto retry;
- }
-
-#ifdef HB_USE_ATEXIT
- atexit (free_uniscribe_funcs); /* First person registers atexit() callback. */
+#if HB_USE_ATEXIT
+ atexit (free_static_uniscribe_shaper_funcs);
#endif
+
+ return funcs;
}
+ static void destroy (hb_uniscribe_shaper_funcs_t *p)
+ {
+ free ((void *) p);
+ }
+ static hb_uniscribe_shaper_funcs_t *get_null ()
+ {
+ return nullptr;
+ }
+} static_uniscribe_shaper_funcs;
+
+#if HB_USE_ATEXIT
+static
+void free_static_uniscribe_shaper_funcs ()
+{
+ static_uniscribe_shaper_funcs.free_instance ();
+}
+#endif
- return funcs;
+static hb_uniscribe_shaper_funcs_t *
+hb_uniscribe_shaper_get_funcs ()
+{
+ return static_uniscribe_shaper_funcs.get_unconst ();
}
a->rec.lParameter < b->rec.lParameter ? -1 : a->rec.lParameter > b->rec.lParameter ? 1 :
0;
}
- bool operator== (const active_feature_t *f) {
- return cmp (this, f) == 0;
- }
+ bool operator== (const active_feature_t *f)
+ { return cmp (this, f) == 0; }
};
struct feature_event_t {
bool start;
active_feature_t feature;
- static int cmp (const void *pa, const void *pb) {
+ static int cmp (const void *pa, const void *pb)
+ {
const feature_event_t *a = (const feature_event_t *) pa;
const feature_event_t *b = (const feature_event_t *) pb;
return a->index < b->index ? -1 : a->index > b->index ? 1 :
unsigned int index_last; /* == end - 1 */
};
-HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, face)
-HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, font)
-
/*
* shaper face data
*/
-struct hb_uniscribe_shaper_face_data_t {
+struct hb_uniscribe_face_data_t {
HANDLE fh;
hb_uniscribe_shaper_funcs_t *funcs;
wchar_t face_name[LF_FACESIZE];
* full, PS. All of them point to the same name data with our unique name.
*/
- blob = OT::Sanitizer<OT::OpenTypeFontFile>().sanitize (blob);
+ blob = hb_sanitize_context_t ().sanitize_blob<OT::OpenTypeFontFile> (blob);
unsigned int length, new_length, name_str_len;
const char *orig_sfnt_data = hb_blob_get_data (blob, &length);
memcpy(new_sfnt_data, orig_sfnt_data, length);
- OT::name &name = OT::StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
+ OT::name &name = StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
name.format.set (0);
name.count.set (ARRAY_LENGTH (name_IDs));
name.stringOffset.set (name.get_size ());
for (unsigned int i = 0; i < ARRAY_LENGTH (name_IDs); i++)
{
- OT::NameRecord &record = name.nameRecord[i];
+ OT::NameRecord &record = name.nameRecordZ[i];
record.platformID.set (3);
record.encodingID.set (1);
record.languageID.set (0x0409u); /* English */
}
/* Copy string data from new_name, converting wchar_t to UTF16BE. */
- unsigned char *p = &OT::StructAfter<unsigned char> (name);
+ unsigned char *p = &StructAfter<unsigned char> (name);
for (unsigned int i = 0; i < name_str_len; i++)
{
*p++ = new_name[i] >> 8;
HB_MEMORY_MODE_WRITABLE, nullptr, free);
}
-hb_uniscribe_shaper_face_data_t *
+hb_uniscribe_face_data_t *
_hb_uniscribe_shaper_face_data_create (hb_face_t *face)
{
- hb_uniscribe_shaper_face_data_t *data = (hb_uniscribe_shaper_face_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_face_data_t));
+ hb_uniscribe_face_data_t *data = (hb_uniscribe_face_data_t *) calloc (1, sizeof (hb_uniscribe_face_data_t));
if (unlikely (!data))
return nullptr;
}
void
-_hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_shaper_face_data_t *data)
+_hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_face_data_t *data)
{
RemoveFontMemResourceEx (data->fh);
free (data);
* shaper font data
*/
-struct hb_uniscribe_shaper_font_data_t {
+struct hb_uniscribe_font_data_t
+{
HDC hdc;
- LOGFONTW log_font;
+ mutable LOGFONTW log_font;
HFONT hfont;
- SCRIPT_CACHE script_cache;
+ mutable SCRIPT_CACHE script_cache;
double x_mult, y_mult; /* From LOGFONT space to HB space. */
};
lf->lfHeight = - (int) font_size;
lf->lfCharSet = DEFAULT_CHARSET;
- hb_face_t *face = font->face;
- hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
-
- memcpy (lf->lfFaceName, face_data->face_name, sizeof (lf->lfFaceName));
+ memcpy (lf->lfFaceName, font->face->data.uniscribe->face_name, sizeof (lf->lfFaceName));
return true;
}
-hb_uniscribe_shaper_font_data_t *
+hb_uniscribe_font_data_t *
_hb_uniscribe_shaper_font_data_create (hb_font_t *font)
{
- if (unlikely (!hb_uniscribe_shaper_face_data_ensure (font->face))) return nullptr;
-
- hb_uniscribe_shaper_font_data_t *data = (hb_uniscribe_shaper_font_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_font_data_t));
+ hb_uniscribe_font_data_t *data = (hb_uniscribe_font_data_t *) calloc (1, sizeof (hb_uniscribe_font_data_t));
if (unlikely (!data))
return nullptr;
}
void
-_hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_shaper_font_data_t *data)
+_hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_font_data_t *data)
{
if (data->hdc)
ReleaseDC (nullptr, data->hdc);
LOGFONTW *
hb_uniscribe_font_get_logfontw (hb_font_t *font)
{
- if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return nullptr;
- hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
- return &font_data->log_font;
+ const hb_uniscribe_font_data_t *data = font->data.uniscribe;
+ return data ? &data->log_font : nullptr;
}
HFONT
hb_uniscribe_font_get_hfont (hb_font_t *font)
{
- if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return nullptr;
- hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
- return font_data->hfont;
-}
-
-
-/*
- * shaper shape_plan data
- */
-
-struct hb_uniscribe_shaper_shape_plan_data_t {};
-
-hb_uniscribe_shaper_shape_plan_data_t *
-_hb_uniscribe_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_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
-}
-
-void
-_hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shaper_shape_plan_data_t *data HB_UNUSED)
-{
+ const hb_uniscribe_font_data_t *data = font->data.uniscribe;
+ return data ? data->hfont : nullptr;
}
unsigned int num_features)
{
hb_face_t *face = font->face;
- hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
- hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
+ const hb_uniscribe_face_data_t *face_data = face->data.uniscribe;
+ const hb_uniscribe_font_data_t *font_data = font->data.uniscribe;
hb_uniscribe_shaper_funcs_t *funcs = face_data->funcs;
/*
* Set up features.
*/
- hb_auto_t<hb_vector_t<OPENTYPE_FEATURE_RECORD> > feature_records;
- hb_auto_t<hb_vector_t<range_record_t> > range_records;
+ hb_vector_t<OPENTYPE_FEATURE_RECORD> feature_records;
+ hb_vector_t<range_record_t> range_records;
if (num_features)
{
/* Sort features by start/end events. */
- hb_auto_t<hb_vector_t<feature_event_t> > feature_events;
+ hb_vector_t<feature_event_t> feature_events;
for (unsigned int i = 0; i < num_features; i++)
{
active_feature_t feature;
}
/* Scan events and save features for each range. */
- hb_auto_t<hb_vector_t<active_feature_t> > active_features;
+ hb_vector_t<active_feature_t> active_features;
unsigned int last_index = 0;
- for (unsigned int i = 0; i < feature_events.len; i++)
+ for (unsigned int i = 0; i < feature_events.length; i++)
{
feature_event_t *event = &feature_events[i];
/* Save a snapshot of active features and the range. */
range_record_t *range = range_records.push ();
- unsigned int offset = feature_records.len;
+ unsigned int offset = feature_records.length;
active_features.qsort ();
- for (unsigned int j = 0; j < active_features.len; j++)
+ for (unsigned int j = 0; j < active_features.length; j++)
{
- if (!j || active_features[j].rec.tagFeature != feature_records[feature_records.len - 1].tagFeature)
+ if (!j || active_features[j].rec.tagFeature != feature_records[feature_records.length - 1].tagFeature)
{
feature_records.push (active_features[j].rec);
}
else
{
/* Overrides value for existing feature. */
- feature_records[feature_records.len - 1].lParameter = active_features[j].rec.lParameter;
+ feature_records[feature_records.length - 1].lParameter = active_features[j].rec.lParameter;
}
}
/* Will convert to pointer after all is ready, since feature_records.array
* may move as we grow it. */
range->props.potfRecords = reinterpret_cast<OPENTYPE_FEATURE_RECORD *> (offset);
- range->props.cotfRecords = feature_records.len - offset;
+ range->props.cotfRecords = feature_records.length - offset;
range->index_first = last_index;
range->index_last = event->index - 1;
{
active_feature_t *feature = active_features.find (&event->feature);
if (feature)
- active_features.remove (feature - active_features.arrayZ);
+ active_features.remove (feature - active_features.arrayZ ());
}
}
- if (!range_records.len) /* No active feature found. */
+ if (!range_records.length) /* No active feature found. */
num_features = 0;
/* Fixup the pointers. */
- for (unsigned int i = 0; i < range_records.len; i++)
+ for (unsigned int i = 0; i < range_records.length; i++)
{
range_record_t *range = &range_records[i];
- range->props.potfRecords = feature_records.arrayZ + reinterpret_cast<uintptr_t> (range->props.potfRecords);
+ range->props.potfRecords = (OPENTYPE_FEATURE_RECORD *) feature_records + reinterpret_cast<uintptr_t> (range->props.potfRecords);
}
}
script_tags,
&item_count);
if (unlikely (FAILED (hr)))
- FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr);
+ FAIL ("ScriptItemizeOpenType() failed: 0x%08lx", hr);
#undef MAX_ITEMS
- OPENTYPE_TAG language_tag = hb_uint32_swap (hb_ot_tag_from_language (buffer->props.language));
- hb_auto_t<hb_vector_t<TEXTRANGE_PROPERTIES*> > range_properties;
- hb_auto_t<hb_vector_t<int> > range_char_counts;
+ hb_tag_t lang_tag;
+ unsigned int lang_count = 1;
+ hb_ot_tags_from_script_and_language (buffer->props.script,
+ buffer->props.language,
+ nullptr, nullptr,
+ &lang_count, &lang_tag);
+ OPENTYPE_TAG language_tag = hb_uint32_swap (lang_count ? lang_tag : HB_TAG_NONE);
+ hb_vector_t<TEXTRANGE_PROPERTIES*> range_properties;
+ hb_vector_t<int> range_char_counts;
unsigned int glyphs_offset = 0;
unsigned int glyphs_len;
range--;
while (log_clusters[k] > range->index_last)
range++;
- if (!range_properties.len ||
- &range->props != range_properties[range_properties.len - 1])
+ if (!range_properties.length ||
+ &range->props != range_properties[range_properties.length - 1])
{
TEXTRANGE_PROPERTIES **props = range_properties.push ();
int *c = range_char_counts.push ();
}
else
{
- range_char_counts[range_char_counts.len - 1]++;
+ range_char_counts[range_char_counts.length - 1]++;
}
last_range = range;
&items[i].a,
script_tags[i],
language_tag,
- range_char_counts.arrayZ,
- range_properties.arrayZ,
- range_properties.len,
+ range_char_counts.arrayZ (),
+ range_properties.arrayZ (),
+ range_properties.length,
pchars + chars_offset,
item_chars_len,
glyphs_size - glyphs_offset,
}
if (unlikely (FAILED (hr)))
{
- FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr);
+ FAIL ("ScriptShapeOpenType() failed: 0x%08lx", hr);
}
for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
&items[i].a,
script_tags[i],
language_tag,
- range_char_counts.arrayZ,
- range_properties.arrayZ,
- range_properties.len,
+ range_char_counts.arrayZ (),
+ range_properties.arrayZ (),
+ range_properties.length,
pchars + chars_offset,
log_clusters + chars_offset,
char_props + chars_offset,
offsets + glyphs_offset,
nullptr);
if (unlikely (FAILED (hr)))
- FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);
+ FAIL ("ScriptPlaceOpenType() failed: 0x%08lx", hr);
if (DEBUG_ENABLED (UNISCRIBE))
fprintf (stderr, "Item %d RTL %d LayoutRTL %d LogicalOrder %d ScriptTag %c%c%c%c\n",
/* Calculate visual-clusters. That's what we ship. */
for (unsigned int i = 0; i < glyphs_len; i++)
- vis_clusters[i] = -1;
+ vis_clusters[i] = (uint32_t) -1;
for (unsigned int i = 0; i < buffer->len; i++) {
uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
*p = MIN (*p, buffer->info[i].cluster);
}
for (unsigned int i = 1; i < glyphs_len; i++)
- if (vis_clusters[i] == -1)
+ if (vis_clusters[i] == (uint32_t) -1)
vis_clusters[i] = vis_clusters[i - 1];
#undef utf16_index