2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
4 * This is part of HarfBuzz, an OpenType Layout engine 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.
25 #include "harfbuzz-shaper.h"
26 #include "harfbuzz-shaper-private.h"
30 static const HB_OpenTypeFeature greek_features[] = {
31 { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },
32 { HB_MAKE_TAG('l', 'i', 'g', 'a'), CcmpProperty },
33 { HB_MAKE_TAG('c', 'l', 'i', 'g'), CcmpProperty },
43 typedef struct _hb_greek_decomposition {
46 } hb_greek_decomposition;
48 static const hb_greek_decomposition decompose_0x300[] = {
69 static HB_UChar16 compose_0x300(HB_UChar16 base)
71 if ((base ^ 0x1f00) < 0x100) {
72 if (base <= 0x1f69 && !(base & 0x6))
81 const hb_greek_decomposition *d = decompose_0x300;
82 while (d->base && d->base != base)
88 static const hb_greek_decomposition decompose_0x301[] = {
110 static HB_UChar16 compose_0x301(HB_UChar16 base)
112 if ((base ^ 0x1f00) < 0x100) {
113 if (base <= 0x1f69 && !(base & 0x6))
121 const hb_greek_decomposition *d = decompose_0x301;
122 while (d->base && d->base != base)
128 static const hb_greek_decomposition decompose_0x304[] = {
138 static HB_UChar16 compose_0x304(HB_UChar16 base)
140 const hb_greek_decomposition *d = decompose_0x304;
141 while (d->base && d->base != base)
146 static const hb_greek_decomposition decompose_0x306[] = {
156 static HB_UChar16 compose_0x306(HB_UChar16 base)
158 const hb_greek_decomposition *d = decompose_0x306;
159 while (d->base && d->base != base)
164 static const hb_greek_decomposition decompose_0x308[] = {
173 static HB_UChar16 compose_0x308(HB_UChar16 base)
175 const hb_greek_decomposition *d = decompose_0x308;
176 while (d->base && d->base != base)
182 static const hb_greek_decomposition decompose_0x313[] = {
200 static HB_UChar16 compose_0x313(HB_UChar16 base)
202 const hb_greek_decomposition *d = decompose_0x313;
203 while (d->base && d->base != base)
208 static const hb_greek_decomposition decompose_0x314[] = {
228 static HB_UChar16 compose_0x314(HB_UChar16 base)
230 const hb_greek_decomposition *d = decompose_0x314;
231 while (d->base && d->base != base)
236 static const hb_greek_decomposition decompose_0x342[] = {
268 static HB_UChar16 compose_0x342(HB_UChar16 base)
270 const hb_greek_decomposition *d = decompose_0x342;
271 while (d->base && d->base != base)
276 static const hb_greek_decomposition decompose_0x345[] = {
343 static HB_UChar16 compose_0x345(HB_UChar16 base)
345 const hb_greek_decomposition *d = decompose_0x345;
346 while (d->base && d->base != base)
352 Greek shaping. Heuristic positioning can't render polytonic greek correctly. We're a lot
353 better off mapping greek chars with diacritics to the characters in the extended greek
354 region in Unicode if possible.
356 HB_Bool HB_GreekShape(HB_ShaperItem *shaper_item)
358 const int availableGlyphs = shaper_item->num_glyphs;
359 const HB_UChar16 *uc = shaper_item->string + shaper_item->item.pos;
360 unsigned short *logClusters = shaper_item->log_clusters;
361 HB_GlyphAttributes *attributes = shaper_item->attributes;
365 int cluster_start = 0;
368 HB_STACKARRAY(HB_UChar16, shapedChars, 2 * shaper_item->item.length);
370 assert(shaper_item->item.script == HB_Script_Greek);
375 for (i = 1; i < shaper_item->item.length; ++i) {
376 hb_uint16 base = shapedChars[slen-1];
377 hb_uint16 shaped = 0;
379 shaped = compose_0x300(base);
380 else if (uc[i] == 0x301)
381 shaped = compose_0x301(base);
382 else if (uc[i] == 0x304)
383 shaped = compose_0x304(base);
384 else if (uc[i] == 0x306)
385 shaped = compose_0x306(base);
386 else if (uc[i] == 0x308)
387 shaped = compose_0x308(base);
388 else if (uc[i] == 0x313)
389 shaped = compose_0x313(base);
390 else if (uc[i] == 0x314)
391 shaped = compose_0x314(base);
392 else if (uc[i] == 0x342)
393 shaped = compose_0x342(base);
394 else if (uc[i] == 0x345)
395 shaped = compose_0x345(base);
398 if (shaper_item->font->klass->canRender(shaper_item->font, (HB_UChar16 *)&shaped, 1)) {
399 shapedChars[slen-1] = shaped;
406 HB_CharCategory category;
408 shapedChars[slen] = uc[i];
409 HB_GetUnicodeCharProperties(uc[i], &category, &cmb);
410 if (category != HB_Mark_NonSpacing) {
411 attributes[slen].clusterStart = TRUE;
412 attributes[slen].mark = FALSE;
413 attributes[slen].combiningClass = 0;
414 attributes[slen].dontPrint = HB_IsControlChar(uc[i]);
415 cluster_start = slen;
417 attributes[slen].clusterStart = FALSE;
418 attributes[slen].mark = TRUE;
419 attributes[slen].combiningClass = cmb;
423 logClusters[i] = cluster_start;
426 haveGlyphs = shaper_item->font->klass
427 ->convertStringToGlyphIndices(shaper_item->font,
429 shaper_item->glyphs, &shaper_item->num_glyphs,
430 shaper_item->item.bidiLevel % 2);
432 HB_FREE_STACKARRAY(shapedChars);
438 if (HB_SelectScript(shaper_item, greek_features)) {
439 HB_OpenTypeShape(shaper_item, /*properties*/0);
440 return HB_OpenTypePosition(shaper_item, availableGlyphs, /*doLogClusters*/TRUE);
443 HB_HeuristicPosition(shaper_item);