2 * Copyright © 2012 Google, Inc.
4 * This is part of HarfBuzz, a text shaping library.
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.
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
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.
24 * Google Author(s): Behdad Esfahbod
27 #define HB_SHAPER icu_le
28 #define hb_icu_le_shaper_font_data_t PortableFontInstance
29 #include "hb-shaper-impl-private.hh"
31 #include "hb-icu-le/PortableFontInstance.h"
33 #include "layout/loengine.h"
34 #include "unicode/unistr.h"
43 struct hb_icu_le_shaper_face_data_t
{};
45 hb_icu_le_shaper_face_data_t
*
46 _hb_icu_le_shaper_face_data_create (hb_face_t
*face HB_UNUSED
)
48 return (hb_icu_le_shaper_face_data_t
*) HB_SHAPER_DATA_SUCCEEDED
;
52 _hb_icu_le_shaper_face_data_destroy (hb_icu_le_shaper_face_data_t
*data HB_UNUSED
)
61 hb_icu_le_shaper_font_data_t
*
62 _hb_icu_le_shaper_font_data_create (hb_font_t
*font
)
64 LEErrorCode status
= LE_NO_ERROR
;
65 hb_icu_le_shaper_font_data_t
*data
= new PortableFontInstance (font
->face
,
69 if (status
!= LE_NO_ERROR
) {
78 _hb_icu_le_shaper_font_data_destroy (hb_icu_le_shaper_font_data_t
*data
)
85 * shaper shape_plan data
88 struct hb_icu_le_shaper_shape_plan_data_t
{};
90 hb_icu_le_shaper_shape_plan_data_t
*
91 _hb_icu_le_shaper_shape_plan_data_create (hb_shape_plan_t
*shape_plan HB_UNUSED
,
92 const hb_feature_t
*user_features
,
93 unsigned int num_user_features
)
95 return (hb_icu_le_shaper_shape_plan_data_t
*) HB_SHAPER_DATA_SUCCEEDED
;
99 _hb_icu_le_shaper_shape_plan_data_destroy (hb_icu_le_shaper_shape_plan_data_t
*data
)
109 _hb_icu_le_shape (hb_shape_plan_t
*shape_plan
,
112 const hb_feature_t
*features
,
113 unsigned int num_features
)
115 LEFontInstance
*font_instance
= HB_SHAPER_DATA_GET (font
);
116 le_int32 script_code
= hb_icu_script_from_script (shape_plan
->props
.script
);
117 le_int32 language_code
= -1 /* TODO */;
118 le_int32 typography_flags
= 3; /* Needed for ligatures and kerning */
119 LEErrorCode status
= LE_NO_ERROR
;
120 le_engine
*le
= le_create ((const le_font
*) font_instance
,
125 if (status
!= LE_NO_ERROR
)
126 { le_close (le
); return false; }
130 unsigned int scratch_size
;
131 char *scratch
= (char *) buffer
->get_scratch_buffer (&scratch_size
);
133 #define ALLOCATE_ARRAY(Type, name, len) \
134 Type *name = (Type *) scratch; \
135 scratch += (len) * sizeof ((name)[0]); \
136 scratch_size -= (len) * sizeof ((name)[0]);
138 ALLOCATE_ARRAY (LEUnicode
, chars
, buffer
->len
);
139 ALLOCATE_ARRAY (unsigned int, clusters
, buffer
->len
);
141 /* XXX Use UTF-16 decoder! */
142 for (unsigned int i
= 0; i
< buffer
->len
; i
++) {
143 chars
[i
] = buffer
->info
[i
].codepoint
;
144 clusters
[i
] = buffer
->info
[i
].cluster
;
147 unsigned int glyph_count
= le_layoutChars (le
,
152 HB_DIRECTION_IS_BACKWARD (buffer
->props
.direction
),
155 if (status
!= LE_NO_ERROR
)
156 { le_close (le
); return false; }
158 unsigned int num_glyphs
= scratch_size
/ (sizeof (LEGlyphID
) +
162 if (unlikely (glyph_count
>= num_glyphs
|| glyph_count
> buffer
->allocated
)) {
163 buffer
->ensure (buffer
->allocated
* 2);
164 if (buffer
->in_error
)
165 { le_close (le
); return false; }
169 ALLOCATE_ARRAY (LEGlyphID
, glyphs
, glyph_count
);
170 ALLOCATE_ARRAY (le_int32
, indices
, glyph_count
);
171 ALLOCATE_ARRAY (float, positions
, glyph_count
* 2 + 2);
173 le_getGlyphs (le
, glyphs
, &status
);
174 le_getCharIndices (le
, indices
, &status
);
175 le_getGlyphPositions (le
, positions
, &status
);
177 #undef ALLOCATE_ARRAY
179 /* Ok, we've got everything we need, now compose output buffer,
180 * very, *very*, carefully! */
183 hb_glyph_info_t
*info
= buffer
->info
;
184 for (unsigned int i
= 0; i
< glyph_count
; i
++)
186 if (glyphs
[i
] >= 0xFFFE)
189 info
[j
].codepoint
= glyphs
[i
];
190 info
[j
].cluster
= clusters
[indices
[i
]];
192 /* icu-le doesn't seem to have separate advance values. */
193 info
[j
].mask
= positions
[2 * i
+ 2] - positions
[2 * i
];
194 info
[j
].var1
.u32
= 0;
195 info
[j
].var2
.u32
= -positions
[2 * i
+ 1];
201 buffer
->clear_positions ();
203 for (unsigned int i
= 0; i
< buffer
->len
; i
++) {
204 hb_glyph_info_t
*info
= &buffer
->info
[i
];
205 hb_glyph_position_t
*pos
= &buffer
->pos
[i
];
208 pos
->x_advance
= info
->mask
;
209 pos
->x_offset
= info
->var1
.u32
;
210 pos
->y_offset
= info
->var2
.u32
;