Fri, 16 Jan 2015 18:13:44 +0100
Integrate suggestion from review to improve consistency with existing code.
michael@0 | 1 | /* |
michael@0 | 2 | * Copyright © 2007,2008,2009 Red Hat, Inc. |
michael@0 | 3 | * |
michael@0 | 4 | * This is part of HarfBuzz, a text shaping library. |
michael@0 | 5 | * |
michael@0 | 6 | * Permission is hereby granted, without written agreement and without |
michael@0 | 7 | * license or royalty fees, to use, copy, modify, and distribute this |
michael@0 | 8 | * software and its documentation for any purpose, provided that the |
michael@0 | 9 | * above copyright notice and the following two paragraphs appear in |
michael@0 | 10 | * all copies of this software. |
michael@0 | 11 | * |
michael@0 | 12 | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
michael@0 | 13 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
michael@0 | 14 | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
michael@0 | 15 | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
michael@0 | 16 | * DAMAGE. |
michael@0 | 17 | * |
michael@0 | 18 | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
michael@0 | 19 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
michael@0 | 20 | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
michael@0 | 21 | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
michael@0 | 22 | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
michael@0 | 23 | * |
michael@0 | 24 | * Red Hat Author(s): Behdad Esfahbod |
michael@0 | 25 | */ |
michael@0 | 26 | |
michael@0 | 27 | #include "hb-mutex-private.hh" |
michael@0 | 28 | #include "hb-open-file-private.hh" |
michael@0 | 29 | #include "hb-ot-layout-gdef-table.hh" |
michael@0 | 30 | #include "hb-ot-layout-gsubgpos-private.hh" |
michael@0 | 31 | |
michael@0 | 32 | #ifdef HAVE_GLIB |
michael@0 | 33 | #include <glib.h> |
michael@0 | 34 | #endif |
michael@0 | 35 | #include <stdlib.h> |
michael@0 | 36 | #include <stdio.h> |
michael@0 | 37 | |
michael@0 | 38 | |
michael@0 | 39 | using namespace OT; |
michael@0 | 40 | |
michael@0 | 41 | |
michael@0 | 42 | int |
michael@0 | 43 | main (int argc, char **argv) |
michael@0 | 44 | { |
michael@0 | 45 | if (argc != 2) { |
michael@0 | 46 | fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]); |
michael@0 | 47 | exit (1); |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | const char *font_data = NULL; |
michael@0 | 51 | int len = 0; |
michael@0 | 52 | |
michael@0 | 53 | #ifdef HAVE_GLIB |
michael@0 | 54 | GMappedFile *mf = g_mapped_file_new (argv[1], false, NULL); |
michael@0 | 55 | font_data = g_mapped_file_get_contents (mf); |
michael@0 | 56 | len = g_mapped_file_get_length (mf); |
michael@0 | 57 | #else |
michael@0 | 58 | FILE *f = fopen (argv[1], "rb"); |
michael@0 | 59 | fseek (f, 0, SEEK_END); |
michael@0 | 60 | len = ftell (f); |
michael@0 | 61 | fseek (f, 0, SEEK_SET); |
michael@0 | 62 | font_data = (const char *) malloc (len); |
michael@0 | 63 | len = fread ((char *) font_data, 1, len, f); |
michael@0 | 64 | #endif |
michael@0 | 65 | |
michael@0 | 66 | printf ("Opened font file %s: %d bytes long\n", argv[1], len); |
michael@0 | 67 | |
michael@0 | 68 | const OpenTypeFontFile &ot = *CastP<OpenTypeFontFile> (font_data); |
michael@0 | 69 | |
michael@0 | 70 | switch (ot.get_tag ()) { |
michael@0 | 71 | case OpenTypeFontFile::TrueTypeTag: |
michael@0 | 72 | printf ("OpenType font with TrueType outlines\n"); |
michael@0 | 73 | break; |
michael@0 | 74 | case OpenTypeFontFile::CFFTag: |
michael@0 | 75 | printf ("OpenType font with CFF (Type1) outlines\n"); |
michael@0 | 76 | break; |
michael@0 | 77 | case OpenTypeFontFile::TTCTag: |
michael@0 | 78 | printf ("TrueType Collection of OpenType fonts\n"); |
michael@0 | 79 | break; |
michael@0 | 80 | case OpenTypeFontFile::TrueTag: |
michael@0 | 81 | printf ("Obsolete Apple TrueType font\n"); |
michael@0 | 82 | break; |
michael@0 | 83 | case OpenTypeFontFile::Typ1Tag: |
michael@0 | 84 | printf ("Obsolete Apple Type1 font in SFNT container\n"); |
michael@0 | 85 | break; |
michael@0 | 86 | default: |
michael@0 | 87 | printf ("Unknown font format\n"); |
michael@0 | 88 | break; |
michael@0 | 89 | } |
michael@0 | 90 | |
michael@0 | 91 | int num_fonts = ot.get_face_count (); |
michael@0 | 92 | printf ("%d font(s) found in file\n", num_fonts); |
michael@0 | 93 | for (int n_font = 0; n_font < num_fonts; n_font++) { |
michael@0 | 94 | const OpenTypeFontFace &font = ot.get_face (n_font); |
michael@0 | 95 | printf ("Font %d of %d:\n", n_font, num_fonts); |
michael@0 | 96 | |
michael@0 | 97 | int num_tables = font.get_table_count (); |
michael@0 | 98 | printf (" %d table(s) found in font\n", num_tables); |
michael@0 | 99 | for (int n_table = 0; n_table < num_tables; n_table++) { |
michael@0 | 100 | const OpenTypeTable &table = font.get_table (n_table); |
michael@0 | 101 | printf (" Table %2d of %2d: %.4s (0x%08x+0x%08x)\n", n_table, num_tables, |
michael@0 | 102 | (const char *)table.tag, |
michael@0 | 103 | (unsigned int) table.offset, |
michael@0 | 104 | (unsigned int) table.length); |
michael@0 | 105 | |
michael@0 | 106 | switch (table.tag) { |
michael@0 | 107 | |
michael@0 | 108 | case GSUBGPOS::GSUBTag: |
michael@0 | 109 | case GSUBGPOS::GPOSTag: |
michael@0 | 110 | { |
michael@0 | 111 | |
michael@0 | 112 | const GSUBGPOS &g = *CastP<GSUBGPOS> (font_data + table.offset); |
michael@0 | 113 | |
michael@0 | 114 | int num_scripts = g.get_script_count (); |
michael@0 | 115 | printf (" %d script(s) found in table\n", num_scripts); |
michael@0 | 116 | for (int n_script = 0; n_script < num_scripts; n_script++) { |
michael@0 | 117 | const Script &script = g.get_script (n_script); |
michael@0 | 118 | printf (" Script %2d of %2d: %.4s\n", n_script, num_scripts, |
michael@0 | 119 | (const char *)g.get_script_tag(n_script)); |
michael@0 | 120 | |
michael@0 | 121 | if (!script.has_default_lang_sys()) |
michael@0 | 122 | printf (" No default language system\n"); |
michael@0 | 123 | int num_langsys = script.get_lang_sys_count (); |
michael@0 | 124 | printf (" %d language system(s) found in script\n", num_langsys); |
michael@0 | 125 | for (int n_langsys = script.has_default_lang_sys() ? -1 : 0; n_langsys < num_langsys; n_langsys++) { |
michael@0 | 126 | const LangSys &langsys = n_langsys == -1 |
michael@0 | 127 | ? script.get_default_lang_sys () |
michael@0 | 128 | : script.get_lang_sys (n_langsys); |
michael@0 | 129 | if (n_langsys == -1) |
michael@0 | 130 | printf (" Default Language System\n"); |
michael@0 | 131 | else |
michael@0 | 132 | printf (" Language System %2d of %2d: %.4s\n", n_langsys, num_langsys, |
michael@0 | 133 | (const char *)script.get_lang_sys_tag (n_langsys)); |
michael@0 | 134 | if (langsys.get_required_feature_index () == Index::NOT_FOUND_INDEX) |
michael@0 | 135 | printf (" No required feature\n"); |
michael@0 | 136 | |
michael@0 | 137 | int num_features = langsys.get_feature_count (); |
michael@0 | 138 | printf (" %d feature(s) found in language system\n", num_features); |
michael@0 | 139 | for (int n_feature = 0; n_feature < num_features; n_feature++) { |
michael@0 | 140 | printf (" Feature index %2d of %2d: %d\n", n_feature, num_features, |
michael@0 | 141 | langsys.get_feature_index (n_feature)); |
michael@0 | 142 | } |
michael@0 | 143 | } |
michael@0 | 144 | } |
michael@0 | 145 | |
michael@0 | 146 | int num_features = g.get_feature_count (); |
michael@0 | 147 | printf (" %d feature(s) found in table\n", num_features); |
michael@0 | 148 | for (int n_feature = 0; n_feature < num_features; n_feature++) { |
michael@0 | 149 | const Feature &feature = g.get_feature (n_feature); |
michael@0 | 150 | printf (" Feature %2d of %2d: %.4s; %d lookup(s)\n", n_feature, num_features, |
michael@0 | 151 | (const char *)g.get_feature_tag(n_feature), |
michael@0 | 152 | feature.get_lookup_count()); |
michael@0 | 153 | |
michael@0 | 154 | int num_lookups = feature.get_lookup_count (); |
michael@0 | 155 | printf (" %d lookup(s) found in feature\n", num_lookups); |
michael@0 | 156 | for (int n_lookup = 0; n_lookup < num_lookups; n_lookup++) { |
michael@0 | 157 | printf (" Lookup index %2d of %2d: %d\n", n_lookup, num_lookups, |
michael@0 | 158 | feature.get_lookup_index (n_lookup)); |
michael@0 | 159 | } |
michael@0 | 160 | } |
michael@0 | 161 | |
michael@0 | 162 | int num_lookups = g.get_lookup_count (); |
michael@0 | 163 | printf (" %d lookup(s) found in table\n", num_lookups); |
michael@0 | 164 | for (int n_lookup = 0; n_lookup < num_lookups; n_lookup++) { |
michael@0 | 165 | const Lookup &lookup = g.get_lookup (n_lookup); |
michael@0 | 166 | printf (" Lookup %2d of %2d: type %d, props 0x%04X\n", n_lookup, num_lookups, |
michael@0 | 167 | lookup.get_type(), lookup.get_props()); |
michael@0 | 168 | } |
michael@0 | 169 | |
michael@0 | 170 | } |
michael@0 | 171 | break; |
michael@0 | 172 | |
michael@0 | 173 | case GDEF::tableTag: |
michael@0 | 174 | { |
michael@0 | 175 | |
michael@0 | 176 | const GDEF &gdef = *CastP<GDEF> (font_data + table.offset); |
michael@0 | 177 | |
michael@0 | 178 | printf (" Has %sglyph classes\n", |
michael@0 | 179 | gdef.has_glyph_classes () ? "" : "no "); |
michael@0 | 180 | printf (" Has %smark attachment types\n", |
michael@0 | 181 | gdef.has_mark_attachment_types () ? "" : "no "); |
michael@0 | 182 | printf (" Has %sattach points\n", |
michael@0 | 183 | gdef.has_attach_points () ? "" : "no "); |
michael@0 | 184 | printf (" Has %slig carets\n", |
michael@0 | 185 | gdef.has_lig_carets () ? "" : "no "); |
michael@0 | 186 | printf (" Has %smark sets\n", |
michael@0 | 187 | gdef.has_mark_sets () ? "" : "no "); |
michael@0 | 188 | break; |
michael@0 | 189 | } |
michael@0 | 190 | } |
michael@0 | 191 | } |
michael@0 | 192 | } |
michael@0 | 193 | |
michael@0 | 194 | return 0; |
michael@0 | 195 | } |
michael@0 | 196 | |
michael@0 | 197 |