1 /* 2 * Copyright 2014 Google, Inc. 3 * 4 * This is part of HarfBuzz, a text shaping library. 5 * 6 * Permission is hereby granted, without written agreement and without 7 * license or royalty fees, to use, copy, modify, and distribute this 8 * software and its documentation for any purpose, provided that the 9 * above copyright notice and the following two paragraphs appear in 10 * all copies of this software. 11 * 12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16 * DAMAGE. 17 * 18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23 * 24 * Google Author(s): Behdad Esfahbod 25 */ 26 27 #include <stdlib.h> 28 #include <stdio.h> 29 30 #include "hb-fc.h" 31 32 static hb_bool_t 33 hb_fc_get_glyph (hb_font_t *font /*HB_UNUSED*/, 34 void *font_data, 35 hb_codepoint_t unicode, 36 hb_codepoint_t variation_selector, 37 hb_codepoint_t *glyph, 38 void *user_data /*HB_UNUSED*/) 39 40 { 41 FcCharSet *cs = (FcCharSet *) font_data; 42 43 if (variation_selector) 44 { 45 /* Fontconfig doesn't cache cmap-14 info. However: 46 * 1. If the font maps the variation_selector, assume it's 47 * supported, 48 * 2. If the font doesn't map it, still say it's supported, 49 * but return 0. This way, the caller will see the zero 50 * and reject. If we return unsupported here, then the 51 * variation selector will be hidden and ignored. 52 */ 53 if (FcCharSetHasChar (cs, unicode) && 54 FcCharSetHasChar (cs, variation_selector)) 55 { 56 unsigned int var_num = 0; 57 if (variation_selector - 0xFE00u < 16) 58 var_num = variation_selector - 0xFE00 + 1; 59 else if (variation_selector - 0xE0100u < (256 - 16)) 60 var_num = variation_selector - 0xE0100 + 17; 61 *glyph = (var_num << 21) | unicode; 62 } 63 else 64 { 65 *glyph = 0; 66 } 67 return true; 68 } 69 70 *glyph = FcCharSetHasChar (cs, unicode) ? unicode : 0; 71 return *glyph != 0; 72 } 73 74 static hb_font_funcs_t * 75 _hb_fc_get_font_funcs (void) 76 { 77 static const hb_font_funcs_t *fc_ffuncs; 78 79 const hb_font_funcs_t *ffuncs; 80 81 if (!(ffuncs = fc_ffuncs)) 82 { 83 hb_font_funcs_t *newfuncs = hb_font_funcs_create (); 84 85 hb_font_funcs_set_glyph_func (newfuncs, hb_fc_get_glyph, NULL, NULL); 86 87 /* XXX MT-unsafe */ 88 if (fc_ffuncs) 89 hb_font_funcs_destroy (newfuncs); 90 else 91 fc_ffuncs = ffuncs = newfuncs; 92 } 93 94 return const_cast<hb_font_funcs_t *> (fc_ffuncs); 95 } 96 97 98 hb_font_t * 99 hb_fc_font_create (FcPattern *fcfont) 100 { 101 static hb_face_t *face; 102 hb_font_t *font; 103 104 FcCharSet *cs; 105 if (FcResultMatch != FcPatternGetCharSet (fcfont, FC_CHARSET, 0, &cs)) 106 return hb_font_get_empty (); 107 108 if (!face) /* XXX MT-unsafe */ 109 face = hb_face_create (hb_blob_get_empty (), 0); 110 111 font = hb_font_create (face); 112 113 hb_font_set_funcs (font, 114 _hb_fc_get_font_funcs (), 115 FcCharSetCopy (cs), 116 (hb_destroy_func_t) FcCharSetDestroy); 117 118 return font; 119 } 120 121 hb_bool_t 122 hb_fc_can_render (hb_font_t *font, const char *text) 123 { 124 static const char *ot[] = {"ot", NULL}; 125 126 hb_buffer_t *buffer = hb_buffer_create (); 127 hb_buffer_add_utf8 (buffer, text, -1, 0, -1); 128 129 /* XXX Do we need this? I think Arabic and Hangul shapers are the 130 * only one that make any use of this. The Hangul case is not really 131 * needed, and for Arabic we'll miss a very narrow set of fonts. 132 * Might be better to force generic shaper perhaps. */ 133 hb_buffer_guess_segment_properties (buffer); 134 135 if (!hb_shape_full (font, buffer, NULL, 0, ot)) 136 abort (); /* hb-ot shaper not enabled? */ 137 138 unsigned int len; 139 hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &len); 140 for (unsigned int i = 0; i < len; i++) 141 { 142 if (!info[i].codepoint) 143 { 144 return false; 145 } 146 } 147 148 return true; 149 } 150