hb-uniscribe.cc revision 872969126756456a69bf958f3df6e56a26e57b0a
1c779e96158cbac4c62df8e2053ab6a933eba5868Chandler Carruth/* 22e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman * Copyright © 2011,2012 Google, Inc. 32e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman * 42e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman * This is part of HarfBuzz, a text shaping library. 52e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman * 62e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman * Permission is hereby granted, without written agreement and without 72e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman * license or royalty fees, to use, copy, modify, and distribute this 82e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman * software and its documentation for any purpose, provided that the 92e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman * above copyright notice and the following two paragraphs appear in 10ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines * all copies of this software. 110b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth * 120b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 130b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 140b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 150b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 160b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth * DAMAGE. 17ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines * 182e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 192e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 202e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 212e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 222e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 232e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman * 24db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner * Google Author(s): Behdad Esfahbod 25eed707b1e6097aac2bb6b3d47271f6300ace7f2eOwen Anderson */ 26eed707b1e6097aac2bb6b3d47271f6300ace7f2eOwen Anderson 27eed707b1e6097aac2bb6b3d47271f6300ace7f2eOwen Anderson#define _WIN32_WINNT 0x0500 28eed707b1e6097aac2bb6b3d47271f6300ace7f2eOwen Anderson 299e9a0d5fc26878e51a58a8b57900fcbf952c2691Owen Anderson#include "hb-private.hh" 302e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman 312e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman#include <windows.h> 322e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman#include <usp10.h> 339138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramer 342e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukmantypedef ULONG WIN_ULONG; 352e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman 362e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman#include "hb-uniscribe.h" 379138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramer 382e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman#include "hb-ot-name-table.hh" 392e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman#include "hb-ot-tag.h" 402e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman 419138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramer#include "hb-font-private.hh" 422e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman#include "hb-buffer-private.hh" 432e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman 442e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman 459138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramer 462e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman#ifndef HB_DEBUG_UNISCRIBE 472e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman#define HB_DEBUG_UNISCRIBE (HB_DEBUG+0) 482e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman#endif 499138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramer 502e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman 512e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman/* 522e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha BrukmanDWORD GetFontData( 539138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramer __in HDC hdc, 542e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman __in DWORD dwTable, 552e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman __in DWORD dwOffset, 562e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman __out LPVOID lpvBuffer, 579138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramer __in DWORD cbData 582e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman); 592e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman*/ 602e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman 619138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramerstatic bool 622e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukmanpopulate_log_font (LOGFONTW *lf, 632e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman hb_font_t *font) 642e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman{ 659138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramer memset (lf, 0, sizeof (*lf)); 662e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman lf->lfHeight = -font->y_scale; 672e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman lf->lfCharSet = DEFAULT_CHARSET; 682e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman 699138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramer hb_blob_t *blob = Sanitizer<name>::sanitize (hb_face_reference_table (font->face, HB_TAG ('n','a','m','e'))); 702e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman const name *name_table = Sanitizer<name>::lock_instance (blob); 712e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman unsigned int len = name_table->get_name (3, 1, 0x409, 4, 722e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman lf->lfFaceName, 739138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramer sizeof (lf->lfFaceName[0]) * LF_FACESIZE) 742e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman / sizeof (lf->lfFaceName[0]); 752e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman hb_blob_destroy (blob); 762e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman 779138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramer if (unlikely (!len)) { 782e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman DEBUG_MSG (UNISCRIBE, NULL, "Didn't find English name table entry"); 792e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman return false; 802e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman } 819138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramer if (unlikely (len >= LF_FACESIZE)) { 822e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman DEBUG_MSG (UNISCRIBE, NULL, "Font name too long"); 832e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman return false; 842e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman } 859138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramer 862e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman for (unsigned int i = 0; i < len; i++) 872e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman lf->lfFaceName[i] = hb_be_uint16 (lf->lfFaceName[i]); 882e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman lf->lfFaceName[len] = 0; 899138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramer 902e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman return true; 912e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman} 922e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman 939138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramer 942e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukmanstatic hb_user_data_key_t hb_uniscribe_data_key; 952e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman 962e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman 979138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramerstatic struct hb_uniscribe_face_data_t { 982e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman HANDLE fh; 992e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman} _hb_uniscribe_face_data_nil = {0}; 1002e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman 1019138b1909a4c2d88aa88f807b296356f09206e87Benjamin Kramerstatic void 1022e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman_hb_uniscribe_face_data_destroy (hb_uniscribe_face_data_t *data) 1032e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman{ 104f3b0aac1902d6e01ed9a633f4a93c26317b43835Chris Lattner if (data->fh) 105db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner RemoveFontMemResourceEx (data->fh); 106eed707b1e6097aac2bb6b3d47271f6300ace7f2eOwen Anderson free (data); 107eed707b1e6097aac2bb6b3d47271f6300ace7f2eOwen Anderson} 108eed707b1e6097aac2bb6b3d47271f6300ace7f2eOwen Anderson 109eed707b1e6097aac2bb6b3d47271f6300ace7f2eOwen Andersonstatic hb_uniscribe_face_data_t * 110eed707b1e6097aac2bb6b3d47271f6300ace7f2eOwen Anderson_hb_uniscribe_face_get_data (hb_face_t *face) 111eed707b1e6097aac2bb6b3d47271f6300ace7f2eOwen Anderson{ 112f3b0aac1902d6e01ed9a633f4a93c26317b43835Chris Lattner hb_uniscribe_face_data_t *data = (hb_uniscribe_face_data_t *) hb_face_get_user_data (face, &hb_uniscribe_data_key); 113f3b0aac1902d6e01ed9a633f4a93c26317b43835Chris Lattner if (likely (data)) return data; 114eed707b1e6097aac2bb6b3d47271f6300ace7f2eOwen Anderson 115f3b0aac1902d6e01ed9a633f4a93c26317b43835Chris Lattner data = (hb_uniscribe_face_data_t *) calloc (1, sizeof (hb_uniscribe_face_data_t)); 116f3b0aac1902d6e01ed9a633f4a93c26317b43835Chris Lattner if (unlikely (!data)) 117e562dba845265b5577699eb857fead1ea0f7905bChris Lattner return &_hb_uniscribe_face_data_nil; 118db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner 119e562dba845265b5577699eb857fead1ea0f7905bChris Lattner 120db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner hb_blob_t *blob = hb_face_reference_blob (face); 121e562dba845265b5577699eb857fead1ea0f7905bChris Lattner unsigned int blob_length; 122e562dba845265b5577699eb857fead1ea0f7905bChris Lattner const char *blob_data = hb_blob_get_data (blob, &blob_length); 123e562dba845265b5577699eb857fead1ea0f7905bChris Lattner if (unlikely (!blob_length)) 124e562dba845265b5577699eb857fead1ea0f7905bChris Lattner DEBUG_MSG (UNISCRIBE, face, "Face has empty blob"); 125e562dba845265b5577699eb857fead1ea0f7905bChris Lattner 126655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov DWORD num_fonts_installed; 127655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov data->fh = AddFontMemResourceEx ((void *) blob_data, blob_length, 0, &num_fonts_installed); 128655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov hb_blob_destroy (blob); 129655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov if (unlikely (!data->fh)) 130655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed"); 131655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov 132655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov 133655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov if (unlikely (!hb_face_set_user_data (face, &hb_uniscribe_data_key, data, 134655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov (hb_destroy_func_t) _hb_uniscribe_face_data_destroy, 135655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov false))) 136655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov { 137655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov _hb_uniscribe_face_data_destroy (data); 138655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov data = (hb_uniscribe_face_data_t *) hb_face_get_user_data (face, &hb_uniscribe_data_key); 139655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov if (data) 140655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov return data; 141655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov else 142655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov return &_hb_uniscribe_face_data_nil; 143655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov } 144655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov 145655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov return data; 146655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov} 147655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov 148655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov 149655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanovstatic struct hb_uniscribe_font_data_t { 150655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov HDC hdc; 151655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov LOGFONTW log_font; 152655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov HFONT hfont; 153655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov SCRIPT_CACHE script_cache; 154655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov} _hb_uniscribe_font_data_nil = {NULL, NULL, NULL}; 155655578f8b5275e7c59b87d4709b0d56b2621caacEvgeniy Stepanov 1566bf3e46aa87d0cb6044f2282a40411211bf95a5dNAKAMURA Takumistatic void 1576bf3e46aa87d0cb6044f2282a40411211bf95a5dNAKAMURA Takumi_hb_uniscribe_font_data_destroy (hb_uniscribe_font_data_t *data) 1586bf3e46aa87d0cb6044f2282a40411211bf95a5dNAKAMURA Takumi{ 1596bf3e46aa87d0cb6044f2282a40411211bf95a5dNAKAMURA Takumi if (data->hdc) 1606bf3e46aa87d0cb6044f2282a40411211bf95a5dNAKAMURA Takumi ReleaseDC (NULL, data->hdc); 1616bf3e46aa87d0cb6044f2282a40411211bf95a5dNAKAMURA Takumi if (data->hfont) 1626bf3e46aa87d0cb6044f2282a40411211bf95a5dNAKAMURA Takumi DeleteObject (data->hfont); 1636bf3e46aa87d0cb6044f2282a40411211bf95a5dNAKAMURA Takumi if (data->script_cache) 164b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy ScriptFreeCache (&data->script_cache); 165b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy free (data); 166b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy} 16736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 168b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloystatic hb_uniscribe_font_data_t * 169b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy_hb_uniscribe_font_get_data (hb_font_t *font) 170b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy{ 171b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy hb_uniscribe_font_data_t *data = (hb_uniscribe_font_data_t *) hb_font_get_user_data (font, &hb_uniscribe_data_key); 172b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy if (likely (data)) return data; 173b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 174b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy data = (hb_uniscribe_font_data_t *) calloc (1, sizeof (hb_uniscribe_font_data_t)); 175b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy if (unlikely (!data)) 176b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy return &_hb_uniscribe_font_data_nil; 177b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 178b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy data->hdc = GetDC (NULL); 179b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 180b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy if (unlikely (!populate_log_font (&data->log_font, font))) 181b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy DEBUG_MSG (UNISCRIBE, font, "Font populate_log_font() failed"); 182b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy else { 183b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy data->hfont = CreateFontIndirectW (&data->log_font); 184b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy if (unlikely (!data->hfont)) 185b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy DEBUG_MSG (UNISCRIBE, font, "Font CreateFontIndirectW() failed"); 186b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy if (!SelectObject (data->hdc, data->hfont)) 187b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy DEBUG_MSG (UNISCRIBE, font, "Font SelectObject() failed"); 188b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy } 189b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 190b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy if (unlikely (!hb_font_set_user_data (font, &hb_uniscribe_data_key, data, 191b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy (hb_destroy_func_t) _hb_uniscribe_font_data_destroy, 192b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy false))) 193b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy { 194b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy _hb_uniscribe_font_data_destroy (data); 195b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy data = (hb_uniscribe_font_data_t *) hb_font_get_user_data (font, &hb_uniscribe_data_key); 196b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy if (data) 197b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy return data; 198b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy else 199b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy return &_hb_uniscribe_font_data_nil; 200b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy } 201b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 202b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy return data; 203b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy} 204b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 205b9478c2aef060aa6b0ede41c05859c34b1527bf8James MolloyLOGFONTW * 206b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloyhb_uniscribe_font_get_logfontw (hb_font_t *font) 207b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy{ 208b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy hb_uniscribe_font_data_t *font_data = _hb_uniscribe_font_get_data (font); 209b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy if (unlikely (!font_data)) 210b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy return NULL; 211b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy return &font_data->log_font; 212b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy} 213b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 214b9478c2aef060aa6b0ede41c05859c34b1527bf8James MolloyHFONT 215b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloyhb_uniscribe_font_get_hfont (hb_font_t *font) 216b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy{ 217b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy hb_uniscribe_font_data_t *font_data = _hb_uniscribe_font_get_data (font); 218b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy if (unlikely (!font_data)) 219b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy return 0; 220b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy return font_data->hfont; 221b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy} 222b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 223b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 224b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloyhb_bool_t 225b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy_hb_uniscribe_shape (hb_font_t *font, 226b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy hb_buffer_t *buffer, 227b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy const hb_feature_t *features, 228b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy unsigned int num_features) 229b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy{ 230b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy buffer->guess_properties (); 231b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 232b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy#define FAIL(...) \ 233b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy HB_STMT_START { \ 234b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy DEBUG_MSG (UNISCRIBE, NULL, __VA_ARGS__); \ 235b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy return false; \ 236b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy } HB_STMT_END; 237b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 238b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy hb_uniscribe_face_data_t *face_data = _hb_uniscribe_face_get_data (font->face); 239b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy if (unlikely (!face_data->fh)) 240b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy FAIL ("Couldn't get face data"); 241b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 242b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy hb_uniscribe_font_data_t *font_data = _hb_uniscribe_font_get_data (font); 243b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy if (unlikely (!font_data->hfont)) 244b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy FAIL ("Couldn't get font font"); 245b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 246b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy if (unlikely (!buffer->len)) 247b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy return true; 248b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 249b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy HRESULT hr; 250b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 2514c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarretry: 2520c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar 2530c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar unsigned int scratch_size; 2544c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar char *scratch = (char *) buffer->get_scratch_buffer (&scratch_size); 255b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 256b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy /* Allocate char buffers; they all fit */ 257b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 258b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy#define ALLOCATE_ARRAY(Type, name, len) \ 259b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy Type *name = (Type *) scratch; \ 260dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines scratch += len * sizeof (name[0]); \ 261dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines scratch_size -= len * sizeof (name[0]); 262dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 263dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define utf16_index() var1.u32 264dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 265dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines WCHAR *pchars = (WCHAR *) scratch; 266dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines unsigned int chars_len = 0; 267dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines for (unsigned int i = 0; i < buffer->len; i++) { 268dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines hb_codepoint_t c = buffer->info[i].codepoint; 269dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines buffer->info[i].utf16_index() = chars_len; 2700c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar if (likely (c < 0x10000)) 2710c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar pchars[chars_len++] = c; 272dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else if (unlikely (c >= 0x110000)) 273dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines pchars[chars_len++] = 0xFFFD; 274dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines else { 275dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines pchars[chars_len++] = 0xD800 + ((c - 0x10000) >> 10); 276dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines pchars[chars_len++] = 0xDC00 + ((c - 0x10000) & ((1 << 10) - 1)); 277dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 278dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 279b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy 280b9478c2aef060aa6b0ede41c05859c34b1527bf8James Molloy ALLOCATE_ARRAY (WCHAR, wchars, chars_len); 28137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ALLOCATE_ARRAY (WORD, log_clusters, chars_len); 28237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ALLOCATE_ARRAY (SCRIPT_CHARPROP, char_props, chars_len); 28337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 28437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines /* On Windows, we don't care about alignment...*/ 28537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines unsigned int glyphs_size = scratch_size / (sizeof (WORD) + 28637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines sizeof (SCRIPT_GLYPHPROP) + 28737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines sizeof (int) + 28837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines sizeof (GOFFSET) + 28937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines sizeof (uint32_t)); 29037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 29137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ALLOCATE_ARRAY (WORD, glyphs, glyphs_size); 29237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ALLOCATE_ARRAY (SCRIPT_GLYPHPROP, glyph_props, glyphs_size); 29337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ALLOCATE_ARRAY (int, advances, glyphs_size); 29437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ALLOCATE_ARRAY (GOFFSET, offsets, glyphs_size); 29537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines ALLOCATE_ARRAY (uint32_t, vis_clusters, glyphs_size); 29637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 29737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 29837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#define MAX_ITEMS 256 29937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 30037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines SCRIPT_ITEM items[MAX_ITEMS + 1]; 30137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines SCRIPT_CONTROL bidi_control = {0}; 30237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines SCRIPT_STATE bidi_state = {0}; 30337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines WIN_ULONG script_tags[MAX_ITEMS]; 30437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines int item_count; 30537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 30637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines /* MinGW32 doesn't define fMergeNeutralItems, so we bruteforce */ 30737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines //bidi_control.fMergeNeutralItems = true; 30837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines *(uint32_t*)&bidi_control |= 1<<24; 30937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 31037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines bidi_state.uBidiLevel = HB_DIRECTION_IS_FORWARD (buffer->props.direction) ? 0 : 1; 31137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines bidi_state.fOverrideDirection = 1; 31237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 31337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines hr = ScriptItemizeOpenType (wchars, 31437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines chars_len, 31537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines MAX_ITEMS, 31637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines &bidi_control, 31737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines &bidi_state, 31837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines items, 31937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines script_tags, 32037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines &item_count); 32137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (unlikely (FAILED (hr))) 32237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines FAIL ("ScriptItemizeOpenType() failed: 0x%08xL", hr); 32337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 32437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#undef MAX_ITEMS 32537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 32637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines int *range_char_counts = NULL; 32737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines TEXTRANGE_PROPERTIES **range_properties = NULL; 32837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines int range_count = 0; 32937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (num_features) { 33037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines /* TODO setup ranges */ 33137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines } 33237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 33337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines OPENTYPE_TAG language_tag = hb_uint32_swap (hb_ot_tag_from_language (buffer->props.language)); 33437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines hb_tag_t buffer_script_tags[2]; 33537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines hb_ot_tags_from_script (buffer->props.script, 33637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines &buffer_script_tags[0], 33737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines &buffer_script_tags[1]); 3380c7f116bb6950ef819323d855415b2f2b0aad987Pirama Arumuga Nainar 33937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines unsigned int glyphs_offset = 0; 34037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines unsigned int glyphs_len; 34137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction); 34237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines for (unsigned int j = 0; j < item_count; j++) 34337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines { 34437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines unsigned int i = backward ? item_count - 1 - j : j; 34537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines unsigned int chars_offset = items[i].iCharPos; 34637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines unsigned int item_chars_len = items[i + 1].iCharPos - chars_offset; 34737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines 34837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines OPENTYPE_TAG script_tag; 34937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines /* We ignore what script tag Uniscribe chose, except to differentiate 35037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines * between old/new tags. Not sure if this picks DFLT up correctly... 35137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines * This also screws things up as the item.analysis also has an opaque 35237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines * script member. */ 35337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines if (script_tags[i] == hb_uint32_swap (buffer_script_tags[1])) 354ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines script_tag = hb_uint32_swap (buffer_script_tags[1]); 355ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines else 356ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines script_tag = hb_uint32_swap (buffer_script_tags[0]); 357ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 358ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines hr = ScriptShapeOpenType (font_data->hdc, 359ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines &font_data->script_cache, 360ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines &items[i].a, 361ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines script_tag, 362ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines language_tag, 363ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines range_char_counts, 364ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines range_properties, 365ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines range_count, 366ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines wchars + chars_offset, 367ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines item_chars_len, 3682e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman glyphs_size - glyphs_offset, 3692e734269e3f354e52bd9e55d791e1885aa7d4cd8Misha Brukman /* out */ 370 log_clusters + chars_offset, 371 char_props + chars_offset, 372 glyphs + glyphs_offset, 373 glyph_props + glyphs_offset, 374 (int *) &glyphs_len); 375 376 for (unsigned int j = chars_offset; j < chars_offset + item_chars_len; j++) 377 log_clusters[j] += glyphs_offset; 378 379 if (unlikely (items[i].a.fNoGlyphIndex)) 380 FAIL ("ScriptShapeOpenType() set fNoGlyphIndex"); 381 if (unlikely (hr == E_OUTOFMEMORY)) 382 { 383 buffer->ensure (buffer->allocated * 2); 384 if (buffer->in_error) 385 FAIL ("Buffer resize failed"); 386 goto retry; 387 } 388 if (unlikely (hr == USP_E_SCRIPT_NOT_IN_FONT)) 389 FAIL ("ScriptShapeOpenType() failed: Font doesn't support script"); 390 if (unlikely (FAILED (hr))) 391 FAIL ("ScriptShapeOpenType() failed: 0x%08xL", hr); 392 393 hr = ScriptPlaceOpenType (font_data->hdc, 394 &font_data->script_cache, 395 &items[i].a, 396 script_tag, 397 language_tag, 398 range_char_counts, 399 range_properties, 400 range_count, 401 wchars + chars_offset, 402 log_clusters + chars_offset, 403 char_props + chars_offset, 404 item_chars_len, 405 glyphs + glyphs_offset, 406 glyph_props + glyphs_offset, 407 glyphs_len, 408 /* out */ 409 advances + glyphs_offset, 410 offsets + glyphs_offset, 411 NULL); 412 if (unlikely (FAILED (hr))) 413 FAIL ("ScriptPlaceOpenType() failed: 0x%08xL", hr); 414 415 glyphs_offset += glyphs_len; 416 } 417 glyphs_len = glyphs_offset; 418 419 /* Ok, we've got everything we need, now compose output buffer, 420 * very, *very*, carefully! */ 421 422 /* Calculate visual-clusters. That's what we ship. */ 423 for (unsigned int i = 0; i < glyphs_len; i++) 424 vis_clusters[i] = -1; 425 for (unsigned int i = 0; i < buffer->len; i++) { 426 uint32_t *p = &vis_clusters[log_clusters[buffer->info[i].utf16_index()]]; 427 *p = MIN (*p, buffer->info[i].cluster); 428 } 429 if (!backward) { 430 for (unsigned int i = 1; i < glyphs_len; i++) 431 if (vis_clusters[i] == -1) 432 vis_clusters[i] = vis_clusters[i - 1]; 433 } else { 434 for (int i = glyphs_len - 2; i >= 0; i--) 435 if (vis_clusters[i] == -1) 436 vis_clusters[i] = vis_clusters[i + 1]; 437 } 438 439#undef utf16_index 440 441 buffer->ensure (glyphs_len); 442 if (buffer->in_error) 443 FAIL ("Buffer in error"); 444 445#undef FAIL 446 447 /* Set glyph infos */ 448 buffer->len = 0; 449 for (unsigned int i = 0; i < glyphs_len; i++) 450 { 451 hb_glyph_info_t *info = &buffer->info[buffer->len++]; 452 453 info->codepoint = glyphs[i]; 454 info->cluster = vis_clusters[i]; 455 456 /* The rest is crap. Let's store position info there for now. */ 457 info->mask = advances[i]; 458 info->var1.u32 = offsets[i].du; 459 info->var2.u32 = offsets[i].dv; 460 } 461 462 /* Set glyph positions */ 463 buffer->clear_positions (); 464 for (unsigned int i = 0; i < glyphs_len; i++) 465 { 466 hb_glyph_info_t *info = &buffer->info[i]; 467 hb_glyph_position_t *pos = &buffer->pos[i]; 468 469 /* TODO vertical */ 470 pos->x_advance = info->mask; 471 pos->x_offset = info->var1.u32; 472 pos->y_offset = info->var2.u32; 473 } 474 475 /* Wow, done! */ 476 return true; 477} 478 479 480