hb-uniscribe.cc 27.9 KB
Newer Older
1
/*
2
 * Copyright © 2011,2012,2013  Google, Inc.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 *  This is part of HarfBuzz, a text shaping library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Google Author(s): Behdad Esfahbod
 */

27
#define _WIN32_WINNT 0x0600
B
Minor  
Behdad Esfahbod 已提交
28
#define WIN32_LEAN_AND_MEAN
29

30 31
#define HB_SHAPER uniscribe
#include "hb-shaper-impl-private.hh"
32

33 34
#include <windows.h>
#include <usp10.h>
35
#include <rpc.h>
36

37 38
#include "hb-uniscribe.h"

39
#include "hb-open-file-private.hh"
40
#include "hb-ot-name-table.hh"
41 42 43 44 45 46 47 48
#include "hb-ot-tag.h"


#ifndef HB_DEBUG_UNISCRIBE
#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0)
#endif


49
typedef HRESULT (WINAPI *SIOT) /*ScriptItemizeOpenType*/(
50 51 52 53 54 55 56 57 58 59
  const WCHAR *pwcInChars,
  int cInChars,
  int cMaxItems,
  const SCRIPT_CONTROL *psControl,
  const SCRIPT_STATE *psState,
  SCRIPT_ITEM *pItems,
  OPENTYPE_TAG *pScriptTags,
  int *pcItems
);

60
typedef HRESULT (WINAPI *SSOT) /*ScriptShapeOpenType*/(
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
  HDC hdc,
  SCRIPT_CACHE *psc,
  SCRIPT_ANALYSIS *psa,
  OPENTYPE_TAG tagScript,
  OPENTYPE_TAG tagLangSys,
  int *rcRangeChars,
  TEXTRANGE_PROPERTIES **rpRangeProperties,
  int cRanges,
  const WCHAR *pwcChars,
  int cChars,
  int cMaxGlyphs,
  WORD *pwLogClust,
  SCRIPT_CHARPROP *pCharProps,
  WORD *pwOutGlyphs,
  SCRIPT_GLYPHPROP *pOutGlyphProps,
  int *pcGlyphs
77
);
78

79
typedef HRESULT (WINAPI *SPOT) /*ScriptPlaceOpenType*/(
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
  HDC hdc,
  SCRIPT_CACHE *psc,
  SCRIPT_ANALYSIS *psa,
  OPENTYPE_TAG tagScript,
  OPENTYPE_TAG tagLangSys,
  int *rcRangeChars,
  TEXTRANGE_PROPERTIES **rpRangeProperties,
  int cRanges,
  const WCHAR *pwcChars,
  WORD *pwLogClust,
  SCRIPT_CHARPROP *pCharProps,
  int cChars,
  const WORD *pwGlyphs,
  const SCRIPT_GLYPHPROP *pGlyphProps,
  int cGlyphs,
  int *piAdvance,
  GOFFSET *pGoffset,
  ABC *pABC
);


/* Fallback implementations. */

static HRESULT WINAPI
hb_ScriptItemizeOpenType(
  const WCHAR *pwcInChars,
  int cInChars,
  int cMaxItems,
  const SCRIPT_CONTROL *psControl,
  const SCRIPT_STATE *psState,
  SCRIPT_ITEM *pItems,
  OPENTYPE_TAG *pScriptTags,
  int *pcItems
)
{
{
  return ScriptItemize (pwcInChars,
			cInChars,
			cMaxItems,
			psControl,
			psState,
			pItems,
			pcItems);
}
}

static HRESULT WINAPI
hb_ScriptShapeOpenType(
  HDC hdc,
  SCRIPT_CACHE *psc,
  SCRIPT_ANALYSIS *psa,
  OPENTYPE_TAG tagScript,
  OPENTYPE_TAG tagLangSys,
  int *rcRangeChars,
  TEXTRANGE_PROPERTIES **rpRangeProperties,
  int cRanges,
  const WCHAR *pwcChars,
  int cChars,
  int cMaxGlyphs,
  WORD *pwLogClust,
  SCRIPT_CHARPROP *pCharProps,
  WORD *pwOutGlyphs,
  SCRIPT_GLYPHPROP *pOutGlyphProps,
  int *pcGlyphs
)
{
  SCRIPT_VISATTR *psva = (SCRIPT_VISATTR *) pOutGlyphProps;
  return ScriptShape (hdc,
		      psc,
		      pwcChars,
		      cChars,
		      cMaxGlyphs,
		      psa,
		      pwOutGlyphs,
		      pwLogClust,
		      psva,
		      pcGlyphs);
}

