Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 1 | /* |
Behdad Esfahbod | 6f425b1 | 2008-01-24 19:38:56 -0500 | [diff] [blame] | 2 | * Copyright (C) 1998-2004 David Turner and Werner Lemberg |
| 3 | * Copyright (C) 2006 Behdad Esfahbod |
Behdad Esfahbod | ee58aae | 2009-05-17 05:14:33 -0400 | [diff] [blame] | 4 | * Copyright (C) 2007,2008,2009 Red Hat, Inc. |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 5 | * |
| 6 | * This is part of HarfBuzz, an OpenType Layout engine library. |
| 7 | * |
| 8 | * Permission is hereby granted, without written agreement and without |
| 9 | * license or royalty fees, to use, copy, modify, and distribute this |
| 10 | * software and its documentation for any purpose, provided that the |
| 11 | * above copyright notice and the following two paragraphs appear in |
| 12 | * all copies of this software. |
| 13 | * |
| 14 | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
| 15 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
| 16 | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
| 17 | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
| 18 | * DAMAGE. |
| 19 | * |
| 20 | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
| 21 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
| 22 | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
| 23 | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
| 24 | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| 25 | * |
| 26 | * Red Hat Author(s): Behdad Esfahbod |
| 27 | */ |
| 28 | |
| 29 | #define HB_OT_LAYOUT_CC |
| 30 | |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 31 | #include "hb-ot-layout-private.h" |
| 32 | |
Behdad Esfahbod | 5f5b24f | 2009-08-02 20:03:12 -0400 | [diff] [blame] | 33 | #include "hb-ot-layout-gdef-private.hh" |
| 34 | #include "hb-ot-layout-gsub-private.hh" |
| 35 | #include "hb-ot-layout-gpos-private.hh" |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 36 | |
Behdad Esfahbod | 6f425b1 | 2008-01-24 19:38:56 -0500 | [diff] [blame] | 37 | |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 38 | #include <stdlib.h> |
Behdad Esfahbod | aff831e | 2008-01-24 06:03:45 -0500 | [diff] [blame] | 39 | #include <string.h> |
| 40 | |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 41 | |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 42 | void |
Behdad Esfahbod | 70e0f2a | 2009-08-03 22:01:47 -0400 | [diff] [blame] | 43 | _hb_ot_layout_init (hb_face_t *face) |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 44 | { |
Behdad Esfahbod | 70e0f2a | 2009-08-03 22:01:47 -0400 | [diff] [blame] | 45 | hb_ot_layout_t *layout = &face->ot_layout; |
| 46 | |
| 47 | /* XXX sanitize */ |
| 48 | |
| 49 | layout->gdef_blob = hb_face_get_table (face, HB_OT_TAG_GDEF); |
| 50 | layout->gdef = &GDEF::get_for_data (hb_blob_lock (layout->gdef_blob)); |
| 51 | |
| 52 | layout->gsub_blob = hb_face_get_table (face, HB_OT_TAG_GSUB); |
| 53 | layout->gsub = &GSUB::get_for_data (hb_blob_lock (layout->gsub_blob)); |
| 54 | |
| 55 | layout->gpos_blob = hb_face_get_table (face, HB_OT_TAG_GPOS); |
| 56 | layout->gpos = &GPOS::get_for_data (hb_blob_lock (layout->gpos_blob)); |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 57 | } |
| 58 | |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 59 | void |
Behdad Esfahbod | 70e0f2a | 2009-08-03 22:01:47 -0400 | [diff] [blame] | 60 | _hb_ot_layout_fini (hb_face_t *face) |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 61 | { |
Behdad Esfahbod | 70e0f2a | 2009-08-03 22:01:47 -0400 | [diff] [blame] | 62 | hb_ot_layout_t *layout = &face->ot_layout; |
Behdad Esfahbod | fd92a3d | 2008-01-24 03:11:09 -0500 | [diff] [blame] | 63 | |
Behdad Esfahbod | 70e0f2a | 2009-08-03 22:01:47 -0400 | [diff] [blame] | 64 | hb_blob_unlock (layout->gdef_blob); |
| 65 | hb_blob_unlock (layout->gsub_blob); |
| 66 | hb_blob_unlock (layout->gpos_blob); |
| 67 | |
| 68 | hb_blob_destroy (layout->gdef_blob); |
| 69 | hb_blob_destroy (layout->gsub_blob); |
| 70 | hb_blob_destroy (layout->gpos_blob); |
Behdad Esfahbod | 679f41f | 2009-08-04 21:32:06 -0400 | [diff] [blame^] | 71 | |
| 72 | free (layout->new_gdef.klasses); |
Behdad Esfahbod | 2ebb89d | 2009-07-25 19:09:01 -0400 | [diff] [blame] | 73 | } |
| 74 | |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 75 | static const GDEF& |
| 76 | _get_gdef (hb_face_t *face) |
| 77 | { |
Behdad Esfahbod | 70e0f2a | 2009-08-03 22:01:47 -0400 | [diff] [blame] | 78 | return HB_LIKELY (face->ot_layout.gdef) ? *face->ot_layout.gdef : Null(GDEF); |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 79 | } |
| 80 | |
| 81 | static const GSUB& |
| 82 | _get_gsub (hb_face_t *face) |
| 83 | { |
Behdad Esfahbod | 70e0f2a | 2009-08-03 22:01:47 -0400 | [diff] [blame] | 84 | return HB_LIKELY (face->ot_layout.gsub) ? *face->ot_layout.gsub : Null(GSUB); |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 85 | } |
| 86 | |
| 87 | static const GPOS& |
| 88 | _get_gpos (hb_face_t *face) |
| 89 | { |
Behdad Esfahbod | 70e0f2a | 2009-08-03 22:01:47 -0400 | [diff] [blame] | 90 | return HB_LIKELY (face->ot_layout.gpos) ? *face->ot_layout.gpos : Null(GPOS); |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 91 | } |
| 92 | |
| 93 | |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 94 | /* |
| 95 | * GDEF |
| 96 | */ |
| 97 | |
Behdad Esfahbod | d6aae5f | 2009-05-18 04:25:22 -0400 | [diff] [blame] | 98 | /* TODO the public class_t is a mess */ |
Behdad Esfahbod | 30bd763 | 2009-04-15 22:56:15 -0400 | [diff] [blame] | 99 | |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 100 | hb_bool_t |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 101 | hb_ot_layout_has_font_glyph_classes (hb_face_t *face) |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 102 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 103 | return _get_gdef (face).has_glyph_classes (); |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 104 | } |
| 105 | |
Behdad Esfahbod | 347f0b8 | 2009-05-25 03:30:31 -0400 | [diff] [blame] | 106 | HB_INTERNAL hb_bool_t |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 107 | _hb_ot_layout_has_new_glyph_classes (hb_face_t *face) |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 108 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 109 | return face->ot_layout.new_gdef.len > 0; |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 110 | } |
| 111 | |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 112 | static unsigned int |
| 113 | _hb_ot_layout_get_glyph_property (hb_face_t *face, |
Behdad Esfahbod | 30bd763 | 2009-04-15 22:56:15 -0400 | [diff] [blame] | 114 | hb_codepoint_t glyph) |
Behdad Esfahbod | ead428d | 2008-01-24 03:54:09 -0500 | [diff] [blame] | 115 | { |
Behdad Esfahbod | aff831e | 2008-01-24 06:03:45 -0500 | [diff] [blame] | 116 | hb_ot_layout_class_t klass; |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 117 | const GDEF &gdef = _get_gdef (face); |
Behdad Esfahbod | ead428d | 2008-01-24 03:54:09 -0500 | [diff] [blame] | 118 | |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 119 | klass = gdef.get_glyph_class (glyph); |
Behdad Esfahbod | aff831e | 2008-01-24 06:03:45 -0500 | [diff] [blame] | 120 | |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 121 | if (!klass && glyph < face->ot_layout.new_gdef.len) |
| 122 | klass = face->ot_layout.new_gdef.klasses[glyph]; |
Behdad Esfahbod | aff831e | 2008-01-24 06:03:45 -0500 | [diff] [blame] | 123 | |
| 124 | switch (klass) { |
| 125 | default: |
| 126 | case GDEF::UnclassifiedGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED; |
| 127 | case GDEF::BaseGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH; |
| 128 | case GDEF::LigatureGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE; |
Behdad Esfahbod | aff831e | 2008-01-24 06:03:45 -0500 | [diff] [blame] | 129 | case GDEF::ComponentGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT; |
Behdad Esfahbod | 5130c35 | 2009-05-26 15:45:41 -0400 | [diff] [blame] | 130 | case GDEF::MarkGlyph: |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 131 | klass = gdef.get_mark_attachment_type (glyph); |
Behdad Esfahbod | 09c292e | 2009-05-26 19:48:16 -0400 | [diff] [blame] | 132 | return HB_OT_LAYOUT_GLYPH_CLASS_MARK + (klass << 8); |
Behdad Esfahbod | aff831e | 2008-01-24 06:03:45 -0500 | [diff] [blame] | 133 | } |
| 134 | } |
| 135 | |
Behdad Esfahbod | 347f0b8 | 2009-05-25 03:30:31 -0400 | [diff] [blame] | 136 | HB_INTERNAL hb_bool_t |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 137 | _hb_ot_layout_check_glyph_property (hb_face_t *face, |
Behdad Esfahbod | f1322e5 | 2009-08-01 22:53:04 -0400 | [diff] [blame] | 138 | hb_internal_glyph_info_t *ginfo, |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 139 | unsigned int lookup_flags, |
| 140 | unsigned int *property_out) |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 141 | { |
Behdad Esfahbod | 4189b92 | 2009-05-26 17:31:56 -0400 | [diff] [blame] | 142 | unsigned int property; |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 143 | |
Behdad Esfahbod | f1322e5 | 2009-08-01 22:53:04 -0400 | [diff] [blame] | 144 | if (ginfo->gproperty == HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN) |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 145 | ginfo->gproperty = _hb_ot_layout_get_glyph_property (face, ginfo->codepoint); |
Behdad Esfahbod | f1322e5 | 2009-08-01 22:53:04 -0400 | [diff] [blame] | 146 | property = ginfo->gproperty; |
Behdad Esfahbod | 4189b92 | 2009-05-26 17:31:56 -0400 | [diff] [blame] | 147 | if (property_out) |
| 148 | *property_out = property; |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 149 | |
Behdad Esfahbod | 4189b92 | 2009-05-26 17:31:56 -0400 | [diff] [blame] | 150 | /* Not covered, if, for example, glyph class is ligature and |
Behdad Esfahbod | 1246e41 | 2009-05-26 15:58:34 -0400 | [diff] [blame] | 151 | * lookup_flags includes LookupFlags::IgnoreLigatures |
Behdad Esfahbod | 6f425b1 | 2008-01-24 19:38:56 -0500 | [diff] [blame] | 152 | */ |
Behdad Esfahbod | 4189b92 | 2009-05-26 17:31:56 -0400 | [diff] [blame] | 153 | if (property & lookup_flags) |
Behdad Esfahbod | 6f425b1 | 2008-01-24 19:38:56 -0500 | [diff] [blame] | 154 | return false; |
| 155 | |
Behdad Esfahbod | 4189b92 | 2009-05-26 17:31:56 -0400 | [diff] [blame] | 156 | if (property & HB_OT_LAYOUT_GLYPH_CLASS_MARK) |
Behdad Esfahbod | 6f425b1 | 2008-01-24 19:38:56 -0500 | [diff] [blame] | 157 | { |
Behdad Esfahbod | 1246e41 | 2009-05-26 15:58:34 -0400 | [diff] [blame] | 158 | /* If using mark filtering sets, the high short of |
Behdad Esfahbod | 4189b92 | 2009-05-26 17:31:56 -0400 | [diff] [blame] | 159 | * lookup_flags has the set index. |
Behdad Esfahbod | 1246e41 | 2009-05-26 15:58:34 -0400 | [diff] [blame] | 160 | */ |
| 161 | if (lookup_flags & LookupFlag::UseMarkFilteringSet) |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 162 | return _get_gdef (face).mark_set_covers (lookup_flags >> 16, ginfo->codepoint); |
Behdad Esfahbod | 1246e41 | 2009-05-26 15:58:34 -0400 | [diff] [blame] | 163 | |
| 164 | /* The second byte of lookup_flags has the meaning |
| 165 | * "ignore marks of attachment type different than |
| 166 | * the attachment type specified." |
| 167 | */ |
Behdad Esfahbod | 4189b92 | 2009-05-26 17:31:56 -0400 | [diff] [blame] | 168 | if (lookup_flags & LookupFlag::MarkAttachmentType && property & LookupFlag::MarkAttachmentType) |
| 169 | return (lookup_flags & LookupFlag::MarkAttachmentType) == (property & LookupFlag::MarkAttachmentType); |
Behdad Esfahbod | 6f425b1 | 2008-01-24 19:38:56 -0500 | [diff] [blame] | 170 | } |
| 171 | |
| 172 | return true; |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 173 | } |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 174 | |
Behdad Esfahbod | 4189b92 | 2009-05-26 17:31:56 -0400 | [diff] [blame] | 175 | HB_INTERNAL hb_bool_t |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 176 | _hb_ot_layout_skip_mark (hb_face_t *face, |
Behdad Esfahbod | f1322e5 | 2009-08-01 22:53:04 -0400 | [diff] [blame] | 177 | hb_internal_glyph_info_t *ginfo, |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 178 | unsigned int lookup_flags, |
| 179 | unsigned int *property_out) |
Behdad Esfahbod | 4189b92 | 2009-05-26 17:31:56 -0400 | [diff] [blame] | 180 | { |
| 181 | unsigned int property; |
| 182 | |
Behdad Esfahbod | f1322e5 | 2009-08-01 22:53:04 -0400 | [diff] [blame] | 183 | if (ginfo->gproperty == HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN) |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 184 | ginfo->gproperty = _hb_ot_layout_get_glyph_property (face, ginfo->codepoint); |
Behdad Esfahbod | f1322e5 | 2009-08-01 22:53:04 -0400 | [diff] [blame] | 185 | property = ginfo->gproperty; |
Behdad Esfahbod | 4189b92 | 2009-05-26 17:31:56 -0400 | [diff] [blame] | 186 | if (property_out) |
| 187 | *property_out = property; |
| 188 | |
| 189 | if (property & HB_OT_LAYOUT_GLYPH_CLASS_MARK) |
| 190 | { |
| 191 | /* Skip mark if lookup_flags includes LookupFlags::IgnoreMarks */ |
| 192 | if (lookup_flags & LookupFlag::IgnoreMarks) |
| 193 | return true; |
| 194 | |
| 195 | /* If using mark filtering sets, the high short of lookup_flags has the set index. */ |
| 196 | if (lookup_flags & LookupFlag::UseMarkFilteringSet) |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 197 | return !_get_gdef (face).mark_set_covers (lookup_flags >> 16, ginfo->codepoint); |
Behdad Esfahbod | 4189b92 | 2009-05-26 17:31:56 -0400 | [diff] [blame] | 198 | |
| 199 | /* The second byte of lookup_flags has the meaning "ignore marks of attachment type |
| 200 | * different than the attachment type specified." */ |
| 201 | if (lookup_flags & LookupFlag::MarkAttachmentType && property & LookupFlag::MarkAttachmentType) |
| 202 | return (lookup_flags & LookupFlag::MarkAttachmentType) != (property & LookupFlag::MarkAttachmentType); |
| 203 | } |
| 204 | |
| 205 | return false; |
| 206 | } |
| 207 | |
Behdad Esfahbod | 347f0b8 | 2009-05-25 03:30:31 -0400 | [diff] [blame] | 208 | HB_INTERNAL void |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 209 | _hb_ot_layout_set_glyph_class (hb_face_t *face, |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 210 | hb_codepoint_t glyph, |
| 211 | hb_ot_layout_glyph_class_t klass) |
Behdad Esfahbod | ead428d | 2008-01-24 03:54:09 -0500 | [diff] [blame] | 212 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 213 | if (HB_OBJECT_IS_INERT (face)) |
| 214 | return; |
| 215 | |
Behdad Esfahbod | 2c80296 | 2009-08-02 15:20:22 -0400 | [diff] [blame] | 216 | /* TODO optimize this? similar to old harfbuzz code for example */ |
Behdad Esfahbod | ead428d | 2008-01-24 03:54:09 -0500 | [diff] [blame] | 217 | |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 218 | hb_ot_layout_t *layout = &face->ot_layout; |
Behdad Esfahbod | aff831e | 2008-01-24 06:03:45 -0500 | [diff] [blame] | 219 | hb_ot_layout_class_t gdef_klass; |
Behdad Esfahbod | 15164d9 | 2009-08-04 13:57:41 -0400 | [diff] [blame] | 220 | unsigned int len = layout->new_gdef.len; |
Behdad Esfahbod | aff831e | 2008-01-24 06:03:45 -0500 | [diff] [blame] | 221 | |
Behdad Esfahbod | 4acaffd | 2009-05-18 05:29:29 -0400 | [diff] [blame] | 222 | if (HB_UNLIKELY (glyph > 65535)) |
Behdad Esfahbod | 30bd763 | 2009-04-15 22:56:15 -0400 | [diff] [blame] | 223 | return; |
| 224 | |
Behdad Esfahbod | 2c80296 | 2009-08-02 15:20:22 -0400 | [diff] [blame] | 225 | /* XXX this is not threadsafe */ |
Behdad Esfahbod | aff831e | 2008-01-24 06:03:45 -0500 | [diff] [blame] | 226 | if (glyph >= len) { |
| 227 | int new_len; |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 228 | unsigned char *new_klasses; |
Behdad Esfahbod | aff831e | 2008-01-24 06:03:45 -0500 | [diff] [blame] | 229 | |
| 230 | new_len = len == 0 ? 120 : 2 * len; |
| 231 | if (new_len > 65535) |
| 232 | new_len = 65535; |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 233 | new_klasses = (unsigned char *) realloc (layout->new_gdef.klasses, new_len * sizeof (unsigned char)); |
Behdad Esfahbod | aff831e | 2008-01-24 06:03:45 -0500 | [diff] [blame] | 234 | |
Behdad Esfahbod | 4acaffd | 2009-05-18 05:29:29 -0400 | [diff] [blame] | 235 | if (HB_UNLIKELY (!new_klasses)) |
Behdad Esfahbod | aff831e | 2008-01-24 06:03:45 -0500 | [diff] [blame] | 236 | return; |
Behdad Esfahbod | ce48f03 | 2009-11-02 14:35:51 -0500 | [diff] [blame] | 237 | |
Behdad Esfahbod | aff831e | 2008-01-24 06:03:45 -0500 | [diff] [blame] | 238 | memset (new_klasses + len, 0, new_len - len); |
| 239 | |
| 240 | layout->new_gdef.klasses = new_klasses; |
| 241 | layout->new_gdef.len = new_len; |
| 242 | } |
| 243 | |
| 244 | switch (klass) { |
| 245 | default: |
| 246 | case HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED: gdef_klass = GDEF::UnclassifiedGlyph; break; |
| 247 | case HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH: gdef_klass = GDEF::BaseGlyph; break; |
| 248 | case HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE: gdef_klass = GDEF::LigatureGlyph; break; |
| 249 | case HB_OT_LAYOUT_GLYPH_CLASS_MARK: gdef_klass = GDEF::MarkGlyph; break; |
| 250 | case HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT: gdef_klass = GDEF::ComponentGlyph; break; |
| 251 | } |
| 252 | |
| 253 | layout->new_gdef.klasses[glyph] = gdef_klass; |
| 254 | return; |
Behdad Esfahbod | ead428d | 2008-01-24 03:54:09 -0500 | [diff] [blame] | 255 | } |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 256 | |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 257 | HB_INTERNAL void |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 258 | _hb_ot_layout_set_glyph_property (hb_face_t *face, |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 259 | hb_codepoint_t glyph, |
| 260 | unsigned int property) |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 261 | { _hb_ot_layout_set_glyph_class (face, glyph, (hb_ot_layout_glyph_class_t) (property & 0xff)); } |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 262 | |
| 263 | |
| 264 | hb_ot_layout_glyph_class_t |
| 265 | hb_ot_layout_get_glyph_class (hb_face_t *face, |
| 266 | hb_codepoint_t glyph) |
| 267 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 268 | return (hb_ot_layout_glyph_class_t) (_hb_ot_layout_get_glyph_property (face, glyph) & 0xff); |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 269 | } |
| 270 | |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 271 | void |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 272 | hb_ot_layout_set_glyph_class (hb_face_t *face, |
| 273 | hb_codepoint_t glyph, |
| 274 | hb_ot_layout_glyph_class_t klass) |
| 275 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 276 | _hb_ot_layout_set_glyph_class (face, glyph, klass); |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 277 | } |
| 278 | |
| 279 | void |
| 280 | hb_ot_layout_build_glyph_classes (hb_face_t *face, |
Behdad Esfahbod | e50c397 | 2008-01-28 00:16:49 -0500 | [diff] [blame] | 281 | uint16_t num_total_glyphs, |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 282 | hb_codepoint_t *glyphs, |
Behdad Esfahbod | e50c397 | 2008-01-28 00:16:49 -0500 | [diff] [blame] | 283 | unsigned char *klasses, |
| 284 | uint16_t count) |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 285 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 286 | if (HB_OBJECT_IS_INERT (face)) |
| 287 | return; |
| 288 | |
| 289 | hb_ot_layout_t *layout = &face->ot_layout; |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 290 | |
Behdad Esfahbod | 4acaffd | 2009-05-18 05:29:29 -0400 | [diff] [blame] | 291 | if (HB_UNLIKELY (!count || !glyphs || !klasses)) |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 292 | return; |
| 293 | |
| 294 | if (layout->new_gdef.len == 0) { |
| 295 | layout->new_gdef.klasses = (unsigned char *) calloc (num_total_glyphs, sizeof (unsigned char)); |
| 296 | layout->new_gdef.len = count; |
| 297 | } |
| 298 | |
Behdad Esfahbod | f4c9514 | 2009-05-17 04:59:56 -0400 | [diff] [blame] | 299 | for (unsigned int i = 0; i < count; i++) |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 300 | _hb_ot_layout_set_glyph_class (face, glyphs[i], (hb_ot_layout_glyph_class_t) klasses[i]); |
Behdad Esfahbod | 590d55c | 2008-01-24 19:13:50 -0500 | [diff] [blame] | 301 | } |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 302 | |
Behdad Esfahbod | 62964af | 2009-05-26 12:40:10 -0400 | [diff] [blame] | 303 | hb_bool_t |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 304 | hb_ot_layout_get_attach_points (hb_face_t *face, |
Behdad Esfahbod | 79420ad | 2009-05-26 12:24:16 -0400 | [diff] [blame] | 305 | hb_codepoint_t glyph, |
| 306 | unsigned int *point_count /* IN/OUT */, |
| 307 | unsigned int *point_array /* OUT */) |
| 308 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 309 | return _get_gdef (face).get_attach_points (glyph, point_count, point_array); |
Behdad Esfahbod | 62964af | 2009-05-26 12:40:10 -0400 | [diff] [blame] | 310 | } |
| 311 | |
| 312 | hb_bool_t |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 313 | hb_ot_layout_get_lig_carets (hb_face_t *face, |
| 314 | hb_font_t *font, |
Behdad Esfahbod | 62964af | 2009-05-26 12:40:10 -0400 | [diff] [blame] | 315 | hb_codepoint_t glyph, |
| 316 | unsigned int *caret_count /* IN/OUT */, |
| 317 | int *caret_array /* OUT */) |
| 318 | { |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 319 | hb_ot_layout_context_t context; |
| 320 | context.font = font; |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 321 | context.face = face; |
| 322 | return _get_gdef (face).get_lig_carets (&context, glyph, caret_count, caret_array); |
Behdad Esfahbod | 79420ad | 2009-05-26 12:24:16 -0400 | [diff] [blame] | 323 | } |
| 324 | |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 325 | /* |
| 326 | * GSUB/GPOS |
| 327 | */ |
| 328 | |
| 329 | static const GSUBGPOS& |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 330 | get_gsubgpos_table (hb_face_t *face, |
| 331 | hb_tag_t table_tag) |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 332 | { |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 333 | switch (table_tag) { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 334 | case HB_OT_TAG_GSUB: return _get_gsub (face); |
| 335 | case HB_OT_TAG_GPOS: return _get_gpos (face); |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 336 | default: return Null(GSUBGPOS); |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 337 | } |
| 338 | } |
| 339 | |
| 340 | |
| 341 | unsigned int |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 342 | hb_ot_layout_table_get_script_count (hb_face_t *face, |
| 343 | hb_tag_t table_tag) |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 344 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 345 | const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 346 | |
| 347 | return g.get_script_count (); |
| 348 | } |
| 349 | |
| 350 | hb_tag_t |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 351 | hb_ot_layout_table_get_script_tag (hb_face_t *face, |
| 352 | hb_tag_t table_tag, |
| 353 | unsigned int script_index) |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 354 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 355 | const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 356 | |
| 357 | return g.get_script_tag (script_index); |
| 358 | } |
| 359 | |
| 360 | hb_bool_t |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 361 | hb_ot_layout_table_find_script (hb_face_t *face, |
| 362 | hb_tag_t table_tag, |
| 363 | hb_tag_t script_tag, |
| 364 | unsigned int *script_index) |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 365 | { |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 366 | ASSERT_STATIC (NO_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 367 | const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 368 | |
| 369 | if (g.find_script_index (script_tag, script_index)) |
| 370 | return TRUE; |
| 371 | |
| 372 | /* try finding 'DFLT' */ |
| 373 | if (g.find_script_index (HB_OT_LAYOUT_TAG_DEFAULT_SCRIPT, script_index)) |
| 374 | return FALSE; |
| 375 | |
| 376 | /* try with 'dflt'; MS site has had typos and many fonts use it now :( */ |
| 377 | if (g.find_script_index (HB_OT_LAYOUT_TAG_DEFAULT_LANGUAGE, script_index)) |
| 378 | return FALSE; |
| 379 | |
| 380 | if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX; |
| 381 | return FALSE; |
| 382 | } |
| 383 | |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 384 | unsigned int |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 385 | hb_ot_layout_table_get_feature_count (hb_face_t *face, |
| 386 | hb_tag_t table_tag) |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 387 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 388 | const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 389 | |
| 390 | return g.get_feature_count (); |
| 391 | } |
| 392 | |
| 393 | hb_tag_t |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 394 | hb_ot_layout_table_get_feature_tag (hb_face_t *face, |
| 395 | hb_tag_t table_tag, |
| 396 | unsigned int feature_index) |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 397 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 398 | const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 399 | |
| 400 | return g.get_feature_tag (feature_index); |
| 401 | } |
| 402 | |
| 403 | hb_bool_t |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 404 | hb_ot_layout_table_find_feature (hb_face_t *face, |
| 405 | hb_tag_t table_tag, |
| 406 | hb_tag_t feature_tag, |
| 407 | unsigned int *feature_index) |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 408 | { |
| 409 | ASSERT_STATIC (NO_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 410 | const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 411 | |
| 412 | if (g.find_feature_index (feature_tag, feature_index)) |
| 413 | return TRUE; |
| 414 | |
| 415 | if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX; |
| 416 | return FALSE; |
| 417 | } |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 418 | |
| 419 | unsigned int |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 420 | hb_ot_layout_table_get_lookup_count (hb_face_t *face, |
| 421 | hb_tag_t table_tag) |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 422 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 423 | const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 424 | |
| 425 | return g.get_lookup_count (); |
| 426 | } |
| 427 | |
| 428 | |
| 429 | unsigned int |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 430 | hb_ot_layout_script_get_language_count (hb_face_t *face, |
| 431 | hb_tag_t table_tag, |
| 432 | unsigned int script_index) |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 433 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 434 | const Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index); |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 435 | |
| 436 | return s.get_lang_sys_count (); |
| 437 | } |
| 438 | |
| 439 | hb_tag_t |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 440 | hb_ot_layout_script_get_language_tag (hb_face_t *face, |
| 441 | hb_tag_t table_tag, |
| 442 | unsigned int script_index, |
| 443 | unsigned int language_index) |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 444 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 445 | const Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index); |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 446 | |
| 447 | return s.get_lang_sys_tag (language_index); |
| 448 | } |
| 449 | |
| 450 | hb_bool_t |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 451 | hb_ot_layout_script_find_language (hb_face_t *face, |
| 452 | hb_tag_t table_tag, |
| 453 | unsigned int script_index, |
| 454 | hb_tag_t language_tag, |
| 455 | unsigned int *language_index) |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 456 | { |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 457 | ASSERT_STATIC (NO_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX); |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 458 | const Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index); |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 459 | |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 460 | if (s.find_lang_sys_index (language_tag, language_index)) |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 461 | return TRUE; |
| 462 | |
| 463 | /* try with 'dflt'; MS site has had typos and many fonts use it now :( */ |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 464 | if (s.find_lang_sys_index (HB_OT_LAYOUT_TAG_DEFAULT_LANGUAGE, language_index)) |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 465 | return FALSE; |
| 466 | |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 467 | if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX; |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 468 | return FALSE; |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 469 | } |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 470 | |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 471 | hb_bool_t |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 472 | hb_ot_layout_language_get_required_feature_index (hb_face_t *face, |
| 473 | hb_tag_t table_tag, |
| 474 | unsigned int script_index, |
| 475 | unsigned int language_index, |
| 476 | unsigned int *feature_index) |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 477 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 478 | const LangSys &l = get_gsubgpos_table (face, table_tag).get_script (script_index).get_lang_sys (language_index); |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 479 | |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 480 | if (feature_index) *feature_index = l.get_required_feature_index (); |
| 481 | |
| 482 | return l.has_required_feature (); |
| 483 | } |
| 484 | |
| 485 | unsigned int |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 486 | hb_ot_layout_language_get_feature_count (hb_face_t *face, |
| 487 | hb_tag_t table_tag, |
| 488 | unsigned int script_index, |
| 489 | unsigned int language_index) |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 490 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 491 | const LangSys &l = get_gsubgpos_table (face, table_tag).get_script (script_index).get_lang_sys (language_index); |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 492 | |
| 493 | return l.get_feature_count (); |
| 494 | } |
| 495 | |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 496 | unsigned int |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 497 | hb_ot_layout_language_get_feature_index (hb_face_t *face, |
| 498 | hb_tag_t table_tag, |
| 499 | unsigned int script_index, |
| 500 | unsigned int language_index, |
| 501 | unsigned int num_feature) |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 502 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 503 | const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 504 | const LangSys &l = g.get_script (script_index).get_lang_sys (language_index); |
| 505 | |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 506 | return l.get_feature_index (num_feature); |
| 507 | } |
| 508 | |
| 509 | hb_tag_t |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 510 | hb_ot_layout_language_get_feature_tag (hb_face_t *face, |
| 511 | hb_tag_t table_tag, |
| 512 | unsigned int script_index, |
| 513 | unsigned int language_index, |
| 514 | unsigned int num_feature) |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 515 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 516 | const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 517 | const LangSys &l = g.get_script (script_index).get_lang_sys (language_index); |
| 518 | unsigned int feature_index = l.get_feature_index (num_feature); |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 519 | |
| 520 | return g.get_feature_tag (feature_index); |
| 521 | } |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 522 | |
| 523 | |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 524 | hb_bool_t |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 525 | hb_ot_layout_language_find_feature (hb_face_t *face, |
| 526 | hb_tag_t table_tag, |
| 527 | unsigned int script_index, |
| 528 | unsigned int language_index, |
| 529 | hb_tag_t feature_tag, |
| 530 | unsigned int *feature_index) |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 531 | { |
| 532 | ASSERT_STATIC (NO_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 533 | const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 534 | const LangSys &l = g.get_script (script_index).get_lang_sys (language_index); |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 535 | |
Behdad Esfahbod | f4c9514 | 2009-05-17 04:59:56 -0400 | [diff] [blame] | 536 | unsigned int num_features = l.get_feature_count (); |
| 537 | for (unsigned int i = 0; i < num_features; i++) { |
Behdad Esfahbod | 4a26ea4 | 2008-01-28 07:40:10 -0500 | [diff] [blame] | 538 | unsigned int f_index = l.get_feature_index (i); |
| 539 | |
| 540 | if (feature_tag == g.get_feature_tag (f_index)) { |
| 541 | if (feature_index) *feature_index = f_index; |
| 542 | return TRUE; |
| 543 | } |
| 544 | } |
| 545 | |
| 546 | if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX; |
Behdad Esfahbod | 706ab25 | 2008-01-28 05:58:50 -0500 | [diff] [blame] | 547 | return FALSE; |
| 548 | } |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 549 | |
| 550 | unsigned int |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 551 | hb_ot_layout_feature_get_lookup_count (hb_face_t *face, |
| 552 | hb_tag_t table_tag, |
| 553 | unsigned int feature_index) |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 554 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 555 | const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 556 | const Feature &f = g.get_feature (feature_index); |
| 557 | |
| 558 | return f.get_lookup_count (); |
| 559 | } |
| 560 | |
| 561 | unsigned int |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 562 | hb_ot_layout_feature_get_lookup_index (hb_face_t *face, |
| 563 | hb_tag_t table_tag, |
| 564 | unsigned int feature_index, |
| 565 | unsigned int num_lookup) |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 566 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 567 | const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); |
Behdad Esfahbod | c447335 | 2008-02-18 21:14:23 -0500 | [diff] [blame] | 568 | const Feature &f = g.get_feature (feature_index); |
| 569 | |
| 570 | return f.get_lookup_index (num_lookup); |
| 571 | } |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 572 | |
| 573 | /* |
| 574 | * GSUB |
| 575 | */ |
| 576 | |
| 577 | hb_bool_t |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 578 | hb_ot_layout_has_substitution (hb_face_t *face) |
| 579 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 580 | return &_get_gsub (face) != &Null(GSUB); |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 581 | } |
| 582 | |
| 583 | hb_bool_t |
| 584 | hb_ot_layout_substitute_lookup (hb_face_t *face, |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 585 | hb_buffer_t *buffer, |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 586 | unsigned int lookup_index, |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 587 | hb_ot_layout_feature_mask_t mask) |
| 588 | { |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 589 | hb_ot_layout_context_t context; |
| 590 | context.font = NULL; |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 591 | context.face = face; |
| 592 | return _get_gsub (face).substitute_lookup (&context, buffer, lookup_index, mask); |
Behdad Esfahbod | 5a0b791 | 2009-04-16 04:45:30 -0400 | [diff] [blame] | 593 | } |
Behdad Esfahbod | 2d15e72 | 2009-04-15 19:50:16 -0400 | [diff] [blame] | 594 | |
Behdad Esfahbod | 9c42f05 | 2009-05-18 17:43:49 -0400 | [diff] [blame] | 595 | /* |
| 596 | * GPOS |
| 597 | */ |
| 598 | |
| 599 | hb_bool_t |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 600 | hb_ot_layout_has_positioning (hb_face_t *face) |
| 601 | { |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 602 | return &_get_gpos (face) != &Null(GPOS); |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 603 | } |
| 604 | |
| 605 | hb_bool_t |
| 606 | hb_ot_layout_position_lookup (hb_face_t *face, |
| 607 | hb_font_t *font, |
Behdad Esfahbod | 9c42f05 | 2009-05-18 17:43:49 -0400 | [diff] [blame] | 608 | hb_buffer_t *buffer, |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 609 | unsigned int lookup_index, |
Behdad Esfahbod | 9c42f05 | 2009-05-18 17:43:49 -0400 | [diff] [blame] | 610 | hb_ot_layout_feature_mask_t mask) |
| 611 | { |
Behdad Esfahbod | 0ead481 | 2009-08-02 17:41:36 -0400 | [diff] [blame] | 612 | hb_ot_layout_context_t context; |
| 613 | context.font = font; |
Behdad Esfahbod | 23c86aa | 2009-08-03 21:40:20 -0400 | [diff] [blame] | 614 | context.face = face; |
| 615 | return _get_gpos (face).position_lookup (&context, buffer, lookup_index, mask); |
Behdad Esfahbod | 9c42f05 | 2009-05-18 17:43:49 -0400 | [diff] [blame] | 616 | } |