Removed header file from dev package
[framework/uifw/harfbuzz.git] / harfbuzz-0.1 / src / harfbuzz-hebrew.c
1 /*
2  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
3  *
4  * This is part of HarfBuzz, an OpenType Layout engine 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
25 #include "harfbuzz-shaper.h"
26 #include "harfbuzz-shaper-private.h"
27 #include <assert.h>
28
29 /*
30 // Uniscribe also defines dlig for Hebrew, but we leave this out for now, as it's mostly
31 // ligatures one does not want in modern Hebrew (as lam-alef ligatures).
32 */
33 #ifndef NO_OPENTYPE
34 static const HB_OpenTypeFeature hebrew_features[] = {
35     { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },
36     {0, 0}
37 };
38 #endif
39
40 /* Hebrew shaping. In the non opentype case we try to use the
41    presentation forms specified for Hebrew. Especially for the
42    ligatures with Dagesh this gives much better results than we could
43    achieve manually.
44 */
45 HB_Bool HB_HebrewShape(HB_ShaperItem *shaper_item)
46 {
47     enum {
48         Dagesh = 0x5bc,
49         ShinDot = 0x5c1,
50         SinDot = 0x5c2,
51         Patah = 0x5b7,
52         Qamats = 0x5b8,
53         Holam = 0x5b9,
54         Rafe = 0x5bf
55     };
56
57     assert(shaper_item->item.script == HB_Script_Hebrew);
58
59     HB_HeuristicSetGlyphAttributes(shaper_item);
60
61 #ifndef NO_OPENTYPE
62     if (HB_SelectScript(shaper_item, hebrew_features)) {
63
64         const int availableGlyphs = shaper_item->num_glyphs;
65         if (!HB_ConvertStringToGlyphIndices(shaper_item))
66             return FALSE;
67
68
69         HB_OpenTypeShape(shaper_item, /*properties*/0);
70         return HB_OpenTypePosition(shaper_item, availableGlyphs, /*doLogClusters*/TRUE);
71     }
72 #endif
73
74     {
75         const HB_UChar16 *uc = shaper_item->string + shaper_item->item.pos;
76         unsigned short *logClusters = shaper_item->log_clusters;
77         HB_GlyphAttributes *attributes = shaper_item->attributes;
78
79         HB_Bool haveGlyphs;
80         int slen = 1;
81         int cluster_start = 0;
82         hb_uint32 i;
83
84         HB_STACKARRAY(HB_UChar16, shapedChars, 2 * shaper_item->item.length);
85         *shapedChars = *uc;
86         logClusters[0] = 0;
87
88         for (i = 1; i < shaper_item->item.length; ++i) {
89             hb_uint16 base = shapedChars[slen-1];
90             hb_uint16 shaped = 0;
91             HB_Bool invalid = FALSE;
92             if (uc[i] == Dagesh) {
93                 if (base >= 0x5d0
94                     && base <= 0x5ea
95                     && base != 0x5d7
96                     && base != 0x5dd
97                     && base != 0x5df
98                     && base != 0x5e2
99                     && base != 0x5e5) {
100                     shaped = base - 0x5d0 + 0xfb30;
101                 } else if (base == 0xfb2a || base == 0xfb2b /* Shin with Shin or Sin dot */) {
102                     shaped = base + 2;
103                 } else {
104                     invalid = TRUE;
105                 }
106             } else if (uc[i] == ShinDot) {
107                 if (base == 0x05e9)
108                     shaped = 0xfb2a;
109                 else if (base == 0xfb49)
110                     shaped = 0xfb2c;
111                 else
112                     invalid = TRUE;
113             } else if (uc[i] == SinDot) {
114                 if (base == 0x05e9)
115                     shaped = 0xfb2b;
116                 else if (base == 0xfb49)
117                     shaped = 0xfb2d;
118                 else
119                     invalid = TRUE;
120             } else if (uc[i] == Patah) {
121                 if (base == 0x5d0)
122                     shaped = 0xfb2e;
123             } else if (uc[i] == Qamats) {
124                 if (base == 0x5d0)
125                     shaped = 0xfb2f;
126             } else if (uc[i] == Holam) {
127                 if (base == 0x5d5)
128                     shaped = 0xfb4b;
129             } else if (uc[i] == Rafe) {
130                 if (base == 0x5d1)
131                     shaped = 0xfb4c;
132                 else if (base == 0x5db)
133                     shaped = 0xfb4d;
134                 else if (base == 0x5e4)
135                     shaped = 0xfb4e;
136             }
137
138             if (invalid) {
139                 shapedChars[slen] = 0x25cc;
140                 attributes[slen].clusterStart = TRUE;
141                 attributes[slen].mark = FALSE;
142                 attributes[slen].combiningClass = 0;
143                 cluster_start = slen;
144                 ++slen;
145             }
146             if (shaped) {
147                 if (shaper_item->font->klass->canRender(shaper_item->font, (HB_UChar16 *)&shaped, 1)) {
148                     shapedChars[slen-1] = shaped;
149                 } else
150                     shaped = 0;
151             }
152             if (!shaped) {
153                 HB_CharCategory category;
154                 int cmb;
155                 shapedChars[slen] = uc[i];
156                 HB_GetUnicodeCharProperties(uc[i], &category, &cmb);
157                 if (category != HB_Mark_NonSpacing) {
158                     attributes[slen].clusterStart = TRUE;
159                     attributes[slen].mark = FALSE;
160                     attributes[slen].combiningClass = 0;
161                     attributes[slen].dontPrint = HB_IsControlChar(uc[i]);
162                     cluster_start = slen;
163                 } else {
164                     attributes[slen].clusterStart = FALSE;
165                     attributes[slen].mark = TRUE;
166                     attributes[slen].combiningClass = cmb;
167                 }
168                 ++slen;
169             }
170             logClusters[i] = cluster_start;
171         }
172
173         haveGlyphs = shaper_item->font->klass
174             ->convertStringToGlyphIndices(shaper_item->font,
175                                           shapedChars, slen,
176                                           shaper_item->glyphs, &shaper_item->num_glyphs,
177                                           shaper_item->item.bidiLevel % 2);
178
179         HB_FREE_STACKARRAY(shapedChars);
180
181         if (!haveGlyphs)
182             return FALSE;
183
184         HB_HeuristicPosition(shaper_item);
185     }
186
187     return TRUE;
188 }
189