hb-uniscribe.cc revision 5b95c148cc485f79fd7018bc4520b4cb5f728a18
10fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod/*
21c1233e57686d77d89fe3ac1dc53de9ee60798c1Behdad Esfahbod * Copyright © 2011,2012  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
27552bf3a9f9651311084b7979805dbdc18c0335caBehdad Esfahbod#define _WIN32_WINNT 0x0600
280fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
29027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod#define HB_SHAPER uniscribe
30027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod#include "hb-shaper-impl-private.hh"
310fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
32b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod#include <windows.h>
33b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod#include <usp10.h>
34b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod
35b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbodtypedef ULONG WIN_ULONG;
36b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod
370fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "hb-uniscribe.h"
380fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
397a750ac33ec482e2c4856c19ea607f3563741c24Behdad Esfahbod#include "hb-ot-name-table.hh"
400fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "hb-ot-tag.h"
410fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
420fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
430fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#ifndef HB_DEBUG_UNISCRIBE
440fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#endif
460fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
470fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
480fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod/*
490fbb2dc83132a89201ad8b56c6909610437d2da0Behdad EsfahbodDWORD GetFontData(
500fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   HDC hdc,
510fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   DWORD dwTable,
520fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   DWORD dwOffset,
530fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __out  LPVOID lpvBuffer,
540fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   DWORD cbData
550fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod);
560fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod*/
570fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
58892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbodstatic bool
590fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodpopulate_log_font (LOGFONTW  *lf,
60892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod		   hb_font_t *font)
610fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod{
620fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  memset (lf, 0, sizeof (*lf));
633fd2b5bece28c81e3e379352f09eee39d19ac372Behdad Esfahbod  lf->lfHeight = -font->y_scale;
64dbffa4c83d29c689ee4cd8a1c53e84521028c711Behdad Esfahbod  lf->lfCharSet = DEFAULT_CHARSET;
650fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
66892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  hb_blob_t *blob = Sanitizer<name>::sanitize (hb_face_reference_table (font->face, HB_TAG ('n','a','m','e')));
67892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  const name *name_table = Sanitizer<name>::lock_instance (blob);
68892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  unsigned int len = name_table->get_name (3, 1, 0x409, 4,
69892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod					   lf->lfFaceName,
70892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod					   sizeof (lf->lfFaceName[0]) * LF_FACESIZE)
71892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod					  / sizeof (lf->lfFaceName[0]);
72826e22732dd8697600a1392f48af21b7b3ce6271Behdad Esfahbod  hb_blob_destroy (blob);
73826e22732dd8697600a1392f48af21b7b3ce6271Behdad Esfahbod
74892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  if (unlikely (!len)) {
75892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod    DEBUG_MSG (UNISCRIBE, NULL, "Didn't find English name table entry");
760594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
77892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  }
78892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  if (unlikely (len >= LF_FACESIZE)) {
79892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod    DEBUG_MSG (UNISCRIBE, NULL, "Font name too long");
800594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false;
81892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  }
82e9c71fab30fd1d5b163c8a072f9e2d3eb8ba3a92Behdad Esfahbod
83892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  for (unsigned int i = 0; i < len; i++)
84892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod    lf->lfFaceName[i] = hb_be_uint16 (lf->lfFaceName[i]);
85892eb2e462b40451b8f73879eab66310d884386aBehdad Esfahbod  lf->lfFaceName[len] = 0;
86e9c71fab30fd1d5b163c8a072f9e2d3eb8ba3a92Behdad Esfahbod
870594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return true;
880fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod}
890fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
90bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
91027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
92027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper face data
93027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
9471388b3ee71c7d3b79f842db7588bd683691797cBehdad Esfahbod
95027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodstruct hb_uniscribe_shaper_face_data_t {
96bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HANDLE fh;
97027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod};
98bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
99027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodhb_uniscribe_shaper_face_data_t *
100027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_face_data_create (hb_face_t *face)
101bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
102027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  hb_uniscribe_shaper_face_data_t *data = (hb_uniscribe_shaper_face_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_face_data_t));
103bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (unlikely (!data))
104027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
105a3bd8a0e1862212a2d4141b973039bd000a3054fBehdad Esfahbod
106bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  hb_blob_t *blob = hb_face_reference_blob (face);
107bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  unsigned int blob_length;
108bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  const char *blob_data = hb_blob_get_data (blob, &blob_length);
109bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (unlikely (!blob_length))
110bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, face, "Face has empty blob");
111bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
112bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  DWORD num_fonts_installed;
113bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  data->fh = AddFontMemResourceEx ((void *) blob_data, blob_length, 0, &num_fonts_installed);
114bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  hb_blob_destroy (blob);
115027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!data->fh)) {
116bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed");
117027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    free (data);
118027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
119bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  }
120bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
121bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  return data;
122bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod}
123bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
124027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodvoid
125027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_shaper_face_data_t *data)
126027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod{
127027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (data->fh)
128027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    RemoveFontMemResourceEx (data->fh);
129027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  free (data);
130027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
131bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
132027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
133027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
134027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper font data
135027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
136027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
137027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodstruct hb_uniscribe_shaper_font_data_t {
138bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HDC hdc;
139d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  LOGFONTW log_font;
140bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HFONT hfont;
141bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  SCRIPT_CACHE script_cache;
142027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod};
143bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
144027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodhb_uniscribe_shaper_font_data_t *
145027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_font_data_create (hb_font_t *font)
146027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod{
147027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  hb_uniscribe_shaper_font_data_t * data = (hb_uniscribe_shaper_font_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_font_data_t));
148027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!data))
149027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
150027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
151027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  data->hdc = GetDC (NULL);
152027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
153027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!populate_log_font (&data->log_font, font))) {
154027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, font, "Font populate_log_font() failed");
155027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    _hb_uniscribe_shaper_font_data_destroy (data);
156027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
157027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  }
158027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
159027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  data->hfont = CreateFontIndirectW (&data->log_font);
160027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!data->hfont)) {
161027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, font, "Font CreateFontIndirectW() failed");
162027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    _hb_uniscribe_shaper_font_data_destroy (data);
163027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod     return NULL;
164027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  }
165027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
166027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (!SelectObject (data->hdc, data->hfont)) {
167027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, font, "Font SelectObject() failed");
168027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    _hb_uniscribe_shaper_font_data_destroy (data);
169027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod     return NULL;
170027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  }
171027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
172027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  return data;
173027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
174027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
175027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodvoid
176027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_shaper_font_data_t *data)
177bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
178bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->hdc)
179bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    ReleaseDC (NULL, data->hdc);
180bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->hfont)
181bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DeleteObject (data->hfont);
182bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->script_cache)
183bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    ScriptFreeCache (&data->script_cache);
184bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  free (data);
185bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod}
186bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
187027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
188027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
189027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper shape_plan data
190027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
191027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
192027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodstruct hb_uniscribe_shaper_shape_plan_data_t {};
193027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
194027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodhb_uniscribe_shaper_shape_plan_data_t *
1955b95c148cc485f79fd7018bc4520b4cb5f728a18Behdad Esfahbod_hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan,
1965b95c148cc485f79fd7018bc4520b4cb5f728a18Behdad Esfahbod					     const hb_feature_t *user_features,
1975b95c148cc485f79fd7018bc4520b4cb5f728a18Behdad Esfahbod					     unsigned int        num_user_features)
198bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
199027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
200027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
201bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
202027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodvoid
203027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shaper_shape_plan_data_t *data)
204027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod{
205027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
206bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
207bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
208027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
209027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper
210027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
211027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodstatic hb_user_data_key_t hb_uniscribe_data_key;
212027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
213027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodstatic hb_uniscribe_shaper_face_data_t *
214027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_face_get_data (hb_face_t *face)
215027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod{
216027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  hb_uniscribe_shaper_face_data_t *data = (hb_uniscribe_shaper_face_data_t *) hb_face_get_user_data (face, &hb_uniscribe_data_key);
217027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (likely (data)) return data;
218027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
219027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  data = _hb_uniscribe_shaper_face_data_create (face);
220027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (!data) return NULL;
221027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
222027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!hb_face_set_user_data (face, &hb_uniscribe_data_key, data,
223027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod					(hb_destroy_func_t) _hb_uniscribe_shaper_face_data_destroy,
224027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod					false)))
225027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  {
226027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    _hb_uniscribe_shaper_face_data_destroy (data);
227027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    data = (hb_uniscribe_shaper_face_data_t *) hb_face_get_user_data (face, &hb_uniscribe_data_key);
228bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  }
229bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
230027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  return data;
231027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
232027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
233027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
234027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodstatic hb_uniscribe_shaper_font_data_t *
235027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_font_get_data (hb_font_t *font)
236027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod{
237027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  hb_uniscribe_shaper_font_data_t *data = (hb_uniscribe_shaper_font_data_t *) hb_font_get_user_data (font, &hb_uniscribe_data_key);
238027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (likely (data)) return data;
239027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
240027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  data = _hb_uniscribe_shaper_font_data_create (font);
241027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!data))
242027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
243027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
2445072934c35bddc23d6bcb07a41010da51eb1b090Behdad Esfahbod  if (unlikely (!hb_font_set_user_data (font, &hb_uniscribe_data_key, data,
245027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod					(hb_destroy_func_t) _hb_uniscribe_shaper_font_data_destroy,
2460594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod					false)))
247bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  {
248027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    _hb_uniscribe_shaper_font_data_destroy (data);
249027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    data = (hb_uniscribe_shaper_font_data_t *) hb_font_get_user_data (font, &hb_uniscribe_data_key);
250bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  }
251bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
252bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  return data;
253bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod}
254bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
255d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad EsfahbodLOGFONTW *
256d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbodhb_uniscribe_font_get_logfontw (hb_font_t *font)
257d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod{
258027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  hb_uniscribe_shaper_font_data_t *font_data = _hb_uniscribe_font_get_data (font);
259d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  if (unlikely (!font_data))
260d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod    return NULL;
261d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  return &font_data->log_font;
262d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod}
263d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod
264d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad EsfahbodHFONT
265d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbodhb_uniscribe_font_get_hfont (hb_font_t *font)
266d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod{
267027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  hb_uniscribe_shaper_font_data_t *font_data = _hb_uniscribe_font_get_data (font);
268d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  if (unlikely (!font_data))
269d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod    return 0;
270d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  return font_data->hfont;
271d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod}
272d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod
273bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
27402aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbodhb_bool_t
275bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod_hb_uniscribe_shape (hb_shape_plan_t    *shape_plan,
276bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod		     hb_font_t          *font,
2776bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod		     hb_buffer_t        *buffer,
2786bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod		     const hb_feature_t *features,
2796bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod		     unsigned int        num_features)
2800fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod{
28102aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod  buffer->guess_properties ();
28202aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod
283bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod#define FAIL(...) \
284bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HB_STMT_START { \
285bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \
2860594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false; \
287bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  } HB_STMT_END;
288bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
289027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  hb_uniscribe_shaper_face_data_t *face_data = _hb_uniscribe_face_get_data (font->face);
290a9057eb3f38018faa1ece53c4aaeeba798b41fd1Behdad Esfahbod  if (unlikely (!face_data->fh))
291bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    FAIL ("Couldn't get face data");
292bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
293027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  hb_uniscribe_shaper_font_data_t *font_data = _hb_uniscribe_font_get_data (font);
294a9057eb3f38018faa1ece53c4aaeeba798b41fd1Behdad Esfahbod  if (unlikely (!font_data->hfont))
295bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    FAIL ("Couldn't get font font");
2960fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
29702aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod  if (unlikely (!buffer->len))
2980594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return true;
2990fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
300bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HRESULT hr;
301bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
3020fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodretry:
3030fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3040fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int scratch_size;
3050fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
3060fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3070fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Allocate char buffers; they all fit */
3080fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3090fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define ALLOCATE_ARRAY(Type, name, len) \
3100fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  Type *name = (Type *) scratch; \
31191e721ea8693205f4f738bca97a5055ee75cf463Behdad Esfahbod  scratch += (len) * sizeof ((name)[0]); \
31291e721ea8693205f4f738bca97a5055ee75cf463Behdad Esfahbod  scratch_size -= (len) * sizeof ((name)[0]);
3130fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3140fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define utf16_index() var1.u32
3150fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3160fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  WCHAR *pchars = (WCHAR *) scratch;
3170fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int chars_len = 0;
3180fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < buffer->len; i++) {
3190fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    hb_codepoint_t c = buffer->info[i].codepoint;
3200fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    buffer->info[i].utf16_index() = chars_len;
3210fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    if (likely (c < 0x10000))
3220fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = c;
3230fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    else if (unlikely (c >= 0x110000))
3240fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = 0xFFFD;
3250fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    else {
3260fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10);
3270fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1));
3280fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    }
3290fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
3300fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3310fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (WCHAR, wchars, chars_len);
3320fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (WORD, log_clusters, chars_len);
3330fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (SCRIPT_CHARPROP, char_props, chars_len);
3340fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3350fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* On Windows, we don't care about alignment...*/
3360fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int glyphs_size = scratch_size / (sizeof (WORD) +
3370fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (SCRIPT_GLYPHPROP) +
3380fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (int) +
3390fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (GOFFSET) +
3400fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (uint32_t));
3410fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3420fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (WORD, glyphs, glyphs_size);
3430fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size);
3440fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (int, advances, glyphs_size);
3450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size);
3460fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
3470fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
34891e721ea8693205f4f738bca97a5055ee75cf463Behdad Esfahbod#undef ALLOCATE_ARRAY
3490fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
350872969126756456a69bf958f3df6e56a26e57b0aBehdad Esfahbod#define MAX_ITEMS 256
3510fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3520fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  SCRIPT_ITEM items[MAX_ITEMS + 1];
3535c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  SCRIPT_CONTROL bidi_control = {0};
3540fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  SCRIPT_STATE bidi_state = {0};
355b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod  WIN_ULONG script_tags[MAX_ITEMS];
3560fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  int item_count;
3570fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3585c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  /* MinGW32 doesn't define fMergeNeutralItems, so we bruteforce */
3590594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  //bidi_control.fMergeNeutralItems = true;
3605c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  *(uint32_t*)&bidi_control |= 1<<24;
3615c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod
3620fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
36329eac8f591fdb86f1c4fdc0a6ab63910ff286b84Behdad Esfahbod  bidi_state.fOverrideDirection = 1;
3640fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3650fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  hr = ScriptItemizeOpenType (wchars,
3660fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      chars_len,
3670fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      MAX_ITEMS,
3685c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod			      &bidi_control,
3690fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      &bidi_state,
3700fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      items,
3710fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      script_tags,
3720fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      &item_count);
3730fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  if (unlikely (FAILED (hr)))
3742eb474afb4a09f4da8f14b444bd6066769010224Behdad Esfahbod    FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr);
3750fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3760fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#undef MAX_ITEMS
3770fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3780fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  int *range_char_counts = NULL;
3790fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  TEXTRANGE_PROPERTIES **range_properties = NULL;
3800fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  int range_count = 0;
3810fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  if (num_features) {
3825c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod    /* TODO setup ranges */
3830fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
3840fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
385fcd6f5326166e993b8f5222efbaffe916da98f0aBehdad Esfahbod  OPENTYPE_TAG language_tag = hb_uint32_swap (hb_ot_tag_from_language (buffer->props.language));
3860fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3870fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int glyphs_offset = 0;
3880fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int glyphs_len;
389b069c3c31bfbbf160eb897c7474be9ea90ed4fc1Behdad Esfahbod  bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
390b069c3c31bfbbf160eb897c7474be9ea90ed4fc1Behdad Esfahbod  for (unsigned int j = 0; j < item_count; j++)
3910fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  {
3920dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    unsigned int i = backward ? item_count - 1 - j : j;
3930dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    unsigned int chars_offset = items[i].iCharPos;
3940dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;
3950dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
396e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod  retry_shape:
3970dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    hr = ScriptShapeOpenType (font_data->hdc,
3980dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      &font_data->script_cache,
3990dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      &items[i].a,
400e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod			      script_tags[i],
4010dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      language_tag,
4020dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_char_counts,
4030dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_properties,
4040dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_count,
4050dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      wchars + chars_offset,
4060dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      item_chars_len,
4070dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyphs_size - glyphs_offset,
4080dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      /* out */
4090dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      log_clusters + chars_offset,
4100dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      char_props + chars_offset,
4110dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyphs + glyphs_offset,
4120dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyph_props + glyphs_offset,
4130dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      (int *) &glyphs_len);
4140dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
4150dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (items[i].a.fNoGlyphIndex))
4160dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
4170dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (hr == E_OUTOFMEMORY))
4180dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    {
4190dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      buffer->ensure (buffer->allocated * 2);
4200dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      if (buffer->in_error)
4210dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod	FAIL ("Buffer resize failed");
4220dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      goto retry;
4230dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    }
4240dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (hr == USP_E_SCRIPT_NOT_IN_FONT))
425e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    {
426e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      if (items[i].a.eScript == SCRIPT_UNDEFINED)
427e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod	FAIL ("ScriptShapeOpenType() failed: Font doesn't support script");
428e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      items[i].a.eScript = SCRIPT_UNDEFINED;
429e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      goto retry_shape;
430e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    }
4310dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (FAILED (hr)))
432e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    {
4330dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr);
434e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    }
435e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod
436e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
437e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      log_clusters[j] += glyphs_offset;
4380dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
4390dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    hr = ScriptPlaceOpenType (font_data->hdc,
4400dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      &font_data->script_cache,
4410dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      &items[i].a,
442e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod			      script_tags[i],
4430dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      language_tag,
4440dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_char_counts,
4450dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_properties,
4460dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_count,
4470dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      wchars + chars_offset,
4480dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      log_clusters + chars_offset,
4490dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      char_props + chars_offset,
4500dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      item_chars_len,
4510dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyphs + glyphs_offset,
4520dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyph_props + glyphs_offset,
4530dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyphs_len,
4540dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      /* out */
4550dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      advances + glyphs_offset,
4560dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      offsets + glyphs_offset,
4570dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      NULL);
4580dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (FAILED (hr)))
4590dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);
4600dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
4610dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    glyphs_offset += glyphs_len;
4620fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
4630fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  glyphs_len = glyphs_offset;
4640fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4650fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Ok, we've got everything we need, now compose output buffer,
4660fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod   * very, *very*, carefully! */
4670fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4680fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Calculate visual-clusters.  That's what we ship. */
4695c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  for (unsigned int i = 0; i < glyphs_len; i++)
4705c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod    vis_clusters[i] = -1;
471577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod  for (unsigned int i = 0; i < buffer->len; i++) {
472577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod    uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
473577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod    *p = MIN (*p, buffer->info[i].cluster);
474577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod  }
475b069c3c31bfbbf160eb897c7474be9ea90ed4fc1Behdad Esfahbod  if (!backward) {
4765c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod    for (unsigned int i = 1; i < glyphs_len; i++)
4778e7beba7c3b3dea3cb3b7e280c5aab4f13b92d31Behdad Esfahbod      if (vis_clusters[i] == -1)
4785c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod	vis_clusters[i] = vis_clusters[i - 1];
4795c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  } else {
4805c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod    for (int i = glyphs_len - 2; i >= 0; i--)
4818e7beba7c3b3dea3cb3b7e280c5aab4f13b92d31Behdad Esfahbod      if (vis_clusters[i] == -1)
4825c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod	vis_clusters[i] = vis_clusters[i + 1];
4835c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  }
4840fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4850fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#undef utf16_index
4860fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4870fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  buffer->ensure (glyphs_len);
4880fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  if (buffer->in_error)
48902aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod    FAIL ("Buffer in error");
4900fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
49102aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod#undef FAIL
4920fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4930fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Set glyph infos */
494d753ac78da5619a0a545cdaf7a8e65787e996570Behdad Esfahbod  buffer->len = 0;
4950fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < glyphs_len; i++)
4960fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  {
497d753ac78da5619a0a545cdaf7a8e65787e996570Behdad Esfahbod    hb_glyph_info_t *info = &buffer->info[buffer->len++];
4980fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4990fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->codepoint = glyphs[i];
5000fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->cluster = vis_clusters[i];
5010fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
5020fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    /* The rest is crap.  Let's store position info there for now. */
5030fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->mask = advances[i];
5040fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->var1.u32 = offsets[i].du;
5050fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->var2.u32 = offsets[i].dv;
5060fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
5070fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
5080fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Set glyph positions */
5090fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  buffer->clear_positions ();
5100fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < glyphs_len; i++)
5110fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  {
5120fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    hb_glyph_info_t *info = &buffer->info[i];
5130fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    hb_glyph_position_t *pos = &buffer->pos[i];
5140fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
5150fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    /* TODO vertical */
5160fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    pos->x_advance = info->mask;
5170fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    pos->x_offset = info->var1.u32;
5180fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    pos->y_offset = info->var2.u32;
5190fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
5200fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
5210fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Wow, done! */
5220594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return true;
5230fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod}
5240fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
5250fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
526