static HRESULT WINAPI
hb_ScriptPlaceOpenType(
  HDC hdc,
  SCRIPT_CACHE *psc,
  SCRIPT_ANALYSIS *psa,
  OPENTYPE_TAG tagScript,
  OPENTYPE_TAG tagLangSys,
  int *rcRangeChars,
  TEXTRANGE_PROPERTIES **rpRangeProperties,
  int cRanges,
  const WCHAR *pwcChars,
  WORD *pwLogClust,
  SCRIPT_CHARPROP *pCharProps,
  int cChars,
  const WORD *pwGlyphs,
  const SCRIPT_GLYPHPROP *pGlyphProps,
  int cGlyphs,
  int *piAdvance,
  GOFFSET *pGoffset,
  ABC *pABC
)
{
  SCRIPT_VISATTR *psva = (SCRIPT_VISATTR *) pGlyphProps;
  return ScriptPlace (hdc,
		      psc,
		      pwGlyphs,
		      cGlyphs,
		      psva,
		      psa,
		      piAdvance,
		      pGoffset,
		      pABC);
}


struct hb_uniscribe_shaper_funcs_t {
  SIOT ScriptItemizeOpenType;
  SSOT ScriptShapeOpenType;
  SPOT ScriptPlaceOpenType;

  inline void init (void)
  {
201
    HMODULE hinstLib;
202 203 204 205
    this->ScriptItemizeOpenType = NULL;
    this->ScriptShapeOpenType   = NULL;
    this->ScriptPlaceOpenType   = NULL;

206
    hinstLib = GetModuleHandle (TEXT ("usp10.dll"));
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
    if (hinstLib)
    {
      this->ScriptItemizeOpenType = (SIOT) GetProcAddress (hinstLib, "ScriptItemizeOpenType");
      this->ScriptShapeOpenType   = (SSOT) GetProcAddress (hinstLib, "ScriptShapeOpenType");
      this->ScriptPlaceOpenType   = (SPOT) GetProcAddress (hinstLib, "ScriptPlaceOpenType");
    }
    if (!this->ScriptItemizeOpenType ||
	!this->ScriptShapeOpenType   ||
	!this->ScriptPlaceOpenType)
    {
      DEBUG_MSG (UNISCRIBE, NULL, "OpenType versions of functions not found; falling back.");
      this->ScriptItemizeOpenType = hb_ScriptItemizeOpenType;
      this->ScriptShapeOpenType   = hb_ScriptShapeOpenType;
      this->ScriptPlaceOpenType   = hb_ScriptPlaceOpenType;
    }
  }
};
static hb_uniscribe_shaper_funcs_t *uniscribe_funcs;

static inline void
free_uniscribe_funcs (void)
{
  free (uniscribe_funcs);
}

static hb_uniscribe_shaper_funcs_t *
hb_uniscribe_shaper_get_funcs (void)
{
retry:
  hb_uniscribe_shaper_funcs_t *funcs = (hb_uniscribe_shaper_funcs_t *) hb_atomic_ptr_get (&uniscribe_funcs);

  if (unlikely (!funcs))
  {
    funcs = (hb_uniscribe_shaper_funcs_t *) calloc (1, sizeof (hb_uniscribe_shaper_funcs_t));
    if (unlikely (!funcs))
      return NULL;

    funcs->init ();

    if (!hb_atomic_ptr_cmpexch (&uniscribe_funcs, NULL, funcs)) {
      free (funcs);
      goto retry;
    }

#ifdef HAVE_ATEXIT
    atexit (free_uniscribe_funcs); /* First person registers atexit() callback. */
#endif
  }

  return funcs;
}
258

B
Behdad Esfahbod 已提交
259

260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
struct active_feature_t {
  OPENTYPE_FEATURE_RECORD rec;
  unsigned int order;

  static int cmp (const active_feature_t *a, const active_feature_t *b) {
    return a->rec.tagFeature < b->rec.tagFeature ? -1 : a->rec.tagFeature > b->rec.tagFeature ? 1 :
	   a->order < b->order ? -1 : a->order > b->order ? 1 :
	   a->rec.lParameter < b->rec.lParameter ? -1 : a->rec.lParameter > b->rec.lParameter ? 1 :
	   0;
  }
  bool operator== (const active_feature_t *f) {
    return cmp (this, f) == 0;
  }
};

struct feature_event_t {
  unsigned int index;
  bool start;
  active_feature_t feature;

  static int cmp (const feature_event_t *a, const feature_event_t *b) {
    return a->index < b->index ? -1 : a->index > b->index ? 1 :
	   a->start < b->start ? -1 : a->start > b->start ? 1 :
	   active_feature_t::cmp (&a->feature, &b->feature);
  }
};

struct range_record_t {
  TEXTRANGE_PROPERTIES props;
  unsigned int index_first; /* == start */
  unsigned int index_last;  /* == end - 1 */
};

293 294 295 296
HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, face)
HB_SHAPER_DATA_ENSURE_DECLARE(uniscribe, font)


