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
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
420fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#ifndef HB_DEBUG_UNISCRIBE
430fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
440fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#endif
450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
460fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
470fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod/*
480fbb2dc83132a89201ad8b56c6909610437d2da0Behdad EsfahbodDWORD GetFontData(
490fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   HDC hdc,
500fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   DWORD dwTable,
510fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   DWORD dwOffset,
520fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __out  LPVOID lpvBuffer,
530fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  __in   DWORD cbData
540fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod);
550fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod*/
560fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
57bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
58cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, face)
59cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad EsfahbodHB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, font)
60cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad Esfahbod
61cfe9882610489e1b917e09a74dfbf6bbba2e4a57Behdad Esfahbod
62027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
63027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper face data
64027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
6571388b3ee71c7d3b79f842db7588bd683691797cBehdad Esfahbod
66027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodstruct hb_uniscribe_shaper_face_data_t {
67bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HANDLE fh;
68027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod};
69bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
70027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodhb_uniscribe_shaper_face_data_t *
71027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_face_data_create (hb_face_t *face)
72bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
73027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  hb_uniscribe_shaper_face_data_t *data = (hb_uniscribe_shaper_face_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_face_data_t));
74bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (unlikely (!data))
75027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
76a3bd8a0e1862212a2d4141b973039bd000a3054fBehdad Esfahbod
77bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  hb_blob_t *blob = hb_face_reference_blob (face);
78bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  unsigned int blob_length;
79bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  const char *blob_data = hb_blob_get_data (blob, &blob_length);
80bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (unlikely (!blob_length))
81bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, face, "Face has empty blob");
82bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
83bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  DWORD num_fonts_installed;
84bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  data->fh = AddFontMemResourceEx ((void *) blob_data, blob_length, 0, &num_fonts_installed);
85bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  hb_blob_destroy (blob);
86027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!data->fh)) {
87bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed");
88027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    free (data);
89027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
90bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  }
91bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
92bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  return data;
93bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod}
94bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
95027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodvoid
96027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_shaper_face_data_t *data)
97027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod{
98713914d3203109a8e9213f5a1d3b384730703ce9Behdad Esfahbod  RemoveFontMemResourceEx (data->fh);
99027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  free (data);
100027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
101bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
102027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
103027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
104027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper font data
105027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
106027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
107027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodstruct hb_uniscribe_shaper_font_data_t {
108bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HDC hdc;
109d6660356dd81358033743f72d8a5fbf2fc70eaf7Behdad Esfahbod  LOGFONTW log_font;
110bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HFONT hfont;
111bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  SCRIPT_CACHE script_cache;
112027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod};
113bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
114b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbodstatic bool
115b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbodpopulate_log_font (LOGFONTW  *lf,
116b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod		   hb_font_t *font)
117b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod{
118b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  memset (lf, 0, sizeof (*lf));
119b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  lf->lfHeight = -font->y_scale;
120b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  lf->lfCharSet = DEFAULT_CHARSET;
121b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod
1227c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  hb_blob_t *blob = OT::Sanitizer<OT::name>::sanitize (hb_face_reference_table (font->face, HB_TAG ('n','a','m','e')));
1237c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  const OT::name *name_table = OT::Sanitizer<OT::name>::lock_instance (blob);
124b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  unsigned int len = name_table->get_name (3, 1, 0x409, 4,
125b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod					   lf->lfFaceName,
126b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod					   sizeof (lf->lfFaceName[0]) * LF_FACESIZE)
127b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod					  / sizeof (lf->lfFaceName[0]);
128b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  hb_blob_destroy (blob);
129b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod
130b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  if (unlikely (!len)) {
131b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, NULL, "Didn't find English name table entry");
132b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod    return false;
133b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  }
134b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  if (unlikely (len >= LF_FACESIZE)) {
135b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, NULL, "Font name too long");
136b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod    return false;
137b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  }
138b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod
139b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  for (unsigned int i = 0; i < len; i++)
140b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod    lf->lfFaceName[i] = hb_be_uint16 (lf->lfFaceName[i]);
141b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  lf->lfFaceName[len] = 0;
142b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod
143b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  return true;
144b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod}
145b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod
146027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodhb_uniscribe_shaper_font_data_t *
147027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_font_data_create (hb_font_t *font)
148027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod{
149713914d3203109a8e9213f5a1d3b384730703ce9Behdad Esfahbod  if (unlikely (!hb_uniscribe_shaper_face_data_ensure (font->face))) return NULL;
150713914d3203109a8e9213f5a1d3b384730703ce9Behdad Esfahbod
151e82061e8db922f0ddbefd5a184ee2f9f967b9a05Behdad Esfahbod  hb_uniscribe_shaper_font_data_t *data = (hb_uniscribe_shaper_font_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_font_data_t));
152027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!data))
153027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
154027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
155027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  data->hdc = GetDC (NULL);
156027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
157027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!populate_log_font (&data->log_font, font))) {
158027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, font, "Font populate_log_font() failed");
159027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    _hb_uniscribe_shaper_font_data_destroy (data);
160027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    return NULL;
161027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  }
162027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
163027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  data->hfont = CreateFontIndirectW (&data->log_font);
164027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (unlikely (!data->hfont)) {
165027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, font, "Font CreateFontIndirectW() failed");
166027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    _hb_uniscribe_shaper_font_data_destroy (data);
167027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod     return NULL;
168027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  }
169027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
170027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  if (!SelectObject (data->hdc, data->hfont)) {
171027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, font, "Font SelectObject() failed");
172027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod    _hb_uniscribe_shaper_font_data_destroy (data);
173027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod     return NULL;
174027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  }
175027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
176027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  return data;
177027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
178027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
179027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodvoid
180027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod_hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_shaper_font_data_t *data)
181bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
182bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->hdc)
183bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    ReleaseDC (NULL, data->hdc);
184bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->hfont)
185bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DeleteObject (data->hfont);
186bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  if (data->script_cache)
187bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    ScriptFreeCache (&data->script_cache);
188bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  free (data);
189bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod}
190bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
1910ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad EsfahbodLOGFONTW *
1920ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbodhb_uniscribe_font_get_logfontw (hb_font_t *font)
1930ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod{
1940ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod  if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return NULL;
1950ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod  hb_uniscribe_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
1960ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod  return &font_data->log_font;
1970ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod}
1980ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod
1990ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad EsfahbodHFONT
2000ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbodhb_uniscribe_font_get_hfont (hb_font_t *font)
2010ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod{
2020ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod  if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return NULL;
2030ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod  hb_uniscribe_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
2040ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod  return font_data->hfont;
2050ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod}
2060ae6dbf1b4de8a0326b8a2f201597427cecfb6dbBehdad Esfahbod
207027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
208027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
209027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper shape_plan data
210027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
211027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
212027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodstruct hb_uniscribe_shaper_shape_plan_data_t {};
213027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod
214027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodhb_uniscribe_shaper_shape_plan_data_t *
21545c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod_hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
21645c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod					     const hb_feature_t *user_features HB_UNUSED,
21745c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod					     unsigned int        num_user_features HB_UNUSED)
218bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod{
219027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod  return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
220027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
221bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
222027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbodvoid
22345c1383cc7315f89c23c0ed388b99e87224884e7Behdad Esfahbod_hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shaper_shape_plan_data_t *data HB_UNUSED)
224027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod{
225027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod}
226bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
227bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
228027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod/*
229027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod * shaper
230027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod */
231bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
232bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
23302aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbodhb_bool_t
234bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod_hb_uniscribe_shape (hb_shape_plan_t    *shape_plan,
235bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod		     hb_font_t          *font,
2366bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod		     hb_buffer_t        *buffer,
2376bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod		     const hb_feature_t *features,
2386bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod		     unsigned int        num_features)
2390fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod{
240b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  hb_face_t *face = font->face;
241b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
242b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
24302aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod
244bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod#define FAIL(...) \
245bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HB_STMT_START { \
246bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod    DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \
2470594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod    return false; \
248bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  } HB_STMT_END;
249bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
250bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod  HRESULT hr;
251bf3eef540f81fdeba1c36263d7d5b2ec4c5f07b1Behdad Esfahbod
2520fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbodretry:
2530fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2540fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int scratch_size;
2550fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size);
2560fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2570fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Allocate char buffers; they all fit */
2580fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2590fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define ALLOCATE_ARRAY(Type, name, len) \
2600fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  Type *name = (Type *) scratch; \
26191e721ea8693205f4f738bca97a5055ee75cf463Behdad Esfahbod  scratch += (len) * sizeof ((name)[0]); \
26291e721ea8693205f4f738bca97a5055ee75cf463Behdad Esfahbod  scratch_size -= (len) * sizeof ((name)[0]);
2630fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2640fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#define utf16_index() var1.u32
2650fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2660fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  WCHAR *pchars = (WCHAR *) scratch;
2670fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int chars_len = 0;
2680fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < buffer->len; i++) {
2690fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    hb_codepoint_t c = buffer->info[i].codepoint;
2700fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    buffer->info[i].utf16_index() = chars_len;
2710fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    if (likely (c < 0x10000))
2720fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = c;
2730fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    else if (unlikely (c >= 0x110000))
2740fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = 0xFFFD;
2750fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    else {
2760fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10);
2770fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod      pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1));
2780fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    }
2790fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
2800fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2810fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (WCHAR, wchars, chars_len);
2820fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (WORD, log_clusters, chars_len);
2830fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (SCRIPT_CHARPROP, char_props, chars_len);
2840fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2850fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* On Windows, we don't care about alignment...*/
2860fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int glyphs_size = scratch_size / (sizeof (WORD) +
2870fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (SCRIPT_GLYPHPROP) +
2880fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (int) +
2890fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (GOFFSET) +
2900fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod					     sizeof (uint32_t));
2910fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
2920fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (WORD, glyphs, glyphs_size);
2930fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size);
2940fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (int, advances, glyphs_size);
2950fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size);
2960fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);
2970fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
29891e721ea8693205f4f738bca97a5055ee75cf463Behdad Esfahbod#undef ALLOCATE_ARRAY
2990fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
300872969126756456a69bf958f3df6e56a26e57b0aBehdad Esfahbod#define MAX_ITEMS 256
3010fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3020fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  SCRIPT_ITEM items[MAX_ITEMS + 1];
3035c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  SCRIPT_CONTROL bidi_control = {0};
3040fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  SCRIPT_STATE bidi_state = {0};
3057c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod  ULONG script_tags[MAX_ITEMS];
3060fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  int item_count;
3070fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3085c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  /* MinGW32 doesn't define fMergeNeutralItems, so we bruteforce */
3090594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  //bidi_control.fMergeNeutralItems = true;
3105c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  *(uint32_t*)&bidi_control |= 1<<24;
3115c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod
3120fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
31329eac8f591fdb86f1c4fdc0a6ab63910ff286b84Behdad Esfahbod  bidi_state.fOverrideDirection = 1;
3140fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3150fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  hr = ScriptItemizeOpenType (wchars,
3160fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      chars_len,
3170fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      MAX_ITEMS,
3185c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod			      &bidi_control,
3190fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      &bidi_state,
3200fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      items,
3210fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      script_tags,
3220fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod			      &item_count);
3230fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  if (unlikely (FAILED (hr)))
3242eb474afb4a09f4da8f14b444bd6066769010224Behdad Esfahbod    FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr);
3250fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3260fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#undef MAX_ITEMS
3270fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3280fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  int *range_char_counts = NULL;
3290fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  TEXTRANGE_PROPERTIES **range_properties = NULL;
3300fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  int range_count = 0;
3310fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  if (num_features) {
3325c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod    /* TODO setup ranges */
3330fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
3340fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
335fcd6f5326166e993b8f5222efbaffe916da98f0aBehdad Esfahbod  OPENTYPE_TAG language_tag = hb_uint32_swap (hb_ot_tag_from_language (buffer->props.language));
3360fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
3370fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int glyphs_offset = 0;
3380fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  unsigned int glyphs_len;
339b069c3c31bfbbf160eb897c7474be9ea90ed4fc1Behdad Esfahbod  bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
340b069c3c31bfbbf160eb897c7474be9ea90ed4fc1Behdad Esfahbod  for (unsigned int j = 0; j < item_count; j++)
3410fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  {
3420dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    unsigned int i = backward ? item_count - 1 - j : j;
3430dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    unsigned int chars_offset = items[i].iCharPos;
3440dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;
3450dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
346e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod  retry_shape:
3470dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    hr = ScriptShapeOpenType (font_data->hdc,
3480dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      &font_data->script_cache,
3490dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      &items[i].a,
350e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod			      script_tags[i],
3510dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      language_tag,
3520dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_char_counts,
3530dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_properties,
3540dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_count,
3550dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      wchars + chars_offset,
3560dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      item_chars_len,
3570dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyphs_size - glyphs_offset,
3580dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      /* out */
3590dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      log_clusters + chars_offset,
3600dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      char_props + chars_offset,
3610dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyphs + glyphs_offset,
3620dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyph_props + glyphs_offset,
3630dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      (int *) &glyphs_len);
3640dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
3650dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (items[i].a.fNoGlyphIndex))
3660dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
3670dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (hr == E_OUTOFMEMORY))
3680dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    {
3690dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      buffer->ensure (buffer->allocated * 2);
3700dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      if (buffer->in_error)
3710dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod	FAIL ("Buffer resize failed");
3720dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      goto retry;
3730dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    }
3740dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (hr == USP_E_SCRIPT_NOT_IN_FONT))
375e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    {
376e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      if (items[i].a.eScript == SCRIPT_UNDEFINED)
377e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod	FAIL ("ScriptShapeOpenType() failed: Font doesn't support script");
378e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      items[i].a.eScript = SCRIPT_UNDEFINED;
379e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      goto retry_shape;
380e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    }
3810dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (FAILED (hr)))
382e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    {
3830dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr);
384e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    }
385e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod
386e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod    for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
387e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod      log_clusters[j] += glyphs_offset;
3880dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
3890dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    hr = ScriptPlaceOpenType (font_data->hdc,
3900dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      &font_data->script_cache,
3910dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      &items[i].a,
392e9c0f152a38cb2e76650a3e43f7fdcda266af696Behdad Esfahbod			      script_tags[i],
3930dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      language_tag,
3940dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_char_counts,
3950dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_properties,
3960dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      range_count,
3970dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      wchars + chars_offset,
3980dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      log_clusters + chars_offset,
3990dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      char_props + chars_offset,
4000dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      item_chars_len,
4010dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyphs + glyphs_offset,
4020dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyph_props + glyphs_offset,
4030dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      glyphs_len,
4040dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      /* out */
4050dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      advances + glyphs_offset,
4060dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      offsets + glyphs_offset,
4070dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod			      NULL);
4080dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    if (unlikely (FAILED (hr)))
4090dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod      FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);
4100dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod
4110dd86f9f6849d82d60a99e66b6928795cfb2a3c7Behdad Esfahbod    glyphs_offset += glyphs_len;
4120fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
4130fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  glyphs_len = glyphs_offset;
4140fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4150fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Ok, we've got everything we need, now compose output buffer,
4160fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod   * very, *very*, carefully! */
4170fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4180fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Calculate visual-clusters.  That's what we ship. */
4195c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  for (unsigned int i = 0; i < glyphs_len; i++)
4205c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod    vis_clusters[i] = -1;
421577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod  for (unsigned int i = 0; i < buffer->len; i++) {
422577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod    uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
423577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod    *p = MIN (*p, buffer->info[i].cluster);
424577326b86af80cc137eea81f4cc1e30adf9232b1Behdad Esfahbod  }
425b069c3c31bfbbf160eb897c7474be9ea90ed4fc1Behdad Esfahbod  if (!backward) {
4265c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod    for (unsigned int i = 1; i < glyphs_len; i++)
4278e7beba7c3b3dea3cb3b7e280c5aab4f13b92d31Behdad Esfahbod      if (vis_clusters[i] == -1)
4285c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod	vis_clusters[i] = vis_clusters[i - 1];
4295c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  } else {
4305c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod    for (int i = glyphs_len - 2; i >= 0; i--)
4318e7beba7c3b3dea3cb3b7e280c5aab4f13b92d31Behdad Esfahbod      if (vis_clusters[i] == -1)
4325c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod	vis_clusters[i] = vis_clusters[i + 1];
4335c299343118d1eaff32ffb2a5dac077cfff67deeBehdad Esfahbod  }
4340fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4350fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod#undef utf16_index
4360fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4370fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  buffer->ensure (glyphs_len);
4380fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  if (buffer->in_error)
43902aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod    FAIL ("Buffer in error");
4400fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
44102aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod#undef FAIL
4420fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4430fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Set glyph infos */
444d753ac78da5619a0a545cdaf7a8e65787e996570Behdad Esfahbod  buffer->len = 0;
4450fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < glyphs_len; i++)
4460fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  {
447d753ac78da5619a0a545cdaf7a8e65787e996570Behdad Esfahbod    hb_glyph_info_t *info = &buffer->info[buffer->len++];
4480fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4490fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->codepoint = glyphs[i];
4500fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->cluster = vis_clusters[i];
4510fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4520fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    /* The rest is crap.  Let's store position info there for now. */
4530fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->mask = advances[i];
4540fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->var1.u32 = offsets[i].du;
4550fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    info->var2.u32 = offsets[i].dv;
4560fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
4570fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4580fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Set glyph positions */
4590fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  buffer->clear_positions ();
4600fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  for (unsigned int i = 0; i < glyphs_len; i++)
4610fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  {
4620fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    hb_glyph_info_t *info = &buffer->info[i];
4630fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    hb_glyph_position_t *pos = &buffer->pos[i];
4640fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4650fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    /* TODO vertical */
4660fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    pos->x_advance = info->mask;
4670fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    pos->x_offset = info->var1.u32;
4680fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod    pos->y_offset = info->var2.u32;
4690fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  }
4700fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4710fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod  /* Wow, done! */
4720594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod  return true;
4730fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod}
4740fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
4750fbb2dc83132a89201ad8b56c6909610437d2da0Behdad Esfahbod
476