Imported Upstream version 3.4.0
[platform/upstream/harfbuzz.git] / src / hb-shape.cc
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 {
58   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   }
74   static void destroy (const char **l)
75   { hb_free (l); }
76   static const char ** get_null ()
77   { return nil_shaper_list; }
78 } static_shaper_list;
79
80 static inline
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 **
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
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
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 }