297 298 299
/*
 * shaper face data
 */
B
Behdad Esfahbod 已提交
300

301
struct hb_uniscribe_shaper_face_data_t {
B
Behdad Esfahbod 已提交
302
  HANDLE fh;
303
  hb_uniscribe_shaper_funcs_t *funcs;
304
  wchar_t face_name[LF_FACESIZE];
305
};
B
Behdad Esfahbod 已提交
306

307 308 309
/* face_name should point to a wchar_t[LF_FACESIZE] object. */
static void
_hb_generate_unique_face_name (wchar_t *face_name, unsigned int *plen)
310 311 312 313 314 315 316
{
  /* We'll create a private name for the font from a UUID using a simple,
   * somewhat base64-like encoding scheme */
  const char *enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
  UUID id;
  UuidCreate ((UUID*) &id);
  unsigned int name_str_len = 0;
317 318
  face_name[name_str_len++] = 'F';
  face_name[name_str_len++] = '_';
319 320 321 322 323 324 325 326
  unsigned char *p = (unsigned char *) &id;
  for (unsigned int i = 0; i < 16; i += 2)
  {
    /* Spread the 16 bits from two bytes of the UUID across three chars of face_name,
     * using the bits in groups of 5,5,6 to select chars from enc.
     * This will generate 24 characters; with the 'F_' prefix we already provided,
     * the name will be 26 chars (plus the NUL terminator), so will always fit within
     * face_name (LF_FACESIZE = 32). */
327 328 329
    face_name[name_str_len++] = enc[p[i] >> 3];
    face_name[name_str_len++] = enc[((p[i] << 2) | (p[i + 1] >> 6)) & 0x1f];
    face_name[name_str_len++] = enc[p[i + 1] & 0x3f];
330
  }
331 332 333 334 335 336 337 338 339
  face_name[name_str_len] = 0;
  if (plen)
    *plen = name_str_len;
}

/* Destroys blob. */
static hb_blob_t *
_hb_rename_font (hb_blob_t *blob, wchar_t *new_name)
{
B
Behdad Esfahbod 已提交
340 341 342 343 344 345 346 347 348
  /* Create a copy of the font data, with the 'name' table replaced by a
   * table that names the font with our private F_* name created above.
   * For simplicity, we just append a new 'name' table and update the
   * sfnt directory; the original table is left in place, but unused.
   *
   * The new table will contain just 5 name IDs: family, style, unique,
   * full, PS. All of them point to the same name data with our unique name.
   */

B
Behdad Esfahbod 已提交
349 350
  blob = OT::Sanitizer<OT::OpenTypeFontFile>::sanitize (blob);

351 352 353 354
  unsigned int length, new_length, name_str_len;
  const char *orig_sfnt_data = hb_blob_get_data (blob, &length);

  _hb_generate_unique_face_name (new_name, &name_str_len);
355 356 357

  static const uint16_t name_IDs[] = { 1, 2, 3, 4, 6 };

B
Behdad Esfahbod 已提交
358 359
  unsigned int name_table_length = OT::name::min_size +
                                   ARRAY_LENGTH (name_IDs) * OT::NameRecord::static_size +
360 361 362
                                   name_str_len * 2; /* for name data in UTF16BE form */
  unsigned int name_table_offset = (length + 3) & ~3;

B
Behdad Esfahbod 已提交
363 364
  new_length = name_table_offset + ((name_table_length + 3) & ~3);
  void *new_sfnt_data = calloc (1, new_length);
365
  if (!new_sfnt_data)
B
Behdad Esfahbod 已提交
366 367
  {
    hb_blob_destroy (blob);
368
    return NULL;
B
Behdad Esfahbod 已提交
369
  }
370 371 372

  memcpy(new_sfnt_data, orig_sfnt_data, length);

B
Behdad Esfahbod 已提交
373 374 375 376 377 378 379 380 381 382 383 384 385
  OT::name &name = OT::StructAtOffset<OT::name> (new_sfnt_data, name_table_offset);
  name.format.set (0);
  name.count.set (ARRAY_LENGTH (name_IDs));
  name.stringOffset.set (name.get_size ());
  for (unsigned int i = 0; i < ARRAY_LENGTH (name_IDs); i++)
  {
    OT::NameRecord &record = name.nameRecord[i];
    record.platformID.set (3);
    record.encodingID.set (1);
    record.languageID.set (0x0409); /* English */
    record.nameID.set (name_IDs[i]);
    record.length.set (name_str_len * 2);
    record.offset.set (0);
386 387
  }

B
Behdad Esfahbod 已提交
388 389 390 391
  /* Copy string data from new_name, converting wchar_t to UTF16BE. */
  unsigned char *p = &OT::StructAfter<unsigned char> (name);
  for (unsigned int i = 0; i < name_str_len; i++)
  {
392 393 394 395
    *p++ = new_name[i] >> 8;
    *p++ = new_name[i] & 0xff;
  }

B
Behdad Esfahbod 已提交
396
  /* Adjust name table entry to point to new name table */
397 398 399
  const OT::OpenTypeFontFile &file = * (OT::OpenTypeFontFile *) (new_sfnt_data);
  unsigned int face_count = file.get_face_count ();
  for (unsigned int face_index = 0; face_index < face_count; face_index++)
400
  {
B
Behdad Esfahbod 已提交
401 402
    /* Note: doing multiple edits (ie. TTC) can be unsafe.  There may be
     * toe-stepping.  But we don't really care. */
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
    const OT::OpenTypeFontFace &face = file.get_face (face_index);
    unsigned int index;
    if (face.find_table_index (HB_OT_TAG_name, &index))
    {
      OT::TableRecord &record = const_cast<OT::TableRecord &> (face.get_table (index));
      record.checkSum.set_for_data (&name, name_table_length);
      record.offset.set (name_table_offset);
      record.length.set (name_table_length);
    }
    else if (face_index == 0) /* Fail if first face doesn't have 'name' table. */
    {
      free (new_sfnt_data);
      hb_blob_destroy (blob);
      return NULL;
    }
418 419 420
  }

  /* The checkSumAdjustment field in the 'head' table is now wrong,
B
Behdad Esfahbod 已提交
421 422
   * but that doesn't actually seem to cause any problems so we don't
   * bother. */
423

424
  hb_blob_destroy (blob);
B
Behdad Esfahbod 已提交
425 426
  return hb_blob_create ((const char *) new_sfnt_data, new_length,
			 HB_MEMORY_MODE_WRITABLE, NULL, free);
427 428
}

