cff852706d210087d1326b8538e713cd6f2b55b2
[apps/home/video-player.git] / src / hb-font.cc
1 /*
2  * Copyright © 2009  Red Hat, 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  * Red Hat Author(s): Behdad Esfahbod
25  */
26
27 #include "hb-private.hh"
28
29 #include "hb-ot-layout-private.hh"
30
31 #include "hb-font-private.hh"
32 #include "hb-blob.h"
33 #include "hb-open-file-private.hh"
34
35 #include <string.h>
36
37 HB_BEGIN_DECLS
38
39
40 /*
41  * hb_font_funcs_t
42  */
43
44 static hb_bool_t
45 hb_font_get_contour_point_nil (hb_font_t *font HB_UNUSED,
46                                void *font_data HB_UNUSED,
47                                hb_codepoint_t glyph,
48                                unsigned int point_index,
49                                hb_position_t *x,
50                                hb_position_t *y,
51                                void *user_data HB_UNUSED)
52 {
53   if (font->parent) {
54     hb_bool_t ret;
55     ret = hb_font_get_contour_point (font->parent,
56                                      glyph, point_index,
57                                      x, y);
58     font->parent_scale_position (x, y);
59     return ret;
60   }
61
62   *x = *y = 0;
63
64   return false;
65 }
66
67 static void
68 hb_font_get_glyph_advance_nil (hb_font_t *font HB_UNUSED,
69                                void *font_data HB_UNUSED,
70                                hb_codepoint_t glyph,
71                                hb_position_t *x_advance,
72                                hb_position_t *y_advance,
73                                void *user_data HB_UNUSED)
74 {
75   if (font->parent) {
76     hb_font_get_glyph_advance (font->parent, glyph, x_advance, y_advance);
77     font->parent_scale_distance (x_advance, y_advance);
78     return;
79   }
80
81   *x_advance = *y_advance = 0;
82 }
83
84 static void
85 hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
86                                void *font_data HB_UNUSED,
87                                hb_codepoint_t glyph,
88                                hb_glyph_extents_t *extents,
89                                void *user_data HB_UNUSED)
90 {
91   if (font->parent) {
92     hb_font_get_glyph_extents (font->parent, glyph, extents);
93     font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
94     font->parent_scale_distance (&extents->width, &extents->height);
95     return;
96   }
97
98   extents->x_bearing = extents->y_bearing = 0;
99   extents->width = extents->height = 0;
100 }
101
102 static hb_bool_t
103 hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
104                        void *font_data HB_UNUSED,
105                        hb_codepoint_t unicode,
106                        hb_codepoint_t variation_selector,
107                        hb_codepoint_t *glyph,
108                        void *user_data HB_UNUSED)
109 {
110   if (font->parent)
111     return hb_font_get_glyph (font->parent, unicode, variation_selector, glyph);
112
113   *glyph = 0;
114   return FALSE;
115 }
116
117 static void
118 hb_font_get_kerning_nil (hb_font_t *font HB_UNUSED,
119                          void *font_data HB_UNUSED,
120                          hb_codepoint_t left_glyph,
121                          hb_codepoint_t right_glyph,
122                          hb_position_t *x_kern,
123                          hb_position_t *y_kern,
124                          void *user_data HB_UNUSED)
125 {
126   if (font->parent) {
127     hb_font_get_kerning (font->parent, left_glyph, right_glyph, x_kern, y_kern);
128     font->parent_scale_distance (x_kern, y_kern);
129     return;
130   }
131
132   *x_kern = *y_kern = 0;
133 }
134
135
136 static hb_font_funcs_t _hb_font_funcs_nil = {
137   HB_OBJECT_HEADER_STATIC,
138
139   TRUE, /* immutable */
140
141   {
142     hb_font_get_contour_point_nil,
143     hb_font_get_glyph_advance_nil,
144     hb_font_get_glyph_extents_nil,
145     hb_font_get_glyph_nil,
146     hb_font_get_kerning_nil
147   }
148 };
149
150
151 hb_font_funcs_t *
152 hb_font_funcs_create (void)
153 {
154   hb_font_funcs_t *ffuncs;
155
156   if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
157     return &_hb_font_funcs_nil;
158
159   ffuncs->get = _hb_font_funcs_nil.get;
160
161   return ffuncs;
162 }
163
164 hb_font_funcs_t *
165 hb_font_funcs_get_empty (void)
166 {
167   return &_hb_font_funcs_nil;
168 }
169
170 hb_font_funcs_t *
171 hb_font_funcs_reference (hb_font_funcs_t *ffuncs)
172 {
173   return hb_object_reference (ffuncs);
174 }
175
176 void
177 hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
178 {
179   if (!hb_object_destroy (ffuncs)) return;
180
181 #define DESTROY(name) if (ffuncs->destroy.name) ffuncs->destroy.name (ffuncs->user_data.name)
182   DESTROY (contour_point);
183   DESTROY (glyph_advance);
184   DESTROY (glyph_extents);
185   DESTROY (glyph);
186   DESTROY (kerning);
187 #undef DESTROY
188
189   free (ffuncs);
190 }
191
192 hb_bool_t
193 hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
194                              hb_user_data_key_t *key,
195                              void *              data,
196                              hb_destroy_func_t   destroy)
197 {
198   return hb_object_set_user_data (ffuncs, key, data, destroy);
199 }
200
201 void *
202 hb_font_funcs_get_user_data (hb_font_funcs_t    *ffuncs,
203                              hb_user_data_key_t *key)
204 {
205   return hb_object_get_user_data (ffuncs, key);
206 }
207
208
209 void
210 hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
211 {
212   if (hb_object_is_inert (ffuncs))
213     return;
214
215   ffuncs->immutable = TRUE;
216 }
217
218 hb_bool_t
219 hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
220 {
221   return ffuncs->immutable;
222 }
223
224
225 #define IMPLEMENT(name)                                                  \
226                                                                          \
227 void                                                                     \
228 hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
229                                  hb_font_get_##name##_func_t  func,      \
230                                  void                        *user_data, \
231                                  hb_destroy_func_t            destroy)   \
232 {                                                                        \
233   if (ffuncs->immutable)                                                 \
234     return;                                                              \
235                                                                          \
236   if (ffuncs->destroy.name)                                              \
237     ffuncs->destroy.name (ffuncs->user_data.name);                       \
238                                                                          \
239   if (func) {                                                            \
240     ffuncs->get.name = func;                                             \
241     ffuncs->user_data.name = user_data;                                  \
242     ffuncs->destroy.name = destroy;                                      \
243   } else {                                                               \
244     ffuncs->get.name = hb_font_get_##name##_nil;                         \
245     ffuncs->user_data.name = NULL;                                       \
246     ffuncs->destroy.name = NULL;                                         \
247   }                                                                      \
248 }
249
250 IMPLEMENT (contour_point);
251 IMPLEMENT (glyph_advance);
252 IMPLEMENT (glyph_extents);
253 IMPLEMENT (glyph);
254 IMPLEMENT (kerning);
255
256 #undef IMPLEMENT
257
258
259 hb_bool_t
260 hb_font_get_contour_point (hb_font_t *font,
261                            hb_codepoint_t glyph, unsigned int point_index,
262                            hb_position_t *x, hb_position_t *y)
263 {
264   *x = 0; *y = 0;
265   return font->klass->get.contour_point (font, font->user_data,
266                                          glyph, point_index,
267                                          x, y,
268                                          font->klass->user_data.contour_point);
269 }
270
271 void
272 hb_font_get_glyph_advance (hb_font_t *font,
273                            hb_codepoint_t glyph,
274                            hb_position_t *x_advance, hb_position_t *y_advance)
275 {
276   *x_advance = *y_advance = 0;
277   return font->klass->get.glyph_advance (font, font->user_data,
278                                          glyph, x_advance, y_advance,
279                                          font->klass->user_data.glyph_advance);
280 }
281
282 void
283 hb_font_get_glyph_extents (hb_font_t *font,
284                            hb_codepoint_t glyph, hb_glyph_extents_t *extents)
285 {
286   memset (extents, 0, sizeof (*extents));
287   return font->klass->get.glyph_extents (font, font->user_data,
288                                          glyph, extents,
289                                          font->klass->user_data.glyph_extents);
290 }
291
292 hb_bool_t
293 hb_font_get_glyph (hb_font_t *font,
294                    hb_codepoint_t unicode, hb_codepoint_t variation_selector,
295                    hb_codepoint_t *glyph)
296 {
297   *glyph = 0;
298   return font->klass->get.glyph (font, font->user_data,
299                                  unicode, variation_selector, glyph,
300                                  font->klass->user_data.glyph);
301 }
302
303 void
304 hb_font_get_kerning (hb_font_t *font,
305                      hb_codepoint_t left_glyph, hb_codepoint_t right_glyph,
306                      hb_position_t *x_kern, hb_position_t *y_kern)
307 {
308   *x_kern = *y_kern = 0;
309   return font->klass->get.kerning (font, font->user_data,
310                                    left_glyph, right_glyph,
311                                    x_kern, y_kern,
312                                    font->klass->user_data.kerning);
313 }
314
315
316 /*
317  * hb_face_t
318  */
319
320 static hb_face_t _hb_face_nil = {
321   HB_OBJECT_HEADER_STATIC,
322
323   TRUE, /* immutable */
324
325   NULL, /* get_table */
326   NULL, /* user_data */
327   NULL, /* destroy */
328
329   NULL, /* ot_layout */
330
331   1000
332 };
333
334
335 hb_face_t *
336 hb_face_create_for_tables (hb_get_table_func_t  get_table,
337                            void                *user_data,
338                            hb_destroy_func_t    destroy)
339 {
340   hb_face_t *face;
341
342   if (!get_table || !(face = hb_object_create<hb_face_t> ())) {
343     if (destroy)
344       destroy (user_data);
345     return &_hb_face_nil;
346   }
347
348   face->get_table = get_table;
349   face->user_data = user_data;
350   face->destroy = destroy;
351
352   face->ot_layout = _hb_ot_layout_create (face);
353
354   face->upem = _hb_ot_layout_get_upem (face);
355
356   return face;
357 }
358
359
360 typedef struct _hb_face_for_data_closure_t {
361   hb_blob_t *blob;
362   unsigned int  index;
363 } hb_face_for_data_closure_t;
364
365 static hb_face_for_data_closure_t *
366 _hb_face_for_data_closure_create (hb_blob_t *blob, unsigned int index)
367 {
368   hb_face_for_data_closure_t *closure;
369
370   closure = (hb_face_for_data_closure_t *) malloc (sizeof (hb_face_for_data_closure_t));
371   if (unlikely (!closure))
372     return NULL;
373
374   closure->blob = blob;
375   closure->index = index;
376
377   return closure;
378 }
379
380 static void
381 _hb_face_for_data_closure_destroy (hb_face_for_data_closure_t *closure)
382 {
383   hb_blob_destroy (closure->blob);
384   free (closure);
385 }
386
387 static hb_blob_t *
388 _hb_face_for_data_get_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
389 {
390   hb_face_for_data_closure_t *data = (hb_face_for_data_closure_t *) user_data;
391
392   const OpenTypeFontFile &ot_file = *Sanitizer<OpenTypeFontFile>::lock_instance (data->blob);
393   const OpenTypeFontFace &ot_face = ot_file.get_face (data->index);
394
395   const OpenTypeTable &table = ot_face.get_table_by_tag (tag);
396
397   hb_blob_t *blob = hb_blob_create_sub_blob (data->blob, table.offset, table.length);
398
399   return blob;
400 }
401
402 hb_face_t *
403 hb_face_create (hb_blob_t    *blob,
404                 unsigned int  index)
405 {
406   if (unlikely (!blob || !hb_blob_get_length (blob)))
407     return &_hb_face_nil;
408
409   hb_face_for_data_closure_t *closure = _hb_face_for_data_closure_create (Sanitizer<OpenTypeFontFile>::sanitize (hb_blob_reference (blob)), index);
410
411   if (unlikely (!closure))
412     return &_hb_face_nil;
413
414   return hb_face_create_for_tables (_hb_face_for_data_get_table,
415                                     closure,
416                                     (hb_destroy_func_t) _hb_face_for_data_closure_destroy);
417 }
418
419 hb_face_t *
420 hb_face_get_empty (void)
421 {
422   return &_hb_face_nil;
423 }
424
425
426 hb_face_t *
427 hb_face_reference (hb_face_t *face)
428 {
429   return hb_object_reference (face);
430 }
431
432 void
433 hb_face_destroy (hb_face_t *face)
434 {
435   if (!hb_object_destroy (face)) return;
436
437   _hb_ot_layout_destroy (face->ot_layout);
438
439   if (face->destroy)
440     face->destroy (face->user_data);
441
442   free (face);
443 }
444
445 hb_bool_t
446 hb_face_set_user_data (hb_face_t          *face,
447                        hb_user_data_key_t *key,
448                        void *              data,
449                        hb_destroy_func_t   destroy)
450 {
451   return hb_object_set_user_data (face, key, data, destroy);
452 }
453
454 void *
455 hb_face_get_user_data (hb_face_t          *face,
456                        hb_user_data_key_t *key)
457 {
458   return hb_object_get_user_data (face, key);
459 }
460
461 void
462 hb_face_make_immutable (hb_face_t *face)
463 {
464   if (hb_object_is_inert (face))
465     return;
466
467   face->immutable = true;
468 }
469
470 hb_bool_t
471 hb_face_is_immutable (hb_face_t *face)
472 {
473   return face->immutable;
474 }
475
476
477 hb_blob_t *
478 hb_face_reference_table (hb_face_t *face,
479                          hb_tag_t   tag)
480 {
481   hb_blob_t *blob;
482
483   if (unlikely (!face || !face->get_table))
484     return hb_blob_get_empty ();
485
486   blob = face->get_table (face, tag, face->user_data);
487   if (unlikely (!blob))
488     return hb_blob_get_empty ();
489
490   return blob;
491 }
492
493 unsigned int
494 hb_face_get_upem (hb_face_t *face)
495 {
496   return _hb_ot_layout_get_upem (face);
497 }
498
499
500 /*
501  * hb_font_t
502  */
503
504 static hb_font_t _hb_font_nil = {
505   HB_OBJECT_HEADER_STATIC,
506
507   TRUE, /* immutable */
508
509   NULL, /* parent */
510   &_hb_face_nil,
511
512   0, /* x_scale */
513   0, /* y_scale */
514
515   0, /* x_ppem */
516   0, /* y_ppem */
517
518   &_hb_font_funcs_nil, /* klass */
519   NULL, /* user_data */
520   NULL  /* destroy */
521 };
522
523 hb_font_t *
524 hb_font_create (hb_face_t *face)
525 {
526   hb_font_t *font;
527
528   if (unlikely (!face))
529     face = &_hb_face_nil;
530   if (unlikely (hb_object_is_inert (face)))
531     return &_hb_font_nil;
532   if (!(font = hb_object_create<hb_font_t> ()))
533     return &_hb_font_nil;
534
535   hb_face_make_immutable (face);
536   font->face = hb_face_reference (face);
537   font->klass = &_hb_font_funcs_nil;
538
539   return font;
540 }
541
542 hb_font_t *
543 hb_font_create_sub_font (hb_font_t *parent)
544 {
545   if (unlikely (!parent))
546     return &_hb_font_nil;
547
548   hb_font_t *font = hb_font_create (parent->face);
549
550   if (unlikely (hb_object_is_inert (font)))
551     return font;
552
553   hb_font_make_immutable (parent);
554   font->parent = hb_font_reference (parent);
555
556   font->x_scale = parent->x_scale;
557   font->y_scale = parent->y_scale;
558   font->x_ppem = parent->x_ppem;
559   font->y_ppem = parent->y_ppem;
560
561   font->klass = &_hb_font_funcs_nil;
562
563   return font;
564 }
565
566 hb_font_t *
567 hb_font_get_empty (void)
568 {
569   return &_hb_font_nil;
570 }
571
572 hb_font_t *
573 hb_font_reference (hb_font_t *font)
574 {
575   return hb_object_reference (font);
576 }
577
578 void
579 hb_font_destroy (hb_font_t *font)
580 {
581   if (!hb_object_destroy (font)) return;
582
583   hb_font_destroy (font->parent);
584   hb_face_destroy (font->face);
585   hb_font_funcs_destroy (font->klass);
586   if (font->destroy)
587     font->destroy (font->user_data);
588
589   free (font);
590 }
591
592 hb_bool_t
593 hb_font_set_user_data (hb_font_t          *font,
594                        hb_user_data_key_t *key,
595                        void *              data,
596                        hb_destroy_func_t   destroy)
597 {
598   return hb_object_set_user_data (font, key, data, destroy);
599 }
600
601 void *
602 hb_font_get_user_data (hb_font_t          *font,
603                        hb_user_data_key_t *key)
604 {
605   return hb_object_get_user_data (font, key);
606 }
607
608 void
609 hb_font_make_immutable (hb_font_t *font)
610 {
611   if (hb_object_is_inert (font))
612     return;
613
614   font->immutable = true;
615 }
616
617 hb_bool_t
618 hb_font_is_immutable (hb_font_t *font)
619 {
620   return font->immutable;
621 }
622
623 hb_font_t *
624 hb_font_get_parent (hb_font_t *font)
625 {
626   return font->parent;
627 }
628
629 hb_face_t *
630 hb_font_get_face (hb_font_t *font)
631 {
632   return font->face;
633 }
634
635
636 void
637 hb_font_set_funcs (hb_font_t         *font,
638                    hb_font_funcs_t   *klass,
639                    void              *user_data,
640                    hb_destroy_func_t  destroy)
641 {
642   if (font->immutable)
643     return;
644
645   if (font->destroy)
646     font->destroy (font->user_data);
647
648   if (!klass)
649     klass = &_hb_font_funcs_nil;
650
651   hb_font_funcs_reference (klass);
652   hb_font_funcs_destroy (font->klass);
653   font->klass = klass;
654   font->user_data = user_data;
655   font->destroy = destroy;
656 }
657
658
659 void
660 hb_font_set_scale (hb_font_t *font,
661                    int x_scale,
662                    int y_scale)
663 {
664   if (font->immutable)
665     return;
666
667   font->x_scale = x_scale;
668   font->y_scale = y_scale;
669 }
670
671 void
672 hb_font_get_scale (hb_font_t *font,
673                    int *x_scale,
674                    int *y_scale)
675 {
676   if (x_scale) *x_scale = font->x_scale;
677   if (y_scale) *y_scale = font->y_scale;
678 }
679
680 void
681 hb_font_set_ppem (hb_font_t *font,
682                   unsigned int x_ppem,
683                   unsigned int y_ppem)
684 {
685   if (font->immutable)
686     return;
687
688   font->x_ppem = x_ppem;
689   font->y_ppem = y_ppem;
690 }
691
692 void
693 hb_font_get_ppem (hb_font_t *font,
694                   unsigned int *x_ppem,
695                   unsigned int *y_ppem)
696 {
697   if (x_ppem) *x_ppem = font->x_ppem;
698   if (y_ppem) *y_ppem = font->y_ppem;
699 }
700
701
702 HB_END_DECLS