1 /*
2  * Copyright © 2009  Red Hat, Inc.
3  * Copyright © 2012  Google, Inc.
4  *
5  *  This is part of HarfBuzz, a text shaping library.
6  *
7  * Permission is hereby granted, without written agreement and without
8  * license or royalty fees, to use, copy, modify, and distribute this
9  * software and its documentation for any purpose, provided that the
10  * above copyright notice and the following two paragraphs appear in
11  * all copies of this software.
12  *
13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17  * DAMAGE.
18  *
19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24  *
25  * Red Hat Author(s): Behdad Esfahbod
26  * Google Author(s): Behdad Esfahbod
27  */
28 
29 #include "hb.hh"
30 
31 #include "hb-shaper.hh"
32 #include "hb-shape-plan.hh"
33 #include "hb-buffer.hh"
34 #include "hb-font.hh"
35 #include "hb-machinery.hh"
36 
37 
38 /**
39  * SECTION:hb-shape
40  * @title: hb-shape
41  * @short_description: Conversion of text strings into positioned glyphs
42  * @include: hb.h
43  *
44  * Shaping is the central operation of HarfBuzz. Shaping operates on buffers,
45  * which are sequences of Unicode characters that use the same font and have
46  * the same text direction, script, and language. After shaping the buffer
47  * contains the output glyphs and their positions.
48  **/
49 
50 
51 static inline void free_static_shaper_list ();
52 
53 static const char *nil_shaper_list[] = {nullptr};
54 
55 static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
56 							      hb_shaper_list_lazy_loader_t>
57 {
createhb_shaper_list_lazy_loader_t58   static const char ** create ()
59   {
60     const char **shaper_list = (const char **) hb_calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
61     if (unlikely (!shaper_list))
62       return nullptr;
63 
64     const hb_shaper_entry_t *shapers = _hb_shapers_get ();
65     unsigned int i;
66     for (i = 0; i < HB_SHAPERS_COUNT; i++)
67       shaper_list[i] = shapers[i].name;
68     shaper_list[i] = nullptr;
69 
70     hb_atexit (free_static_shaper_list);
71 
72     return shaper_list;
73   }
destroyhb_shaper_list_lazy_loader_t74   static void destroy (const char **l)
75   { hb_free (l); }
get_nullhb_shaper_list_lazy_loader_t76   static const char ** get_null ()
77   { return nil_shaper_list; }
78 } static_shaper_list;
79 
80 static inline
free_static_shaper_list()81 void free_static_shaper_list ()
82 {
83   static_shaper_list.free_instance ();
84 }
85 
86 
87 /**
88  * hb_shape_list_shapers:
89  *
90  * Retrieves the list of shapers supported by HarfBuzz.
91  *
92  * Return value: (transfer none) (array zero-terminated=1): an array of
93  *    constant strings
94  *
95  * Since: 0.9.2
96  **/
97 const char **
hb_shape_list_shapers()98 hb_shape_list_shapers ()
99 {
100   return static_shaper_list.get_unconst ();
101 }
102 
103 
104 /**
105  * hb_shape_full:
106  * @font: an #hb_font_t to use for shaping
107  * @buffer: an #hb_buffer_t to shape
108  * @features: (array length=num_features) (nullable): an array of user
109  *    specified #hb_feature_t or %NULL
110  * @num_features: the length of @features array
111  * @shaper_list: (array zero-terminated=1) (nullable): a %NULL-terminated
112  *    array of shapers to use or %NULL
113  *
114  * See hb_shape() for details. If @shaper_list is not %NULL, the specified
115  * shapers will be used in the given order, otherwise the default shapers list
116  * will be used.
117  *
118  * Return value: false if all shapers failed, true otherwise
119  *
120  * Since: 0.9.2
121  **/
122 hb_bool_t
hb_shape_full(hb_font_t * font,hb_buffer_t * buffer,const hb_feature_t * features,unsigned int num_features,const char * const * shaper_list)123 hb_shape_full (hb_font_t          *font,
124 	       hb_buffer_t        *buffer,
125 	       const hb_feature_t *features,
126 	       unsigned int        num_features,
127 	       const char * const *shaper_list)
128 {
129   hb_buffer_t *text_buffer = nullptr;
130   if (buffer->flags & HB_BUFFER_FLAG_VERIFY)
131   {
132     text_buffer = hb_buffer_create ();
133     hb_buffer_append (text_buffer, buffer, 0, -1);
134   }
135 
136   hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached2 (font->face, &buffer->props,
137 							      features, num_features,
138 							      font->coords, font->num_coords,
139 							      shaper_list);
140   hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
141   hb_shape_plan_destroy (shape_plan);
142 
143   if (text_buffer)
144   {
145     if (res && !buffer->verify (text_buffer,
146 				font,
147 				features,
148 				num_features,
149 				shaper_list))
150       res = false;
151     hb_buffer_destroy (text_buffer);
152   }
153 
154   return res;
155 }
156 
157 /**
158  * hb_shape:
159  * @font: an #hb_font_t to use for shaping
160  * @buffer: an #hb_buffer_t to shape
161  * @features: (array length=num_features) (nullable): an array of user
162  *    specified #hb_feature_t or %NULL
163  * @num_features: the length of @features array
164  *
165  * Shapes @buffer using @font turning its Unicode characters content to
166  * positioned glyphs. If @features is not %NULL, it will be used to control the
167  * features applied during shaping. If two @features have the same tag but
168  * overlapping ranges the value of the feature with the higher index takes
169  * precedence.
170  *
171  * Since: 0.9.2
172  **/
173 void
hb_shape(hb_font_t * font,hb_buffer_t * buffer,const hb_feature_t * features,unsigned int num_features)174 hb_shape (hb_font_t           *font,
175 	  hb_buffer_t         *buffer,
176 	  const hb_feature_t  *features,
177 	  unsigned int         num_features)
178 {
179   hb_shape_full (font, buffer, features, num_features, nullptr);
180 }
181