429 430
hb_uniscribe_shaper_face_data_t *
_hb_uniscribe_shaper_face_data_create (hb_face_t *face)
B
Behdad Esfahbod 已提交
431
{
432
  hb_uniscribe_shaper_face_data_t *data = (hb_uniscribe_shaper_face_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_face_data_t));
B
Behdad Esfahbod 已提交
433
  if (unlikely (!data))
434
    return NULL;
B
Behdad Esfahbod 已提交
435

436 437 438 439 440 441 442
  data->funcs = hb_uniscribe_shaper_get_funcs ();
  if (unlikely (!data->funcs))
  {
    free (data);
    return NULL;
  }

B
Behdad Esfahbod 已提交
443
  hb_blob_t *blob = hb_face_reference_blob (face);
444
  if (unlikely (!hb_blob_get_length (blob)))
B
Behdad Esfahbod 已提交
445 446
    DEBUG_MSG (UNISCRIBE, face, "Face has empty blob");

447
  blob = _hb_rename_font (blob, data->face_name);
B
Behdad Esfahbod 已提交
448 449 450 451 452
  if (unlikely (!blob))
  {
    free (data);
    return NULL;
  }
453 454

  DWORD num_fonts_installed;
455 456 457
  data->fh = AddFontMemResourceEx ((void *) hb_blob_get_data (blob, NULL),
				   hb_blob_get_length (blob),
				   0, &num_fonts_installed);
B
Behdad Esfahbod 已提交
458 459
  if (unlikely (!data->fh))
  {
B
Behdad Esfahbod 已提交
460
    DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed");
461 462
    free (data);
    return NULL;
B
Behdad Esfahbod 已提交
463 464 465 466 467
  }

  return data;
}

468 469 470
void
_hb_uniscribe_shaper_face_data_destroy (hb_uniscribe_shaper_face_data_t *data)
{
B
Behdad Esfahbod 已提交
471
  RemoveFontMemResourceEx (data->fh);
472 473
  free (data);
}
B
Behdad Esfahbod 已提交
474

475 476 477 478 479 480

/*
 * shaper font data
 */

struct hb_uniscribe_shaper_font_data_t {
B
Behdad Esfahbod 已提交
481
  HDC hdc;
B
Behdad Esfahbod 已提交
482
  LOGFONTW log_font;
B
Behdad Esfahbod 已提交
483 484
  HFONT hfont;
  SCRIPT_CACHE script_cache;
485
};
B
Behdad Esfahbod 已提交
486

487 488 489 490 491 492 493 494
static bool
populate_log_font (LOGFONTW  *lf,
		   hb_font_t *font)
{
  memset (lf, 0, sizeof (*lf));
  lf->lfHeight = -font->y_scale;
  lf->lfCharSet = DEFAULT_CHARSET;

495 496
  hb_face_t *face = font->face;
  hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
497

498
  memcpy (lf->lfFaceName, face_data->face_name, sizeof (lf->lfFaceName));
499 500 501 502

  return true;
}

