1 --- texk/xdvik/ft2vert.c.orig 2015-07-19 18:49:42 UTC 2 +++ texk/xdvik/ft2vert.c 3 @@ -0,0 +1,399 @@ 4 +/* 5 + * "ft2vert.c" 6 + * 7 + * Converter to vertical glyph ID by handling GSUB vrt2/vert feature 8 + * requires FreeType-2.1.10 or latter 9 + * 10 + * (C) 2005 Nobuyuki TSUCHIMURA 11 + * 12 + * This file is free 13 + * software; you can redistribute it and/or modify it under the terms of 14 + * the GNU Library General Public License as published by the Free 15 + * Software Foundation; either version 2 of the License, or (at your 16 + * option) any later version. This library is distributed in the hope 17 + * that it will be useful, but WITHOUT ANY WARRANTY; without even the 18 + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 19 + * PURPOSE. See the GNU Library General Public License for more details. 20 + * You should have received a copy of the GNU Library General Public 21 + * License along with this library; if not, write to the Free Software 22 + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 + * 24 + * using such Lookup 25 + * ScriptTag == 'kana' 26 + * DefaultLangSys or LangSysTag == 'JAN ' 27 + * FeatureTag == 'vrt2' or 'vert' 28 + * 29 + * [reference] 30 + * http://partners.adobe.com/public/developer/opentype/index_table_formats1.html 31 + * http://partners.adobe.com/public/developer/opentype/index_table_formats.html 32 + * http://partners.adobe.com/public/developer/opentype/index_tag9.html#vrt2 33 + */ 34 + 35 +#include "xdvi-config.h" 36 +#include "xdvi.h" 37 +#ifdef PTEX 38 + 39 +#include <ft2build.h> 40 +#include FT_FREETYPE_H 41 +#include FT_OPENTYPE_VALIDATE_H 42 + 43 +#include <stdio.h> 44 +#include <stdlib.h> 45 +#include "ft2vert.h" 46 + 47 +#define TAG_KANA FT_MAKE_TAG('k', 'a', 'n', 'a') 48 +#define TAG_JAN FT_MAKE_TAG('J', 'A', 'N', ' ') 49 +#define TAG_VERT FT_MAKE_TAG('v', 'e', 'r', 't') 50 +#define TAG_VRT2 FT_MAKE_TAG('v', 'r', 't', '2') 51 + 52 +#define MALLOC(ptr, size) ptr = xmalloc(sizeof((ptr)[0]) * (size)) 53 +#define BYTE2(p) ((p) += 2, (int)(p)[-2] << 8 | (p)[-1]) 54 +#define BYTE4(p) ((p) += 4, (int)(p)[-4] << 24 | (int)(p)[-3] << 16 | \ 55 + (int)(p)[-2] << 8 | (p)[-1]) 56 + 57 +struct ft2vert_st { 58 + int SubTableCount; 59 + struct SubTable_st { 60 + struct SingleSubst_st { 61 + FT_UInt SubstFormat; 62 + FT_UInt DeltaGlyphID; /* SubstFormat == 1 */ 63 + int GlyphCount; /* SubstFormat == 2 */ 64 + FT_UInt *Substitute; /* SubstFormat == 2 */ 65 + } SingleSubst; 66 + struct Coverage_st { 67 + FT_UInt CoverageFormat; 68 + int GlyphCount; /* CoverageFormat == 1 */ 69 + FT_UInt *GlyphArray; /* CoverageFormat == 1 */ 70 + int RangeCount; /* CoverageFormat == 2 */ 71 + struct RangeRecord_st 72 + *RangeRecord; /* CoverageFormat == 2 */ 73 + } Coverage; 74 + } *SubTable; 75 + FT_Bytes kanaFeature; 76 + FT_Bytes vertLookup; 77 + FT_Bytes vrt2Lookup; 78 +}; 79 + 80 +struct RangeRecord_st { 81 + FT_UInt Start; 82 + FT_UInt End; 83 +}; 84 + 85 + 86 +int isInIndex(FT_Bytes s, int index) { 87 + int i, count; 88 + 89 + if (s == NULL) return FALSE; 90 + count = BYTE2(s); 91 + for (i=0; i<count; i++) { 92 + if (index == BYTE2(s)) return TRUE; 93 + } 94 + return FALSE; 95 +} 96 + 97 + 98 +/********** Debug ***************/ 99 + 100 +#ifdef DEBUG 101 +static FT_Bytes gsub_top; 102 + 103 +void print_offset(char *message, const FT_Bytes ptr) { 104 + printf("%s offset = %x\n", message, ptr - gsub_top); 105 +} 106 + 107 +char *tag_to_string(FT_Tag tag) { 108 + static char str[5]; 109 + str[0] = tag >> 24; 110 + str[1] = tag >> 16; 111 + str[2] = tag >> 8; 112 + str[3] = tag; 113 + return str; 114 +} 115 + 116 +void hex_dump(const FT_Bytes top) { 117 + int i, j; 118 + FT_Bytes s = top; 119 + 120 + for (j=0; j<100; j++) { 121 + printf("%04x : ", j*8); 122 + for (i=0; i<8; i++) { 123 + printf("%02x ", s[i+j*8]); 124 + } 125 + printf("\n"); 126 + } 127 +} 128 +#endif /* DEBUG */ 129 + 130 +/********** Lookup part ***************/ 131 + 132 +void scan_Coverage(struct ft2vert_st *ret, const FT_Bytes top) { 133 + int i; 134 + FT_Bytes s = top; 135 + struct Coverage_st *t; 136 + 137 + t = &ret->SubTable[ret->SubTableCount].Coverage; 138 + t->CoverageFormat = BYTE2(s); 139 + switch (t->CoverageFormat) { 140 + case 1: 141 + t->GlyphCount = BYTE2(s); 142 + MALLOC(t->GlyphArray, t->GlyphCount); 143 + for (i=0; i<t->GlyphCount; i++) { 144 + t->GlyphArray[i] = BYTE2(s); 145 + } 146 + break; 147 + case 2: 148 + t->RangeCount = BYTE2(s); 149 + MALLOC(t->RangeRecord, t->RangeCount); 150 + for (i=0; i<t->RangeCount; i++) { 151 + t->RangeRecord[i].Start = BYTE2(s); 152 + t->RangeRecord[i].End = BYTE2(s); 153 + s += 2; /* drop StartCoverageIndex */ 154 + } 155 + break; 156 + default: 157 + fprintf(stderr, "scan_Coverage: unknown CoverageFormat (%d).", 158 + t->CoverageFormat); 159 + exit(1); 160 + } 161 + ret->SubTableCount++; 162 +} 163 + 164 +void scan_SubTable(struct ft2vert_st *ret, const FT_Bytes top) { 165 + int i; 166 + FT_Bytes s = top; 167 + FT_Offset Coverage; 168 + struct SingleSubst_st *t; 169 + 170 + t = &ret->SubTable[ret->SubTableCount].SingleSubst; 171 + t->SubstFormat = BYTE2(s); 172 + Coverage = BYTE2(s); 173 + scan_Coverage(ret, top + Coverage); 174 + switch (t->SubstFormat) { 175 + case 1: /* SingleSubstFormat1 */ 176 + t->DeltaGlyphID = BYTE2(s); 177 + break; 178 + case 2: /* SingleSubstFormat2 */ 179 + t->GlyphCount = BYTE2(s); 180 + MALLOC(t->Substitute, t->GlyphCount); 181 + for (i=0; i<t->GlyphCount; i++) { 182 + t->Substitute[i] = BYTE2(s); 183 + } 184 + break; 185 + default: 186 + fprintf(stderr, "scan_SubTable: unknown SubstFormat (%d).", 187 + t->SubstFormat); 188 + exit(1); 189 + } 190 +} 191 + 192 +void scan_Lookup(struct ft2vert_st *ret, const FT_Bytes top) { 193 + int i; 194 + FT_Bytes s = top; 195 + FT_UShort LookupType; 196 + FT_UShort LookupFlag; 197 + FT_UShort SubTableCount; 198 + FT_UShort SubTable; 199 + 200 + LookupType = BYTE2(s); 201 + LookupFlag = BYTE2(s); 202 + SubTableCount = BYTE2(s); 203 + SubTable = BYTE2(s); 204 + 205 + MALLOC(ret->SubTable, SubTableCount); 206 + for (i=0; i<SubTableCount; i++) { 207 + scan_SubTable(ret, top + SubTable); 208 + } 209 + if (ret->SubTableCount != SubTableCount) { 210 + fprintf(stderr, "warning (scan_Lookup): " 211 + "SubTableCount (=%d) is not expected (=%d).\n", 212 + ret->SubTableCount, SubTableCount); 213 + } 214 +} 215 + 216 + 217 +void scan_LookupList(struct ft2vert_st *ret, const FT_Bytes top) { 218 + int i; 219 + FT_Bytes s = top; 220 + int LookupCount; 221 + 222 + LookupCount = BYTE2(s); 223 + 224 + for (i=0; i<LookupCount; i++) { 225 + FT_Bytes t = top + BYTE2(s); 226 + if (isInIndex(ret->vertLookup, i)) { 227 + scan_Lookup(ret, t); 228 + } 229 + } 230 +} 231 + 232 +/********** Feature part ****************/ 233 + 234 +void scan_FeatureList(struct ft2vert_st *ret, const FT_Bytes top) { 235 + int i; 236 + FT_Bytes s = top; 237 + int FeatureCount; 238 + 239 + FeatureCount = BYTE2(s); 240 + 241 + for (i=0; i<FeatureCount; i++) { 242 + FT_Tag FeatureTag = BYTE4(s); 243 + FT_Offset Feature = BYTE2(s); 244 + if (!isInIndex(ret->kanaFeature, i)) continue; 245 + if (FeatureTag == TAG_VERT) { 246 + ret->vertLookup = top + Feature + 2; 247 + } else if (FeatureTag == TAG_VRT2) { 248 + ret->vrt2Lookup = top + Feature + 2; 249 + } 250 + } 251 +} 252 + 253 +/********** Script part ****************/ 254 + 255 +void scan_LangSys(struct ft2vert_st *ret, const FT_Bytes top) { 256 + if (ret->kanaFeature == NULL) ret->kanaFeature = top + 4; 257 +} 258 + 259 +void scan_Script(struct ft2vert_st *ret, const FT_Bytes top) { 260 + int i; 261 + FT_Bytes s = top; 262 + FT_Offset DefaultLangSys; 263 + int LangSysCount; 264 + 265 + DefaultLangSys = BYTE2(s); 266 + if (DefaultLangSys != 0) { 267 + scan_LangSys(ret, top + DefaultLangSys); 268 + } 269 + LangSysCount = BYTE2(s); 270 + 271 + for (i=0; i<LangSysCount; i++) { 272 + FT_Tag LangSysTag = BYTE4(s); 273 + FT_Bytes t = top + BYTE2(s); 274 + if (LangSysTag == TAG_JAN) { 275 + scan_LangSys(ret, t); 276 + } 277 + } 278 +} 279 + 280 +void scan_ScriptList(struct ft2vert_st *ret, const FT_Bytes top) { 281 + int i; 282 + FT_Bytes s = top; 283 + int ScriptCount; 284 + 285 + ScriptCount = BYTE2(s); 286 + 287 + for (i=0; i<ScriptCount; i++) { 288 + FT_Tag ScriptTag = BYTE4(s); 289 + FT_Bytes t = top + BYTE2(s); 290 + if (ScriptTag == TAG_KANA) { 291 + scan_Script(ret, t); 292 + } 293 + } 294 +} 295 + 296 +/********** header part *****************/ 297 + 298 +void scan_GSUB_Header(struct ft2vert_st *ret, const FT_Bytes top) { 299 + FT_Bytes s = top; 300 + FT_Fixed Version; 301 + FT_Offset ScriptList; 302 + FT_Offset FeatureList; 303 + FT_Offset LookupList; 304 + 305 +#ifdef DEBUG 306 + gsub_top = top; 307 +#endif /* DEBUG */ 308 + Version = BYTE4(s); 309 + ScriptList = BYTE2(s); 310 + FeatureList = BYTE2(s); 311 + LookupList = BYTE2(s); 312 + 313 + if (Version != 0x00010000) { 314 + fprintf(stderr, "warning: GSUB Version (=%.1f) is not 1.0\n", 315 + (double)Version / 0x10000); 316 + } 317 + 318 + scan_ScriptList (ret, top + ScriptList); 319 + scan_FeatureList(ret, top + FeatureList); 320 + /* vrt2 has higher priority over vert */ 321 + if (ret->vrt2Lookup != NULL) ret->vertLookup = ret->vrt2Lookup; 322 + scan_LookupList (ret, top + LookupList); 323 +} 324 + 325 +struct ft2vert_st *ft2vert_init(FT_Face face) { 326 + struct ft2vert_st *ret; 327 + int ft_error; 328 + FT_Bytes dummy, GSUB_table; 329 + 330 + MALLOC(ret, 1); 331 + ret->SubTableCount = 0; 332 + ret->vertLookup = NULL; 333 + ret->vrt2Lookup = NULL; 334 + ret->kanaFeature = NULL; 335 + ft_error = 336 + FT_OpenType_Validate( face, FT_VALIDATE_GSUB, 337 + &dummy, &dummy, &dummy, &GSUB_table, &dummy); 338 + if (ft_error == FT_Err_Unimplemented_Feature) { 339 + fprintf(stderr, "warning: FT_OpenType_Validate is disabled. " 340 + "Replace FreeType2 with otvalid-enabled version.\n"); 341 + return ret; 342 + } else if (ft_error != 0 || GSUB_table == 0) { 343 + fprintf(stderr, "warning: %s has no GSUB table.\n", 344 + face->family_name); 345 + return ret; 346 + } 347 + scan_GSUB_Header(ret, GSUB_table); 348 + if (ret->SubTableCount == 0) { 349 + fprintf(stderr, "warning: %s has no vrt2/vert feature.\n", 350 + face->family_name); 351 + } 352 + free((void*)GSUB_table); 353 + return ret; 354 +} 355 + 356 +/********** converting part *****************/ 357 + 358 +static FT_UInt get_vert_nth_gid(struct SubTable_st *t, FT_UInt gid, int n) { 359 + switch (t->SingleSubst.SubstFormat) { 360 + case 1: 361 + return gid + t->SingleSubst.DeltaGlyphID; 362 + case 2: 363 + return t->SingleSubst.Substitute[n]; 364 + } 365 + fprintf(stderr, "get_vert_nth_gid: internal error"); 366 + exit(1); 367 + return 0; 368 +} 369 + 370 + 371 +FT_UInt ft2vert_get_gid(struct ft2vert_st *ft2vert, FT_UInt gid) { 372 + int i, k; 373 + int j = 0; /* StartCoverageIndex */ 374 + 375 + for (k=0; k<ft2vert->SubTableCount; k++) { 376 + struct SubTable_st *t = &ft2vert->SubTable[k]; 377 + switch (t->Coverage.CoverageFormat) { 378 + case 1: 379 + for (i=0; i<t->Coverage.GlyphCount; i++) { 380 + if (t->Coverage.GlyphArray[i] == gid) { 381 + return get_vert_nth_gid(t, gid, i); 382 + } 383 + } 384 + break; 385 + case 2: 386 + for (i=0; i<t->Coverage.RangeCount; i++) { 387 + struct RangeRecord_st *r = &t->Coverage.RangeRecord[i]; 388 + if (r->Start <= gid && gid <= r->End) { 389 + return get_vert_nth_gid(t, gid, gid - r->Start + j); 390 + } 391 + j += r->End - r->Start + 1; 392 + } 393 + break; 394 + default: 395 + fprintf(stderr, "ft2vert_get_gid: internal error"); 396 + exit(1); 397 + } 398 + } 399 + return gid; 400 +} 401 + 402 +#endif /* PTEX */ 403