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 634 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 666 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 712 713 714 715 716 717 718 719 720
  /*
   * 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;
    }
    feature_events.sort ();
    /* 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;

	active_features.sort ();
	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];
      range->props.potfRecords = feature_records.array + reinterpret_cast<unsigned int> (range->props.potfRecords);
    }
  }
  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
  /* All the following types are sized in multiples of sizeof(int). */
  unsigned int glyphs_size = scratch_size / ((sizeof (WORD) +
					      sizeof (SCRIPT_GLYPHPROP) +
					      sizeof (int) +
					      sizeof (GOFFSET) +
					      sizeof (uint32_t))
					     / sizeof (int));
786 787 788 789 790 791 792

  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);

793 794 795 796 797 798 799 800
  /* 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 已提交
801
#undef ALLOCATE_ARRAY
802

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

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

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

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

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

#undef MAX_ITEMS

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

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

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

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

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
      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;
      }
878 879
    }

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

884
  retry_shape:
885 886 887 888 889
    hr = funcs->ScriptShapeOpenType (font_data->hdc,
				     &font_data->script_cache,
				     &items[i].a,
				     script_tags[i],
				     language_tag,
890 891 892
				     range_char_counts.array,
				     range_properties.array,
				     range_properties.len,
B
Behdad Esfahbod 已提交
893
				     pchars + chars_offset,
894 895 896 897 898 899 900 901
				     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 已提交
902 903 904 905 906 907 908 909 910 911 912

    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))
913 914 915 916 917 918
    {
      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 已提交
919
    if (unlikely (FAILED (hr)))
920
    {
B
Behdad Esfahbod 已提交
921
      FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr);
922 923 924 925
    }

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

927 928 929 930 931
    hr = funcs->ScriptPlaceOpenType (font_data->hdc,
				     &font_data->script_cache,
				     &items[i].a,
				     script_tags[i],
				     language_tag,
932 933 934
				     range_char_counts.array,
				     range_properties.array,
				     range_properties.len,
B
Behdad Esfahbod 已提交
935
				     pchars + chars_offset,
936 937 938 939 940 941 942 943 944 945
				     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 已提交
946 947 948
    if (unlikely (FAILED (hr)))
      FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr);

B
Behdad Esfahbod 已提交
949 950 951 952 953 954 955 956
    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 已提交
957
    glyphs_offset += glyphs_len;
958 959 960 961 962 963 964
  }
  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. */
965 966
  for (unsigned int i = 0; i < glyphs_len; i++)
    vis_clusters[i] = -1;
967 968 969 970
  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);
  }
971 972 973
  for (unsigned int i = 1; i < glyphs_len; i++)
    if (vis_clusters[i] == -1)
      vis_clusters[i] = vis_clusters[i - 1];
974 975 976 977 978

#undef utf16_index

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

981
#undef FAIL
982 983

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

    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;
1007
    pos->x_offset = backward ? -info->var1.u32 : info->var1.u32;
1008 1009 1010
    pos->y_offset = info->var2.u32;
  }

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

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