503 504 505
hb_uniscribe_shaper_font_data_t *
_hb_uniscribe_shaper_font_data_create (hb_font_t *font)
{
B
Behdad Esfahbod 已提交
506 507
  if (unlikely (!hb_uniscribe_shaper_face_data_ensure (font->face))) return NULL;

508
  hb_uniscribe_shaper_font_data_t *data = (hb_uniscribe_shaper_font_data_t *) calloc (1, sizeof (hb_uniscribe_shaper_font_data_t));
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
  if (unlikely (!data))
    return NULL;

  data->hdc = GetDC (NULL);

  if (unlikely (!populate_log_font (&data->log_font, font))) {
    DEBUG_MSG (UNISCRIBE, font, "Font populate_log_font() failed");
    _hb_uniscribe_shaper_font_data_destroy (data);
    return NULL;
  }

  data->hfont = CreateFontIndirectW (&data->log_font);
  if (unlikely (!data->hfont)) {
    DEBUG_MSG (UNISCRIBE, font, "Font CreateFontIndirectW() failed");
    _hb_uniscribe_shaper_font_data_destroy (data);
     return NULL;
  }

  if (!SelectObject (data->hdc, data->hfont)) {
    DEBUG_MSG (UNISCRIBE, font, "Font SelectObject() failed");
    _hb_uniscribe_shaper_font_data_destroy (data);
     return NULL;
  }

  return data;
}

void
_hb_uniscribe_shaper_font_data_destroy (hb_uniscribe_shaper_font_data_t *data)
B
Behdad Esfahbod 已提交
538 539 540 541 542 543 544 545 546 547
{
  if (data->hdc)
    ReleaseDC (NULL, data->hdc);
  if (data->hfont)
    DeleteObject (data->hfont);
  if (data->script_cache)
    ScriptFreeCache (&data->script_cache);
  free (data);
}

B
Minor  
Behdad Esfahbod 已提交
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
LOGFONTW *
hb_uniscribe_font_get_logfontw (hb_font_t *font)
{
  if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return NULL;
  hb_uniscribe_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
  return &font_data->log_font;
}

HFONT
hb_uniscribe_font_get_hfont (hb_font_t *font)
{
  if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return NULL;
  hb_uniscribe_shaper_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
  return font_data->hfont;
}

564 565 566 567 568 569 570 571

/*
 * shaper shape_plan data
 */

struct hb_uniscribe_shaper_shape_plan_data_t {};

hb_uniscribe_shaper_shape_plan_data_t *
B
Minor  
Behdad Esfahbod 已提交
572 573 574
_hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan HB_UNUSED,
					     const hb_feature_t *user_features HB_UNUSED,
					     unsigned int        num_user_features HB_UNUSED)
