hb-uniscribe.cc revision eb56f6ae96260c5b4bcd4e1dfb7ab733a230f3a8
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
28eb56f6ae96260c5b4bcd4e1dfb7ab733a230f3a8Behdad Esfahbod#define WIN32_LEAN_AND_MEAN
290fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
30027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod#define HB_SHAPER uniscribe
31027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod#include "hb-shaper-impl-private.hh"
320fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
33b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod#include <windows.h>
34b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod#include <usp10.h>
35b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod
36b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbodtypedef ULONG WIN_ULONG;
37b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod
380fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "hb-uniscribe.h"
390fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
407a750ac33ec482e2c4856c19ea607f3563741c24Behdad Esfahbod#include "hb-ot-name-table.hh"
410fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#include "hb-ot-tag.h"
420fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
430fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
440fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#ifndef HB_DEBUG_UNISCRIBE
450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
460fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#endif
470fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
480fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
490fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod/*
500fbb2dc83132a89201ad8b56c6909610437d2da0Behdad EsfahbodDWORD GetFontData(
510fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   HDC hdc,
520fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   DWORD dwTable,
530fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   DWORD dwOffset,
540fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __out  LPVOID lpvBuffer,
550fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   DWORD cbData
560fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod);
570fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod*/
580fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
59bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
60cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, face)
61cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, font)
62cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad Esfahbod
63cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad Esfahbod
64027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
65027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper face data
66027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
6771388b3ee71c7d3b79f842db7588bd683691797cBehdad Esfahbod
68027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodstruct hb_uniscribe_shaper_face_data_t {
69bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HANDLE fh;
70027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod};
71bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
72027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodhb_uniscribe_shaper_face_data_t *
73027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_face_data_create (hb_face_t *face)
74bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
75027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  hb_uniscribe_shaper_face_data_t *data = (hb_uniscribe_shaper_face_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_face_data_t));
76bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (unlikely (!data))
77027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
78a3bd8a0e1862212a2d4141b973039bd000a3054fBehdad Esfahbod
79bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  hb_blob_t *blob = hb_face_reference_blob (face);
80bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  unsigned int blob_length;
81bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  const char *blob_data = hb_blob_get_data (blob, &blob_length);
82bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (unlikely (!blob_length))
83bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, face, "Face has empty blob");
84bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
85bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  DWORD num_fonts_installed;
86bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  data->fh = AddFontMemResourceEx ((void *) blob_data, blob_length, 0, &num_fonts_installed);
87bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  hb_blob_destroy (blob);
88027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!data->fh)) {
89bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed");
90027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    free (data);
91027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
92bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  }
93bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
94bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  return data;
95bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod}
96bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
97027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodvoid
98027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_shaper_face_data_t *data)
99027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod{
100713914d3203109a8e9213f5a1d3b384730703ce9Behdad Esfahbod  RemoveFontMemResourceEx (data->fh);
101027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  free (data);
102027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
103bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
104027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
105027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
106027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper font data
107027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
108027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
109027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodstruct hb_uniscribe_shaper_font_data_t {
110bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HDC hdc;
111d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  LOGFONTW log_font;
112bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HFONT hfont;
113bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  SCRIPT_CACHE script_cache;
114027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod};
115bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
116b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbodstatic bool
117b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbodpopulate_log_font (LOGFONTW  *lf,
118b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod		   hb_font_t *font)
119b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod{
120b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  memset (lf, 0, sizeof (*lf));
121b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  lf->lfHeight = -font->y_scale;
122b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  lf->lfCharSet = DEFAULT_CHARSET;
123b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod
124b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  hb_blob_t *blob = Sanitizer<name>::sanitize (hb_face_reference_table (font->face, HB_TAG ('n','a','m','e')));
125b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  const name *name_table = Sanitizer<name>::lock_instance (blob);
126b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  unsigned int len = name_table->get_name (3, 1, 0x409, 4,
127b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod					   lf->lfFaceName,
128b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod					   sizeof (lf->lfFaceName[0]) * LF_FACESIZE)
129b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod					  / sizeof (lf->lfFaceName[0]);
130b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  hb_blob_destroy (blob);
131b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod
132b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  if (unlikely (!len)) {
133b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, NULL, "Didn't find English name table entry");
134b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod    return false;
135b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  }
136b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  if (unlikely (len >= LF_FACESIZE)) {
137b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, NULL, "Font name too long");
138b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod    return false;
139b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  }
140b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod
141b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  for (unsigned int i = 0; i < len; i++)
142b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod    lf->lfFaceName[i] = hb_be_uint16 (lf->lfFaceName[i]);
143b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  lf->lfFaceName[len] = 0;
144b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod
145b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  return true;
146b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod}
147b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod
148027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodhb_uniscribe_shaper_font_data_t *
149027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_font_data_create (hb_font_t *font)
150027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod{
151713914d3203109a8e9213f5a1d3b384730703ce9Behdad Esfahbod  if (unlikely (!hb_uniscribe_shaper_face_data_ensure (font->face))) return NULL;
152713914d3203109a8e9213f5a1d3b384730703ce9Behdad Esfahbod
153e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod  hb_uniscribe_shaper_font_data_t *data = (hb_uniscribe_shaper_font_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_font_data_t));
154027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!data))
155027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
156027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
157027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  data->hdc = GetDC (NULL);
158027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
159027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!populate_log_font (&data->log_font, font))) {
160027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, font, "Font populate_log_font() failed");
161027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    _hb_uniscribe_shaper_font_data_destroy (data);
162027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
163027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  }
164027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
165027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  data->hfont = CreateFontIndirectW (&data->log_font);
166027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!data->hfont)) {
167027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, font, "Font CreateFontIndirectW() failed");
168027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    _hb_uniscribe_shaper_font_data_destroy (data);
169027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod     return NULL;
170027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  }
171027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
172027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (!SelectObject (data->hdc, data->hfont)) {
173027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, font, "Font SelectObject() failed");
174027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    _hb_uniscribe_shaper_font_data_destroy (data);
175027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod     return NULL;
176027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  }
177027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
178027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  return data;
179027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
180027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
181027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodvoid
182027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_shaper_font_data_t *data)
183bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
184bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->hdc)
185bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    ReleaseDC (NULL, data->hdc);
186bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->hfont)
187bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DeleteObject (data->hfont);
188bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->script_cache)
189bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    ScriptFreeCache (&data->script_cache);
190bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  free (data);
191bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod}
192bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
193027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
194027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
195027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper shape_plan data
196027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
197027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
198027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodstruct hb_uniscribe_shaper_shape_plan_data_t {};
199027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
200027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodhb_uniscribe_shaper_shape_plan_data_t *
2015b95c148cc485f79fd7018bc4520b4cb5f728a18Behdad Esfahbod_hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan,
2025b95c148cc485f79fd7018bc4520b4cb5f728a18Behdad Esfahbod					     const hb_feature_t *user_features,
2035b95c148cc485f79fd7018bc4520b4cb5f728a18Behdad Esfahbod					     unsigned int        num_user_features)
204bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
205027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
206027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
207bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
208027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodvoid
209027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shaper_shape_plan_data_t *data)
210027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod{
211027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
212bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
213bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
214027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
215027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper
216027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
217bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
218d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad EsfahbodLOGFONTW *
219d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbodhb_uniscribe_font_get_logfontw (hb_font_t *font)
220d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod{
221713914d3203109a8e9213f5a1d3b384730703ce9Behdad Esfahbod  if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return NULL;
222a00ad60bc0fe74bf0e11d73da563239f3392f351Behdad Esfahbod    return NULL;
223b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  hb_uniscribe_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
224d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  return &font_data->log_font;
225d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod}
226d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod
227d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad EsfahbodHFONT
228d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbodhb_uniscribe_font_get_hfont (hb_font_t *font)
229d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod{
230713914d3203109a8e9213f5a1d3b384730703ce9Behdad Esfahbod  if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return NULL;
231b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  hb_uniscribe_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
232d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  return font_data->hfont;
233d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod}
234d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod
235bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
23602aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbodhb_bool_t
237bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod_hb_uniscribe_shape (hb_shape_plan_t    *shape_plan,
238bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod		     hb_font_t          *font,
2396bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod		     hb_buffer_t        *buffer,
2406bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod		     const hb_feature_t *features,
2416bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod		     unsigned int        num_features)
2420fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod{
243b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  hb_face_t *face = font->face;
244b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
245b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
24602aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod
247bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod#define FAIL(...) \
248bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HB_STMT_START { \
249bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \
2500594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false; \
251bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  } HB_STMT_END;
252bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
253bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HRESULT hr;
254bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
2550fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodretry:
2560fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2570fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int scratch_size;
2580fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
2590fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2600fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Allocate char buffers; they all fit */
2610fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2620fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define ALLOCATE_ARRAY(Type, name, len) \
2630fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  Type *name = (Type *) scratch; \
26491e721ea8693205f4f738bca97a5055ee75cf463Behdad Esfahbod  scratch += (len) * sizeof ((name)[0]); \
26591e721ea8693205f4f738bca97a5055ee75cf463Behdad Esfahbod  scratch_size -= (len) * sizeof ((name)[0]);
2660fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2670fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define utf16_index() var1.u32
2680fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2690fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  WCHAR *pchars = (WCHAR *) scratch;
2700fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int chars_len = 0;
2710fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < buffer->len; i++) {
2720fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    hb_codepoint_t c = buffer->info[i].codepoint;
2730fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    buffer->info[i].utf16_index() = chars_len;
2740fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    if (likely (c < 0x10000))
2750fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = c;
2760fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    else if (unlikely (c >= 0x110000))
2770fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = 0xFFFD;
2780fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    else {
2790fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10);
2800fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1));
2810fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    }
2820fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
2830fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2840fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (WCHAR, wchars, chars_len);
2850fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (WORD, log_clusters, chars_len);
2860fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (SCRIPT_CHARPROP, char_props, chars_len);
2870fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2880fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* On Windows, we don't care about alignment...*/
2890fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int glyphs_size = scratch_size / (sizeof (WORD) +
2900fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (SCRIPT_GLYPHPROP) +
2910fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (int) +
2920fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (GOFFSET) +
2930fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (uint32_t));
2940fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2950fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (WORD, glyphs, glyphs_size);
2960fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size);
2970fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (int, advances, glyphs_size);
2980fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size);
2990fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
3000fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
30191e721ea8693205f4f738bca97a5055ee75cf463Behdad Esfahbod#undef ALLOCATE_ARRAY
3020fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
303872969126756456a69bf958f3df6e56a26e57b0aBehdad Esfahbod#define MAX_ITEMS 256
3040fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3050fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  SCRIPT_ITEM items[MAX_ITEMS + 1];
3065c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  SCRIPT_CONTROL bidi_control = {0};
3070fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  SCRIPT_STATE bidi_state = {0};
308b492299eb3c398701557e452f6c2c9bd370fbbf3Behdad Esfahbod  WIN_ULONG script_tags[MAX_ITEMS];
3090fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  int item_count;
3100fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3115c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  /* MinGW32 doesn't define fMergeNeutralItems, so we bruteforce */
3120594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  //bidi_control.fMergeNeutralItems = true;
3135c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  *(uint32_t*)&bidi_control |= 1<<24;
3145c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod
3150fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
31629eac8f591fdb86f1c4fdc0a6ab63910ff286b84Behdad Esfahbod  bidi_state.fOverrideDirection = 1;
3170fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3180fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  hr = ScriptItemizeOpenType (wchars,
3190fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      chars_len,
3200fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      MAX_ITEMS,
3215c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod			      &bidi_control,
3220fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      &bidi_state,
3230fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      items,
3240fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      script_tags,
3250fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      &item_count);
3260fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  if (unlikely (FAILED (hr)))
3272eb474afb4a09f4da8f14b444bd6066769010224Behdad Esfahbod    FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr);
3280fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3290fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#undef MAX_ITEMS
3300fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3310fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  int *range_char_counts = NULL;
3320fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  TEXTRANGE_PROPERTIES **range_properties = NULL;
3330fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  int range_count = 0;
3340fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  if (num_features) {
3355c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod    /* TODO setup ranges */
3360fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
3370fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
338fcd6f5326166e993b8f5222efbaffe916da98f0aBehdad Esfahbod  OPENTYPE_TAG language_tag = hb_uint32_swap (hb_ot_tag_from_language (buffer->props.language));
3390fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3400fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int glyphs_offset = 0;
3410fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int glyphs_len;
342b069c3c31bfbbf160eb897c7474be9ea90ed4fc1Behdad Esfahbod  bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
343b069c3c31bfbbf160eb897c7474be9ea90ed4fc1Behdad Esfahbod  for (unsigned int j = 0; j < item_count; j++)
3440fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  {
3450dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    unsigned int i = backward ? item_count - 1 - j : j;
3460dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    unsigned int chars_offset = items[i].iCharPos;
3470dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;
3480dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
349e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod  retry_shape:
3500dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    hr = ScriptShapeOpenType (font_data->hdc,
3510dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      &font_data->script_cache,
3520dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      &items[i].a,
353e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod			      script_tags[i],
3540dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      language_tag,
3550dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_char_counts,
3560dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_properties,
3570dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_count,
3580dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      wchars + chars_offset,
3590dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      item_chars_len,
3600dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyphs_size - glyphs_offset,
3610dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      /* out */
3620dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      log_clusters + chars_offset,
3630dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      char_props + chars_offset,
3640dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyphs + glyphs_offset,
3650dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyph_props + glyphs_offset,
3660dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      (int *) &glyphs_len);
3670dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
3680dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (items[i].a.fNoGlyphIndex))
3690dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
3700dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (hr == E_OUTOFMEMORY))
3710dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    {
3720dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      buffer->ensure (buffer->allocated * 2);
3730dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      if (buffer->in_error)
3740dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod	FAIL ("Buffer resize failed");
3750dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      goto retry;
3760dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    }
3770dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (hr == USP_E_SCRIPT_NOT_IN_FONT))
378e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    {
379e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      if (items[i].a.eScript == SCRIPT_UNDEFINED)
380e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod	FAIL ("ScriptShapeOpenType() failed: Font doesn't support script");
381e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      items[i].a.eScript = SCRIPT_UNDEFINED;
382e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      goto retry_shape;
383e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    }
3840dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (FAILED (hr)))
385e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    {
3860dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr);
387e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    }
388e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod
389e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
390e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      log_clusters[j] += glyphs_offset;
3910dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
3920dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    hr = ScriptPlaceOpenType (font_data->hdc,
3930dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      &font_data->script_cache,
3940dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      &items[i].a,
395e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod			      script_tags[i],
3960dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      language_tag,
3970dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_char_counts,
3980dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_properties,
3990dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_count,
4000dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      wchars + chars_offset,
4010dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      log_clusters + chars_offset,
4020dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      char_props + chars_offset,
4030dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      item_chars_len,
4040dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyphs + glyphs_offset,
4050dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyph_props + glyphs_offset,
4060dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyphs_len,
4070dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      /* out */
4080dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      advances + glyphs_offset,
4090dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      offsets + glyphs_offset,
4100dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      NULL);
4110dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (FAILED (hr)))
4120dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);
4130dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
4140dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    glyphs_offset += glyphs_len;
4150fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
4160fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  glyphs_len = glyphs_offset;
4170fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4180fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Ok, we've got everything we need, now compose output buffer,
4190fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod   * very, *very*, carefully! */
4200fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4210fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Calculate visual-clusters.  That's what we ship. */
4225c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  for (unsigned int i = 0; i < glyphs_len; i++)
4235c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod    vis_clusters[i] = -1;
424577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod  for (unsigned int i = 0; i < buffer->len; i++) {
425577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod    uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
426577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod    *p = MIN (*p, buffer->info[i].cluster);
427577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod  }
428b069c3c31bfbbf160eb897c7474be9ea90ed4fc1Behdad Esfahbod  if (!backward) {
4295c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod    for (unsigned int i = 1; i < glyphs_len; i++)
4308e7beba7c3b3dea3cb3b7e280c5aab4f13b92d31Behdad Esfahbod      if (vis_clusters[i] == -1)
4315c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod	vis_clusters[i] = vis_clusters[i - 1];
4325c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  } else {
4335c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod    for (int i = glyphs_len - 2; i >= 0; i--)
4348e7beba7c3b3dea3cb3b7e280c5aab4f13b92d31Behdad Esfahbod      if (vis_clusters[i] == -1)
4355c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod	vis_clusters[i] = vis_clusters[i + 1];
4365c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  }
4370fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4380fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#undef utf16_index
4390fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4400fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  buffer->ensure (glyphs_len);
4410fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  if (buffer->in_error)
44202aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod    FAIL ("Buffer in error");
4430fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
44402aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod#undef FAIL
4450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4460fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Set glyph infos */
447d753ac78da5619a0a545cdaf7a8e65787e996570Behdad Esfahbod  buffer->len = 0;
4480fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < glyphs_len; i++)
4490fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  {
450d753ac78da5619a0a545cdaf7a8e65787e996570Behdad Esfahbod    hb_glyph_info_t *info = &buffer->info[buffer->len++];
4510fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4520fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->codepoint = glyphs[i];
4530fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->cluster = vis_clusters[i];
4540fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4550fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    /* The rest is crap.  Let's store position info there for now. */
4560fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->mask = advances[i];
4570fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->var1.u32 = offsets[i].du;
4580fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->var2.u32 = offsets[i].dv;
4590fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
4600fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4610fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Set glyph positions */
4620fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  buffer->clear_positions ();
4630fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < glyphs_len; i++)
4640fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  {
4650fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    hb_glyph_info_t *info = &buffer->info[i];
4660fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    hb_glyph_position_t *pos = &buffer->pos[i];
4670fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4680fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    /* TODO vertical */
4690fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    pos->x_advance = info->mask;
4700fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    pos->x_offset = info->var1.u32;
4710fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    pos->y_offset = info->var2.u32;
4720fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
4730fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4740fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Wow, done! */
4750594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return true;
4760fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod}
4770fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4780fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
479