hb-uniscribe.cc revision 71388b3ee71c7d3b79f842db7588bd683691797c
10fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod/*
20fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * Copyright © 2011  Google, Inc.
30fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod *
40fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
50fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod *
60fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * Permission is hereby granted, without written agreement and without
70fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
80fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * software and its documentation for any purpose, provided that the
90fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * above copyright notice and the following two paragraphs appear in
100fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * all copies of this software.
110fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod *
120fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
130fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
140fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
150fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
160fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * DAMAGE.
170fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod *
180fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
190fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
200fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
210fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
220fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
230fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod *
240fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod * Google Author(s): Behdad Esfahbod
250fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod */
260fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
270fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define _WIN32_WINNT 0x0500
280fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
290fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "hb-private.hh"
300fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
31b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod#include <windows.h>
32b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod#include <usp10.h>
33b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod
34b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbodtypedef ULONG WIN_ULONG;
35b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod
360fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "hb-uniscribe.h"
370fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
387a750ac33ec482e2c4856c19ea607f3563741c24Behdad Esfahbod#include "hb-ot-name-table.hh"
390fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "hb-ot-tag.h"
400fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
410fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "hb-font-private.hh"
420fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "hb-buffer-private.hh"
430fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
440fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
460fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#ifndef HB_DEBUG_UNISCRIBE
470fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
480fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#endif
490fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
500fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
510fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod/*
520fbb2dc83132a89201ad8b56c6909610437d2da0Behdad EsfahbodDWORD GetFontData(
530fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   HDC hdc,
540fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   DWORD dwTable,
550fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   DWORD dwOffset,
560fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __out  LPVOID lpvBuffer,
570fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   DWORD cbData
580fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod);
590fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod*/
600fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
61892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbodstatic bool
620fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodpopulate_log_font (LOGFONTW  *lf,
630fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod		   HDC        hdc,
64892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod		   hb_font_t *font)
650fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod{
660fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  memset (lf, 0, sizeof (*lf));
670fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  int dpi = GetDeviceCaps (hdc, LOGPIXELSY);
683fd2b5bece28c81e3e379352f09eee39d19ac372Behdad Esfahbod  lf->lfHeight = -font->y_scale;
690fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
70892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  hb_blob_t *blob = Sanitizer<name>::sanitize (hb_face_reference_table (font->face, HB_TAG ('n','a','m','e')));
71892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  const name *name_table = Sanitizer<name>::lock_instance (blob);
72892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  unsigned int len = name_table->get_name (3, 1, 0x409, 4,
73892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod					   lf->lfFaceName,
74892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod					   sizeof (lf->lfFaceName[0]) * LF_FACESIZE)
75892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod					  / sizeof (lf->lfFaceName[0]);
76826e22732dd8697600a1392f48af21b7b3ce6271Behdad Esfahbod  hb_blob_destroy (blob);
77826e22732dd8697600a1392f48af21b7b3ce6271Behdad Esfahbod
78892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  if (unlikely (!len)) {
79892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod    DEBUG_MSG (UNISCRIBE, NULL, "Didn't find English name table entry");
80892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod    return FALSE;
81892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  }
82892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  if (unlikely (len >= LF_FACESIZE)) {
83892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod    DEBUG_MSG (UNISCRIBE, NULL, "Font name too long");
84892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod    return FALSE;
85892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  }
86e9c71fab30fd1d5b163c8a072f9e2d3eb8ba3a92Behdad Esfahbod
87892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  for (unsigned int i = 0; i < len; i++)
88892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod    lf->lfFaceName[i] = hb_be_uint16 (lf->lfFaceName[i]);
89892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  lf->lfFaceName[len] = 0;
90e9c71fab30fd1d5b163c8a072f9e2d3eb8ba3a92Behdad Esfahbod
91892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  return TRUE;
920fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod}
930fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
94bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
9571388b3ee71c7d3b79f842db7588bd683691797cBehdad Esfahbodstatic hb_user_data_key_t uniscribe_data_key;
9671388b3ee71c7d3b79f842db7588bd683691797cBehdad Esfahbod
9771388b3ee71c7d3b79f842db7588bd683691797cBehdad Esfahbod
98255f176fdcd42ab94f9c3c54e2bffb55d0b1a8f5Behdad Esfahbodstatic struct hb_uniscribe_face_data_t {
99bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HANDLE fh;
100bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod} _hb_uniscribe_face_data_nil = {0};
101bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
102bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbodstatic void
103bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod_hb_uniscribe_face_data_destroy (hb_uniscribe_face_data_t *data)
104bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
105bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->fh)
106bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    RemoveFontMemResourceEx (data->fh);
107bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  free (data);
108bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod}
109bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
110bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbodstatic hb_uniscribe_face_data_t *
111bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod_hb_uniscribe_face_get_data (hb_face_t *face)
112bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
11371388b3ee71c7d3b79f842db7588bd683691797cBehdad Esfahbod  hb_uniscribe_face_data_t *data = (hb_uniscribe_face_data_t *) hb_face_get_user_data (face, &uniscribe_data_key);
114bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (likely (data)) return data;
115bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
116bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  data = (hb_uniscribe_face_data_t *) calloc (1, sizeof (hb_uniscribe_face_data_t));
117bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (unlikely (!data))
118bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    return &_hb_uniscribe_face_data_nil;
119bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
120bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  hb_blob_t *blob = hb_face_reference_blob (face);
121bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  unsigned int blob_length;
122bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  const char *blob_data = hb_blob_get_data (blob, &blob_length);
123bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (unlikely (!blob_length))
124bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, face, "Face has empty blob");
125bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
126bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  DWORD num_fonts_installed;
127bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  data->fh = AddFontMemResourceEx ((void *) blob_data, blob_length, 0, &num_fonts_installed);
128bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  hb_blob_destroy (blob);
129bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (unlikely (!data->fh))
130bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed");
131bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
13271388b3ee71c7d3b79f842db7588bd683691797cBehdad Esfahbod  if (unlikely (!hb_face_set_user_data (face, &uniscribe_data_key, data,
13333ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod					(hb_destroy_func_t) _hb_uniscribe_face_data_destroy,
13433ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod					FALSE)))
135bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  {
136bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    _hb_uniscribe_face_data_destroy (data);
13771388b3ee71c7d3b79f842db7588bd683691797cBehdad Esfahbod    data = (hb_uniscribe_face_data_t *) hb_face_get_user_data (face, &uniscribe_data_key);
13833ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod    if (data)
13933ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod      return data;
14033ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod    else
14133ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod      return &_hb_uniscribe_face_data_nil;
142bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  }
143bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
144bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  return data;
145bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod}
146bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
147bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
148bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbodstatic struct hb_uniscribe_font_data_t {
149bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HDC hdc;
150d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  LOGFONTW log_font;
151bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HFONT hfont;
152bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  SCRIPT_CACHE script_cache;
153bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod} _hb_uniscribe_font_data_nil = {NULL, NULL, NULL};
154bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
155bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbodstatic void
156bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod_hb_uniscribe_font_data_destroy (hb_uniscribe_font_data_t *data)
157bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
158bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->hdc)
159bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    ReleaseDC (NULL, data->hdc);
160bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->hfont)
161bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DeleteObject (data->hfont);
162bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->script_cache)
163bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    ScriptFreeCache (&data->script_cache);
164bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  free (data);
165bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod}
166bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
167bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbodstatic hb_uniscribe_font_data_t *
168bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod_hb_uniscribe_font_get_data (hb_font_t *font)
169bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
17071388b3ee71c7d3b79f842db7588bd683691797cBehdad Esfahbod  hb_uniscribe_font_data_t *data = (hb_uniscribe_font_data_t *) hb_font_get_user_data (font, &uniscribe_data_key);
171bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (likely (data)) return data;
172bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
173bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  data = (hb_uniscribe_font_data_t *) calloc (1, sizeof (hb_uniscribe_font_data_t));
174bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (unlikely (!data))
175bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    return &_hb_uniscribe_font_data_nil;
176bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
177bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  data->hdc = GetDC (NULL);
178bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
179d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  if (unlikely (!populate_log_font (&data->log_font, data->hdc, font)))
180bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, font, "Font populate_log_font() failed");
181bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  else {
182d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod    data->hfont = CreateFontIndirectW (&data->log_font);
183bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    if (unlikely (!data->hfont))
184bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod      DEBUG_MSG (UNISCRIBE, font, "Font CreateFontIndirectW() failed");
185bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    if (!SelectObject (data->hdc, data->hfont))
186bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod      DEBUG_MSG (UNISCRIBE, font, "Font SelectObject() failed");
187bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  }
188bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
18971388b3ee71c7d3b79f842db7588bd683691797cBehdad Esfahbod  if (unlikely (!hb_font_set_user_data (font, &uniscribe_data_key, data,
19033ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod					(hb_destroy_func_t) _hb_uniscribe_font_data_destroy,
19133ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod					FALSE)))
192bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  {
193bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    _hb_uniscribe_font_data_destroy (data);
19471388b3ee71c7d3b79f842db7588bd683691797cBehdad Esfahbod    data = (hb_uniscribe_font_data_t *) hb_font_get_user_data (font, &uniscribe_data_key);
19533ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod    if (data)
19633ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod      return data;
19733ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod    else
19833ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod      return &_hb_uniscribe_font_data_nil;
199bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  }
200bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
201bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  return data;
202bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod}
203bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
204d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad EsfahbodLOGFONTW *
205d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbodhb_uniscribe_font_get_logfontw (hb_font_t *font)
206d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod{
207d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  hb_uniscribe_font_data_t *font_data = _hb_uniscribe_font_get_data (font);
208d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  if (unlikely (!font_data))
209d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod    return NULL;
210d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  return &font_data->log_font;
211d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod}
212d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod
213d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad EsfahbodHFONT
214d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbodhb_uniscribe_font_get_hfont (hb_font_t *font)
215d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod{
216d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  hb_uniscribe_font_data_t *font_data = _hb_uniscribe_font_get_data (font);
217d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  if (unlikely (!font_data))
218d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod    return 0;
219d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  return font_data->hfont;
220d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod}
221d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod
222bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
22302aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbodhb_bool_t
2240fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodhb_uniscribe_shape (hb_font_t          *font,
2250fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod		    hb_buffer_t        *buffer,
2260fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod		    const hb_feature_t *features,
22702aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod		    unsigned int        num_features,
2280501573deda3a8dcdfcea491392f554f21ed0154Behdad Esfahbod		    const char * const *shaper_options)
2290fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod{
23002aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod  buffer->guess_properties ();
23102aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod
232bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod#define FAIL(...) \
233bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HB_STMT_START { \
234bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \
235bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    return FALSE; \
236bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  } HB_STMT_END;
237bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
238bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  hb_uniscribe_face_data_t *face_data = _hb_uniscribe_face_get_data (font->face);
239a9057eb3f38018faa1ece53c4aaeeba798b41fd1Behdad Esfahbod  if (unlikely (!face_data->fh))
240bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    FAIL ("Couldn't get face data");
241bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
242bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  hb_uniscribe_font_data_t *font_data = _hb_uniscribe_font_get_data (font);
243a9057eb3f38018faa1ece53c4aaeeba798b41fd1Behdad Esfahbod  if (unlikely (!font_data->hfont))
244bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    FAIL ("Couldn't get font font");
2450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
24602aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod  if (unlikely (!buffer->len))
24702aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod    return TRUE;
2480fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
249bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HRESULT hr;
250bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
2510fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodretry:
2520fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2530fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int scratch_size;
2540fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
2550fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2560fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Allocate char buffers; they all fit */
2570fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2580fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define ALLOCATE_ARRAY(Type, name, len) \
2590fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  Type *name = (Type *) scratch; \
2600fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  scratch += len * sizeof (name[0]); \
2610fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  scratch_size -= len * sizeof (name[0]);
2620fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2630fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define utf16_index() var1.u32
2640fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2650fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  WCHAR *pchars = (WCHAR *) scratch;
2660fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int chars_len = 0;
2670fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < buffer->len; i++) {
2680fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    hb_codepoint_t c = buffer->info[i].codepoint;
2690fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    buffer->info[i].utf16_index() = chars_len;
2700fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    if (likely (c < 0x10000))
2710fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = c;
2720fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    else if (unlikely (c >= 0x110000))
2730fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = 0xFFFD;
2740fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    else {
2750fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10);
2760fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1));
2770fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    }
2780fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
2790fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2800fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (WCHAR, wchars, chars_len);
2810fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (WORD, log_clusters, chars_len);
2820fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (SCRIPT_CHARPROP, char_props, chars_len);
2830fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2840fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* On Windows, we don't care about alignment...*/
2850fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int glyphs_size = scratch_size / (sizeof (WORD) +
2860fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (SCRIPT_GLYPHPROP) +
2870fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (int) +
2880fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (GOFFSET) +
2890fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (uint32_t));
2900fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2910fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (WORD, glyphs, glyphs_size);
2920fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size);
2930fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (int, advances, glyphs_size);
2940fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size);
2950fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
2960fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2970fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2980fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define MAX_ITEMS 10
2990fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3000fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  SCRIPT_ITEM items[MAX_ITEMS + 1];
3010fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  SCRIPT_STATE bidi_state = {0};
302b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod  WIN_ULONG script_tags[MAX_ITEMS];
3030fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  int item_count;
3040fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3050fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
3060fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  bidi_state.fOverrideDirection = 1;
3070fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3080fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  hr = ScriptItemizeOpenType (wchars,
3090fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      chars_len,
3100fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      MAX_ITEMS,
3110fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      NULL,
3120fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      &bidi_state,
3130fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      items,
3140fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      script_tags,
3150fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      &item_count);
3160fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  if (unlikely (FAILED (hr)))
3172eb474afb4a09f4da8f14b444bd6066769010224Behdad Esfahbod    FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr);
3180fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3190fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#undef MAX_ITEMS
3200fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3210fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  int *range_char_counts = NULL;
3220fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  TEXTRANGE_PROPERTIES **range_properties = NULL;
3230fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  int range_count = 0;
3240fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  if (num_features) {
3250fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    /* XXX setup ranges */
3260fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
3270fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3280fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  OPENTYPE_TAG language_tag = hb_ot_tag_from_language (buffer->props.language);
3290fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3300fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int glyphs_offset = 0;
3310fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int glyphs_len;
3320fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < item_count; i++)
3330fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  {
3340fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      unsigned int chars_offset = items[i].iCharPos;
3350fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;
3360fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      OPENTYPE_TAG script_tag = script_tags[i]; /* XXX buffer->props.script */
3370fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
338bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod      hr = ScriptShapeOpenType (font_data->hdc,
339bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod				&font_data->script_cache,
3400fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				&items[i].a,
3410fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				script_tag,
3420fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				language_tag,
3430fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				range_char_counts,
3440fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				range_properties,
3450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				range_count,
3460fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				wchars + chars_offset,
3470fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				item_chars_len,
3480fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				glyphs_size - glyphs_offset,
3490fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				/* out */
3500fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				log_clusters + chars_offset,
3510fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				char_props + chars_offset,
3520fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				glyphs + glyphs_offset,
3530fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				glyph_props + glyphs_offset,
3540fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				(int *) &glyphs_len);
3550fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3560fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      if (unlikely (items[i].a.fNoGlyphIndex))
35702aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod	FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
3580fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      if (unlikely (hr == E_OUTOFMEMORY))
3590fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      {
3600fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod        buffer->ensure (buffer->allocated * 2);
3610fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod	if (buffer->in_error)
36202aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod	  FAIL ("Buffer resize failed");
3630fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod	goto retry;
3640fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      }
3652eb474afb4a09f4da8f14b444bd6066769010224Behdad Esfahbod      if (unlikely (hr == USP_E_SCRIPT_NOT_IN_FONT))
3662eb474afb4a09f4da8f14b444bd6066769010224Behdad Esfahbod	FAIL ("ScriptShapeOpenType() failed: Font doesn't support script");
3670fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      if (unlikely (FAILED (hr)))
3682eb474afb4a09f4da8f14b444bd6066769010224Behdad Esfahbod	FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr);
3690fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
370bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod      hr = ScriptPlaceOpenType (font_data->hdc,
371bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod				&font_data->script_cache,
3720fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				&items[i].a,
3730fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				script_tag,
3740fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				language_tag,
3750fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				range_char_counts,
3760fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				range_properties,
3770fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				range_count,
3780fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				wchars + chars_offset,
3790fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				log_clusters + chars_offset,
3800fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				char_props + chars_offset,
3810fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				item_chars_len,
3820fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				glyphs + glyphs_offset,
3830fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				glyph_props + glyphs_offset,
3840fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				glyphs_len,
3850fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				/* out */
3860fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				advances + glyphs_offset,
3870fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				offsets + glyphs_offset,
3880fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod				NULL);
3890fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      if (unlikely (FAILED (hr)))
3902eb474afb4a09f4da8f14b444bd6066769010224Behdad Esfahbod	FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);
3910fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3920fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      glyphs_offset += glyphs_len;
3930fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
3940fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  glyphs_len = glyphs_offset;
3950fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3960fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Ok, we've got everything we need, now compose output buffer,
3970fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod   * very, *very*, carefully! */
3980fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3990fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Calculate visual-clusters.  That's what we ship. */
4000fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < buffer->len; i++)
401577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod    vis_clusters[i] = 0;
402577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod  for (unsigned int i = 0; i < buffer->len; i++) {
403577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod    uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
404577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod    *p = MIN (*p, buffer->info[i].cluster);
405577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod  }
4060fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 1; i < glyphs_len; i++)
4070fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    if (!glyph_props[i].sva.fClusterStart)
4080fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    vis_clusters[i] = vis_clusters[i - 1];
4090fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4100fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#undef utf16_index
4110fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4120fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  buffer->ensure (glyphs_len);
4130fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  if (buffer->in_error)
41402aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod    FAIL ("Buffer in error");
4150fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
41602aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod#undef FAIL
4170fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4180fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Set glyph infos */
419d753ac78da5619a0a545cdaf7a8e65787e996570Behdad Esfahbod  buffer->len = 0;
4200fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < glyphs_len; i++)
4210fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  {
422d753ac78da5619a0a545cdaf7a8e65787e996570Behdad Esfahbod    if (glyph_props[i].sva.fZeroWidth)
423d753ac78da5619a0a545cdaf7a8e65787e996570Behdad Esfahbod      continue;
424d753ac78da5619a0a545cdaf7a8e65787e996570Behdad Esfahbod
425d753ac78da5619a0a545cdaf7a8e65787e996570Behdad Esfahbod    hb_glyph_info_t *info = &buffer->info[buffer->len++];
4260fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4270fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->codepoint = glyphs[i];
4280fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->cluster = vis_clusters[i];
4290fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4300fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    /* The rest is crap.  Let's store position info there for now. */
4310fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->mask = advances[i];
4320fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->var1.u32 = offsets[i].du;
4330fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->var2.u32 = offsets[i].dv;
4340fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
4350fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4360fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Set glyph positions */
4370fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  buffer->clear_positions ();
4380fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < glyphs_len; i++)
4390fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  {
4400fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    hb_glyph_info_t *info = &buffer->info[i];
4410fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    hb_glyph_position_t *pos = &buffer->pos[i];
4420fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4430fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    /* TODO vertical */
4440fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    pos->x_advance = info->mask;
4450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    pos->x_offset = info->var1.u32;
4460fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    pos->y_offset = info->var2.u32;
4470fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
4480fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4490fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Wow, done! */
45002aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod  return TRUE;
4510fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod}
4520fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4530fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
454