B
Behdad Esfahbod 已提交
575
{
576 577
  return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
B
Behdad Esfahbod 已提交
578

579
void
B
Minor  
Behdad Esfahbod 已提交
580
_hb_uniscribe_shaper_shape_plan_data_destroy (hb_uniscribe_shaper_shape_plan_data_t *data HB_UNUSED)
581 582
{
}
B
Behdad Esfahbod 已提交
583 584


585 586 587
/*
 * shaper
 */
B
Behdad Esfahbod 已提交
588 589


590
hb_bool_t
B
Minor  
Behdad Esfahbod 已提交
591 592
_hb_uniscribe_shape (hb_shape_plan_t    *shape_plan,
		     hb_font_t          *font,
593 594 595
		     hb_buffer_t        *buffer,
		     const hb_feature_t *features,
		     unsigned int        num_features)
596
{
597 598 599
  hb_face_t *face = font->face;
  hb_uniscribe_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
  hb_uniscribe_shaper_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
600
  hb_uniscribe_shaper_funcs_t *funcs = face_data->funcs;
601

602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
  /*
   * Set up features.
   */
  hb_auto_array_t<OPENTYPE_FEATURE_RECORD> feature_records;
  hb_auto_array_t<range_record_t> range_records;
  if (num_features)
  {
    /* Sort features by start/end events. */
    hb_auto_array_t<feature_event_t> feature_events;
    for (unsigned int i = 0; i < num_features; i++)
    {
      active_feature_t feature;
      feature.rec.tagFeature = hb_uint32_swap (features[i].tag);
      feature.rec.lParameter = features[i].value;
      feature.order = i;

      feature_event_t *event;

      event = feature_events.push ();
      if (unlikely (!event))
	goto fail_features;
      event->index = features[i].start;
      event->start = true;
      event->feature = feature;

      event = feature_events.push ();
      if (unlikely (!event))
	goto fail_features;
      event->index = features[i].end;
      event->start = false;
      event->feature = feature;
    }
B
Behdad Esfahbod 已提交
634
    feature_events.qsort ();
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
    /* Add a strategic final event. */
    {
      active_feature_t feature;
      feature.rec.tagFeature = 0;
      feature.rec.lParameter = 0;
      feature.order = num_features + 1;

      feature_event_t *event = feature_events.push ();
      if (unlikely (!event))
	goto fail_features;
      event->index = 0; /* This value does magic. */
      event->start = false;
      event->feature = feature;
    }

    /* Scan events and save features for each range. */
    hb_auto_array_t<active_feature_t> active_features;
    unsigned int last_index = 0;
    for (unsigned int i = 0; i < feature_events.len; i++)
    {
      feature_event_t *event = &feature_events[i];

      if (event->index != last_index)
      {
        /* Save a snapshot of active features and the range. */
	range_record_t *range = range_records.push ();
	if (unlikely (!range))
	  goto fail_features;

	unsigned int offset = feature_records.len;

B
Behdad Esfahbod 已提交
666
	active_features.qsort ();
667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711
	for (unsigned int j = 0; j < active_features.len; j++)
	{
	  if (!j || active_features[j].rec.tagFeature != feature_records[feature_records.len - 1].tagFeature)
	  {
	    OPENTYPE_FEATURE_RECORD *feature = feature_records.push ();
	    if (unlikely (!feature))
	      goto fail_features;
	    *feature = active_features[j].rec;
	  }
	  else
	  {
	    /* Overrides value for existing feature. */
	    feature_records[feature_records.len - 1].lParameter = active_features[j].rec.lParameter;
	  }
	}

	/* Will convert to pointer after all is ready, since feature_records.array
	 * may move as we grow it. */
	range->props.potfRecords = reinterpret_cast<OPENTYPE_FEATURE_RECORD *> (offset);
	range->props.cotfRecords = feature_records.len - offset;
	range->index_first = last_index;
	range->index_last  = event->index - 1;

	last_index = event->index;
      }

      if (event->start) {
        active_feature_t *feature = active_features.push ();
	if (unlikely (!feature))
	  goto fail_features;
	*feature = event->feature;
      } else {
        active_feature_t *feature = active_features.find (&event->feature);
	if (feature)
	  active_features.remove (feature - active_features.array);
      }
    }

    if (!range_records.len) /* No active feature found. */
      goto fail_features;

    /* Fixup the pointers. */
    for (unsigned int i = 0; i < range_records.len; i++)
    {
      range_record_t *range = &range_records[i];
J
Jonathan Kew 已提交
712
      range->props.potfRecords = feature_records.array + reinterpret_cast<uintptr_t> (range->props.potfRecords);
713 714 715 716 717 718 719 720
    }
  }
  else
  {
  fail_features:
    num_features = 0;
  }

B
Behdad Esfahbod 已提交
721 722 723
#define FAIL(...) \
  HB_STMT_START { \
    DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \
724
    return false; \
B
Behdad Esfahbod 已提交
725 726 727 728
  } HB_STMT_END;

  HRESULT hr;

729 730 731
retry:

  unsigned int scratch_size;
B
Behdad Esfahbod 已提交
732
  hb_buffer_t::scratch_buffer_t *scratch = buffer->get_scratch_buffer (&scratch_size);
733

B
Behdad Esfahbod 已提交
734 735 736 737 738 739 740 741
#define ALLOCATE_ARRAY(Type, name, len) \
  Type *name = (Type *) scratch; \
  { \
    unsigned int _consumed = DIV_CEIL ((len) * sizeof (Type), sizeof (*scratch)); \
    assert (_consumed <= scratch_size); \
    scratch += _consumed; \
    scratch_size -= _consumed; \
  }
742 743 744

#define utf16_index() var1.u32

B
Behdad Esfahbod 已提交
745 746
  ALLOCATE_ARRAY (WCHAR, pchars, buffer->len * 2);

747
  unsigned int chars_len = 0;
748 749
  for (unsigned int i = 0; i < buffer->len; i++)
  {
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764
    hb_codepoint_t c = buffer->info[i].codepoint;
    buffer->info[i].utf16_index() = chars_len;
    if (likely (c < 0x10000))
      pchars[chars_len++] = c;
    else if (unlikely (c >= 0x110000))
      pchars[chars_len++] = 0xFFFD;
    else {
      pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10);
      pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1));
    }
  }

  ALLOCATE_ARRAY (WORD, log_clusters, chars_len);
  ALLOCATE_ARRAY (SCRIPT_CHARPROP, char_props, chars_len);

765 766 767 768 769 770 771 772 773 774 775 776 777 778
  if (num_features)
  {
    /* Need log_clusters to assign features. */
    chars_len = 0;
    for (unsigned int i = 0; i < buffer->len; i++)
    {
      hb_codepoint_t c = buffer->info[i].codepoint;
      unsigned int cluster = buffer->info[i].cluster;
      log_clusters[chars_len++] = cluster;
      if (c >= 0x10000 && c < 0x110000)
	log_clusters[chars_len++] = cluster; /* Surrogates. */
    }
  }

779 780 781 782 783 784 785 786
  /* The -2 in the following is to compensate for possible
   * alignment needed after the WORD array.  sizeof(WORD) == 2. */
  unsigned int glyphs_size = (scratch_size * sizeof (int) - 2)
			   / (sizeof (WORD) +
			      sizeof (SCRIPT_GLYPHPROP) +
			      sizeof (int) +
			      sizeof (GOFFSET) +
			      sizeof (uint32_t));
787 788 789 790 791 792 793

  ALLOCATE_ARRAY (WORD, glyphs, glyphs_size);
  ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size);
  ALLOCATE_ARRAY (int, advances, glyphs_size);
  ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size);
  ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size);

794 795 796 797 798 799 800 801
  /* Note:
   * We can't touch the contents of glyph_props.  Our fallback
   * implementations of Shape and Place functions use that buffer
   * by casting it to a different type.  It works because they
   * both agree about it, but if we want to access it here we
   * need address that issue first.
   */

B
Behdad Esfahbod 已提交
802
#undef ALLOCATE_ARRAY
803

B
Behdad Esfahbod 已提交
804
#define MAX_ITEMS 256
805 806

  SCRIPT_ITEM items[MAX_ITEMS + 1];
807
  SCRIPT_CONTROL bidi_control = {0};
808
  SCRIPT_STATE bidi_state = {0};
809
  ULONG script_tags[MAX_ITEMS];
810 811
  int item_count;

812
  /* MinGW32 doesn't define fMergeNeutralItems, so we bruteforce */
813
  //bidi_control.fMergeNeutralItems = true;
814 815
  *(uint32_t*)&bidi_control |= 1<<24;

816
  bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1;
817
  bidi_state.fOverrideDirection = 1;
818

B
Behdad Esfahbod 已提交
819
  hr = funcs->ScriptItemizeOpenType (pchars,
820 821 822 823 824 825 826
				     chars_len,
				     MAX_ITEMS,
				     &bidi_control,
				     &bidi_state,
				     items,
				     script_tags,
				     &item_count);
827
  if (unlikely (FAILED (hr)))
B
Behdad Esfahbod 已提交
828
    FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr);
829 830 831

#undef MAX_ITEMS

832
  OPENTYPE_TAG language_tag = hb_uint32_swap (hb_ot_tag_from_language (buffer->props.language));
833 834
  hb_auto_array_t<TEXTRANGE_PROPERTIES*> range_properties;
  hb_auto_array_t<int> range_char_counts;
835 836 837

  unsigned int glyphs_offset = 0;
  unsigned int glyphs_len;
838
  bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
839
  for (unsigned int i = 0; i < item_count; i++)
840
  {
B
Behdad Esfahbod 已提交
841 842 843
    unsigned int chars_offset = items[i].iCharPos;
    unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset;

844 845 846
    if (num_features)
    {
      range_properties.shrink (0);
847
      range_char_counts.shrink (0);
848

849
      range_record_t *last_range = &range_records[0];
850

851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878
      for (unsigned int k = chars_offset; k < chars_offset + item_chars_len; k++)
      {
	range_record_t *range = last_range;
	while (log_clusters[k] < range->index_first)
	  range--;
	while (log_clusters[k] > range->index_last)
	  range++;
	if (!range_properties.len ||
	    &range->props != range_properties[range_properties.len - 1])
	{
	  TEXTRANGE_PROPERTIES **props = range_properties.push ();
	  int *c = range_char_counts.push ();
	  if (unlikely (!props || !c))
	  {
	    range_properties.shrink (0);
	    range_char_counts.shrink (0);
	    break;
	  }
	  *props = &range->props;
	  *c = 1;
	}
	else
	{
	  range_char_counts[range_char_counts.len - 1]++;
	}

	last_range = range;
      }
879 880
    }

881 882 883 884
    /* Asking for glyphs in logical order circumvents at least
     * one bug in Uniscribe. */
    items[i].a.fLogicalOrder = true;

885
  retry_shape:
886 887 888 889 890
    hr = funcs->ScriptShapeOpenType (font_data->hdc,
				     &font_data->script_cache,
				     &items[i].a,
				     script_tags[i],
				     language_tag,
891 892 893
				     range_char_counts.array,
				     range_properties.array,
				     range_properties.len,
B
Behdad Esfahbod 已提交
894
				     pchars + chars_offset,
895 896 897 898 899 900 901 902
				     item_chars_len,
				     glyphs_size - glyphs_offset,
				     /* out */
				     log_clusters + chars_offset,
				     char_props + chars_offset,
				     glyphs + glyphs_offset,
				     glyph_props + glyphs_offset,
				     (int *) &glyphs_len);
B
Behdad Esfahbod 已提交
903 904 905 906 907 908 909 910 911 912 913

    if (unlikely (items[i].a.fNoGlyphIndex))
      FAIL ("ScriptShapeOpenType() set fNoGlyphIndex");
    if (unlikely (hr == E_OUTOFMEMORY))
    {
      buffer->ensure (buffer->allocated * 2);
      if (buffer->in_error)
	FAIL ("Buffer resize failed");
      goto retry;
    }
    if (unlikely (hr == USP_E_SCRIPT_NOT_IN_FONT))
914 915 916 917 918 919
    {
      if (items[i].a.eScript == SCRIPT_UNDEFINED)
	FAIL ("ScriptShapeOpenType() failed: Font doesn't support script");
      items[i].a.eScript = SCRIPT_UNDEFINED;
      goto retry_shape;
    }
B
Behdad Esfahbod 已提交
920
    if (unlikely (FAILED (hr)))
921
    {
B
Behdad Esfahbod 已提交
922
      FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr);
923 924 925 926
    }

    for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++)
      log_clusters[j] += glyphs_offset;
B
Behdad Esfahbod 已提交
927

928 929 930 931 932
    hr = funcs->ScriptPlaceOpenType (font_data->hdc,
				     &font_data->script_cache,
				     &items[i].a,
				     script_tags[i],
				     language_tag,
933 934 935
				     range_char_counts.array,
				     range_properties.array,
				     range_properties.len,
B
Behdad Esfahbod 已提交
936
				     pchars + chars_offset,
937 938 939 940 941 942 943 944 945 946
				     log_clusters + chars_offset,
				     char_props + chars_offset,
				     item_chars_len,
				     glyphs + glyphs_offset,
				     glyph_props + glyphs_offset,
				     glyphs_len,
				     /* out */
				     advances + glyphs_offset,
				     offsets + glyphs_offset,
				     NULL);
B
Behdad Esfahbod 已提交
947 948 949
    if (unlikely (FAILED (hr)))
      FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);

B
Behdad Esfahbod 已提交
950 951 952 953 954 955 956 957
    if (DEBUG_ENABLED (UNISCRIBE))
      fprintf (stderr, "Item %d RTL %d LayoutRTL %d LogicalOrder %d ScriptTag %c%c%c%c\n",
	       i,
	       items[i].a.fRTL,
	       items[i].a.fLayoutRTL,
	       items[i].a.fLogicalOrder,
	       HB_UNTAG (hb_uint32_swap (script_tags[i])));

B
Behdad Esfahbod 已提交
958
    glyphs_offset += glyphs_len;
959 960 961 962 963 964 965
  }
  glyphs_len = glyphs_offset;

  /* Ok, we've got everything we need, now compose output buffer,
   * very, *very*, carefully! */

  /* Calculate visual-clusters.  That's what we ship. */
966 967
  for (unsigned int i = 0; i < glyphs_len; i++)
    vis_clusters[i] = -1;
968 969 970 971
  for (unsigned int i = 0; i < buffer->len; i++) {
    uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]];
    *p = MIN (*p, buffer->info[i].cluster);
  }
972 973 974
  for (unsigned int i = 1; i < glyphs_len; i++)
    if (vis_clusters[i] == -1)
      vis_clusters[i] = vis_clusters[i - 1];
975 976 977 978 979

#undef utf16_index

  buffer->ensure (glyphs_len);
  if (buffer->in_error)
980
    FAIL ("Buffer in error");
981

982
#undef FAIL
983 984

  /* Set glyph infos */
985
  buffer->len = 0;
986 987
  for (unsigned int i = 0; i < glyphs_len; i++)
  {
988
    hb_glyph_info_t *info = &buffer->info[buffer->len++];
989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007

    info->codepoint = glyphs[i];
    info->cluster = vis_clusters[i];

    /* The rest is crap.  Let's store position info there for now. */
    info->mask = advances[i];
    info->var1.u32 = offsets[i].du;
    info->var2.u32 = offsets[i].dv;
  }

  /* Set glyph positions */
  buffer->clear_positions ();
  for (unsigned int i = 0; i < glyphs_len; i++)
  {
    hb_glyph_info_t *info = &buffer->info[i];
    hb_glyph_position_t *pos = &buffer->pos[i];

    /* TODO vertical */
    pos->x_advance = info->mask;
1008
    pos->x_offset = backward ? -info->var1.u32 : info->var1.u32;
1009 1010 1011
    pos->y_offset = info->var2.u32;
  }

1012 1013 1014
  if (backward)
    hb_buffer_reverse (buffer);

1015
  /* Wow, done! */
1016
  return true;
1017 1018 1019
}