mirror of
https://github.com/snowie2000/mactype.git
synced 2025-01-09 04:07:44 +08:00
2ebcf52f68
removed horizontal glyph width increment since it doesn't make the expect effect and its side-effect is unknown.
563 lines
16 KiB
C
563 lines
16 KiB
C
/*
|
||
* "ft2vert.c"
|
||
*
|
||
* Converter to vertical glyph ID by handling GSUB vrt2/vert feature
|
||
* requires FreeType-2.1.10 or latter
|
||
*
|
||
* (C) 2005 Nobuyuki TSUCHIMURA
|
||
*
|
||
* using such Lookup
|
||
* ScriptTag == 'kana'
|
||
* DefaultLangSys or LangSysTag == 'JAN '
|
||
* FeatureTag == 'vrt2' or 'vert'
|
||
*
|
||
* [reference]
|
||
* http://partners.adobe.com/public/developer/opentype/index_table_formats1.html
|
||
* http://partners.adobe.com/public/developer/opentype/index_table_formats.html
|
||
* http://partners.adobe.com/public/developer/opentype/index_tag9.html#vrt2
|
||
*/
|
||
|
||
//#include "xdvi-config.h"
|
||
//#include "xdvi.h"
|
||
//#ifdef USE_ZEIT
|
||
//#include <windows.h>
|
||
#include <ft2build.h>
|
||
#include FT_FREETYPE_H
|
||
#include FT_OPENTYPE_VALIDATE_H
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include "ft2vert.h"
|
||
const struct ivs_otft_desc {
|
||
int baseChar;
|
||
int otft_index;
|
||
} ivs_otft[] = {
|
||
#define OTFT_DEF_BEGIN(index) /**/
|
||
#define OTFT_DEF(baseChar, otft_index) { baseChar, otft_index },
|
||
#define OTFT_DEF_END(count) /**/
|
||
#include "ivs_otft.h"
|
||
#undef OTFT_DEF_BEGIN
|
||
#undef OTFT_DEF
|
||
#undef OTFT_DEF_END
|
||
};
|
||
const int ivs_otft_index[] = {
|
||
#define OTFT_DEF_BEGIN(index) index,
|
||
#define OTFT_DEF(baseChar, otft_index) /**/
|
||
#define OTFT_DEF_END(count) /**/
|
||
#include "ivs_otft.h"
|
||
#undef OTFT_DEF_BEGIN
|
||
#undef OTFT_DEF
|
||
#undef OTFT_DEF_END
|
||
};
|
||
const int ivs_otft_count[] = {
|
||
#define OTFT_DEF_BEGIN(index) /**/
|
||
#define OTFT_DEF(baseChar, otft_index) /**/
|
||
#define OTFT_DEF_END(count) count,
|
||
#include "ivs_otft.h"
|
||
#undef OTFT_DEF_BEGIN
|
||
#undef OTFT_DEF
|
||
#undef OTFT_DEF_END
|
||
};
|
||
|
||
#define TAG_KANA FT_MAKE_TAG('k', 'a', 'n', 'a')
|
||
#define TAG_HANI FT_MAKE_TAG('h', 'a', 'n', 'i')
|
||
#define TAG_JAN FT_MAKE_TAG('J', 'A', 'N', ' ')
|
||
#define TAG_VERT FT_MAKE_TAG('v', 'e', 'r', 't')
|
||
#define TAG_VRT2 FT_MAKE_TAG('v', 'r', 't', '2')
|
||
#define TAG_JP78 FT_MAKE_TAG('j', 'p', '7', '8')
|
||
#define TAG_JP90 FT_MAKE_TAG('j', 'p', '9', '0')
|
||
#define TAG_JP04 FT_MAKE_TAG('j', 'p', '0', '4')
|
||
|
||
#define VERT_LOOKUP_INDEX 0
|
||
#define JP78_LOOKUP_INDEX 1
|
||
#define JP90_LOOKUP_INDEX 2
|
||
#define JP04_LOOKUP_INDEX 3
|
||
|
||
#define MALLOC(ptr, size) ptr = malloc(sizeof((ptr)[0]) * (size))
|
||
#define BYTE2(p) ((p) += 2, (int)(p)[-2] << 8 | (p)[-1])
|
||
#define BYTE4(p) ((p) += 4, (int)(p)[-4] << 24 | (int)(p)[-3] << 16 | \
|
||
(int)(p)[-2] << 8 | (p)[-1])
|
||
|
||
struct ft2vert_st {
|
||
struct Lookup_st {
|
||
int SubTableCount;
|
||
struct SubTable_st {
|
||
struct SingleSubst_st {
|
||
FT_UInt SubstFormat;
|
||
FT_UInt DeltaGlyphID; /* SubstFormat == 1 */
|
||
int GlyphCount; /* SubstFormat == 2 */
|
||
FT_UInt *Substitute; /* SubstFormat == 2 */
|
||
} SingleSubst;
|
||
struct Coverage_st {
|
||
FT_UInt CoverageFormat;
|
||
int GlyphCount; /* CoverageFormat == 1 */
|
||
FT_UInt *GlyphArray; /* CoverageFormat == 1 */
|
||
int RangeCount; /* CoverageFormat == 2 */
|
||
struct RangeRecord_st
|
||
*RangeRecord; /* CoverageFormat == 2 */
|
||
} Coverage;
|
||
} *SubTable;
|
||
} Lookup[4];
|
||
FT_Bytes GSUB_table;
|
||
FT_Bytes kanaFeature, haniFeature;
|
||
FT_Bytes vertLookup, vrt2Lookup;
|
||
FT_Bytes jp78Lookup, jp90Lookup, jp04Lookup;
|
||
FT_UInt32* variantSelectors;
|
||
};
|
||
|
||
struct RangeRecord_st {
|
||
FT_UInt Start;
|
||
FT_UInt End;
|
||
};
|
||
|
||
|
||
int isInIndex(FT_Bytes s, int index) {
|
||
int i, count;
|
||
|
||
if (s == NULL) return 0;
|
||
count = BYTE2(s);
|
||
for (i = 0; i < count; i++) {
|
||
if (index == BYTE2(s)) return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
|
||
/********** Debug ***************/
|
||
|
||
#ifdef DEBUG
|
||
static FT_Bytes gsub_top;
|
||
|
||
void print_offset(char *message, const FT_Bytes ptr) {
|
||
printf("%s offset = %x\n", message, ptr - gsub_top);
|
||
}
|
||
|
||
char *tag_to_string(FT_Tag tag) {
|
||
static char str[5];
|
||
str[0] = tag >> 24;
|
||
str[1] = tag >> 16;
|
||
str[2] = tag >> 8;
|
||
str[3] = tag;
|
||
return str;
|
||
}
|
||
|
||
void hex_dump(const FT_Bytes top) {
|
||
int i, j;
|
||
FT_Bytes s = top;
|
||
|
||
for (j = 0; j < 100; j++) {
|
||
printf("%04x : ", j*8);
|
||
for (i = 0; i < 8; i++) {
|
||
printf("%02x ", s[i+j*8]);
|
||
}
|
||
printf("\n");
|
||
}
|
||
}
|
||
#endif /* DEBUG */
|
||
|
||
/********** Lookup part ***************/
|
||
|
||
void scan_Coverage(struct ft2vert_st *ret, const FT_Bytes top, const int l) {
|
||
int i;
|
||
FT_Bytes s = top;
|
||
struct Coverage_st *t;
|
||
|
||
t = &ret->Lookup[l].SubTable[ret->Lookup[l].SubTableCount].Coverage;
|
||
t->CoverageFormat = BYTE2(s);
|
||
switch (t->CoverageFormat) {
|
||
case 1:
|
||
t->GlyphCount = BYTE2(s);
|
||
MALLOC(t->GlyphArray, t->GlyphCount);
|
||
memset(t->GlyphArray, 0, sizeof(t->GlyphArray[0]) * t->GlyphCount);
|
||
for (i = 0; i < t->GlyphCount; i++) {
|
||
t->GlyphArray[i] = BYTE2(s);
|
||
}
|
||
break;
|
||
case 2:
|
||
t->RangeCount = BYTE2(s);
|
||
MALLOC(t->RangeRecord, t->RangeCount);
|
||
memset(t->RangeRecord, 0, sizeof(t->RangeRecord[0]) * t->RangeCount);
|
||
for (i = 0; i < t->RangeCount; i++) {
|
||
t->RangeRecord[i].Start = BYTE2(s);
|
||
t->RangeRecord[i].End = BYTE2(s);
|
||
s += 2; /* drop StartCoverageIndex */
|
||
}
|
||
break;
|
||
default:
|
||
#ifdef _DEBUG
|
||
fprintf(stderr, "scan_Coverage: unknown CoverageFormat (%d).",
|
||
t->CoverageFormat);
|
||
#endif
|
||
return;
|
||
}
|
||
ret->Lookup[l].SubTableCount++;
|
||
}
|
||
|
||
void scan_SubTable(struct ft2vert_st *ret, const FT_Bytes top, const int l) {
|
||
int i;
|
||
FT_Bytes s = top;
|
||
FT_Offset Coverage;
|
||
struct SingleSubst_st *t;
|
||
|
||
t = &ret->Lookup[l].SubTable[ret->Lookup[l].SubTableCount].SingleSubst;
|
||
t->SubstFormat = BYTE2(s);
|
||
Coverage = BYTE2(s);
|
||
scan_Coverage(ret, top + Coverage, l);
|
||
switch (t->SubstFormat) {
|
||
case 1: /* SingleSubstFormat1 */
|
||
t->DeltaGlyphID = BYTE2(s);
|
||
break;
|
||
case 2: /* SingleSubstFormat2 */
|
||
t->GlyphCount = BYTE2(s);
|
||
MALLOC(t->Substitute, t->GlyphCount);
|
||
memset(t->Substitute, 0, sizeof(t->Substitute[0]) * t->GlyphCount);
|
||
for (i = 0; i < t->GlyphCount; i++) {
|
||
t->Substitute[i] = BYTE2(s);
|
||
}
|
||
break;
|
||
#ifdef _DEBUG
|
||
default:
|
||
|
||
fprintf(stderr, "scan_SubTable: unknown SubstFormat (%d).",
|
||
t->SubstFormat);
|
||
#endif
|
||
|
||
}
|
||
}
|
||
|
||
void scan_Lookup(struct ft2vert_st *ret, const FT_Bytes top, const int l) {
|
||
int i;
|
||
FT_Bytes s = top;
|
||
FT_UShort LookupType;
|
||
FT_UShort LookupFlag;
|
||
FT_UShort SubTableCount;
|
||
FT_UShort SubTable;
|
||
|
||
LookupType = BYTE2(s);
|
||
LookupFlag = BYTE2(s);
|
||
SubTableCount = BYTE2(s);
|
||
SubTable = BYTE2(s);
|
||
|
||
MALLOC(ret->Lookup[l].SubTable, SubTableCount);
|
||
memset(ret->Lookup[l].SubTable, 0, sizeof(ret->Lookup[l].SubTable[0]) * SubTableCount);
|
||
for (i = 0; i < SubTableCount; i++) {
|
||
scan_SubTable(ret, top + SubTable, l);
|
||
}
|
||
if (ret->Lookup[l].SubTableCount != SubTableCount) {
|
||
|
||
#ifdef _DEBUG
|
||
fprintf(stderr, "warning (scan_Lookup): "
|
||
"SubTableCount (=%d) is not expected (=%d).\n",
|
||
ret->Lookup[l].SubTableCount, SubTableCount);
|
||
#endif
|
||
}
|
||
}
|
||
|
||
|
||
void scan_LookupList(struct ft2vert_st *ret, const FT_Bytes top) {
|
||
int i;
|
||
FT_Bytes s = top;
|
||
int LookupCount;
|
||
|
||
LookupCount = BYTE2(s);
|
||
|
||
for (i = 0; i < LookupCount; i++) {
|
||
FT_Bytes t = top + BYTE2(s);
|
||
if (isInIndex(ret->vertLookup, i)) {
|
||
scan_Lookup(ret, t, VERT_LOOKUP_INDEX);
|
||
} else if (isInIndex(ret->jp78Lookup, i)) {
|
||
scan_Lookup(ret, t, JP78_LOOKUP_INDEX);
|
||
} else if (isInIndex(ret->jp90Lookup, i)) {
|
||
scan_Lookup(ret, t, JP90_LOOKUP_INDEX);
|
||
} else if (isInIndex(ret->jp04Lookup, i)) {
|
||
scan_Lookup(ret, t, JP04_LOOKUP_INDEX);
|
||
}
|
||
}
|
||
}
|
||
|
||
/********** Feature part ****************/
|
||
|
||
void scan_FeatureList(struct ft2vert_st *ret, const FT_Bytes top) {
|
||
int i;
|
||
FT_Bytes s = top;
|
||
int FeatureCount;
|
||
|
||
FeatureCount = BYTE2(s);
|
||
|
||
for (i = 0; i < FeatureCount; i++) {
|
||
FT_Tag FeatureTag = BYTE4(s);
|
||
FT_Offset Feature = BYTE2(s);
|
||
if (isInIndex(ret->kanaFeature, i)) {
|
||
switch (FeatureTag) {
|
||
case TAG_VERT:
|
||
ret->vertLookup = top + Feature + 2;
|
||
break;
|
||
case TAG_VRT2:
|
||
ret->vrt2Lookup = top + Feature + 2;
|
||
break;
|
||
}
|
||
} else if (isInIndex(ret->haniFeature, i)) {
|
||
switch (FeatureTag) {
|
||
case TAG_JP78:
|
||
ret->jp78Lookup = top + Feature + 2;
|
||
break;
|
||
case TAG_JP90:
|
||
ret->jp90Lookup = top + Feature + 2;
|
||
break;
|
||
case TAG_JP04:
|
||
ret->jp04Lookup = top + Feature + 2;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/********** Script part ****************/
|
||
|
||
void scan_LangSys(struct ft2vert_st *ret, const FT_Bytes top, const FT_Tag ScriptTag) {
|
||
if (ScriptTag == TAG_KANA && ret->kanaFeature == NULL) ret->kanaFeature = top + 4;
|
||
if (ScriptTag == TAG_HANI && ret->haniFeature == NULL) ret->haniFeature = top + 4;
|
||
}
|
||
|
||
void scan_Script(struct ft2vert_st *ret, const FT_Bytes top, const FT_Tag ScriptTag) {
|
||
int i;
|
||
FT_Bytes s = top;
|
||
FT_Offset DefaultLangSys;
|
||
int LangSysCount;
|
||
|
||
DefaultLangSys = BYTE2(s);
|
||
if (DefaultLangSys != 0) {
|
||
scan_LangSys(ret, top + DefaultLangSys, ScriptTag);
|
||
}
|
||
LangSysCount = BYTE2(s);
|
||
|
||
for (i = 0; i < LangSysCount; i++) {
|
||
FT_Tag LangSysTag = BYTE4(s);
|
||
FT_Bytes t = top + BYTE2(s);
|
||
if (LangSysTag == TAG_JAN) {
|
||
scan_LangSys(ret, t, ScriptTag);
|
||
}
|
||
}
|
||
}
|
||
|
||
void scan_ScriptList(struct ft2vert_st *ret, const FT_Bytes top) {
|
||
int i;
|
||
FT_Bytes s = top;
|
||
int ScriptCount;
|
||
|
||
ScriptCount = BYTE2(s);
|
||
|
||
for (i = 0; i < ScriptCount; i++) {
|
||
FT_Tag ScriptTag = BYTE4(s);
|
||
FT_Bytes t = top + BYTE2(s);
|
||
if (ScriptTag == TAG_KANA || ScriptTag == TAG_HANI) {
|
||
scan_Script(ret, t, ScriptTag);
|
||
}
|
||
}
|
||
}
|
||
|
||
/********** header part *****************/
|
||
|
||
void scan_GSUB_Header(struct ft2vert_st *ret, const FT_Bytes top) {
|
||
FT_Bytes s = top;
|
||
FT_Fixed Version;
|
||
FT_Offset ScriptList;
|
||
FT_Offset FeatureList;
|
||
FT_Offset LookupList;
|
||
|
||
#ifdef DEBUG
|
||
gsub_top = top;
|
||
#endif /* DEBUG */
|
||
Version = BYTE4(s);
|
||
ScriptList = BYTE2(s);
|
||
FeatureList = BYTE2(s);
|
||
LookupList = BYTE2(s);
|
||
|
||
if (Version != 0x00010000) {
|
||
#ifdef _DEBUG
|
||
fprintf(stderr, "warning: GSUB Version (=%.1f) is not 1.0\n",
|
||
(double)Version / 0x10000);
|
||
#endif
|
||
}
|
||
|
||
scan_ScriptList(ret, top + ScriptList);
|
||
scan_FeatureList(ret, top + FeatureList);
|
||
/* vrt2 has higher priority over vert */
|
||
if (ret->vrt2Lookup != NULL) ret->vertLookup = ret->vrt2Lookup;
|
||
scan_LookupList(ret, top + LookupList);
|
||
}
|
||
|
||
struct ft2vert_st *ft2vert_init(FT_Face face) {
|
||
struct ft2vert_st *ret;
|
||
int ft_error, i;
|
||
FT_Bytes base = NULL;
|
||
FT_Bytes gdef = NULL;
|
||
FT_Bytes gpos = NULL;
|
||
FT_Bytes jstf = NULL;
|
||
|
||
MALLOC(ret, 1);
|
||
memset(ret, 0, sizeof(ret[0]));
|
||
for (i = 0; i < sizeof(ret->Lookup) / sizeof(ret->Lookup[0]); i++) {
|
||
ret->Lookup[i].SubTableCount = 0;
|
||
}
|
||
ret->vertLookup = NULL;
|
||
ret->vrt2Lookup = NULL;
|
||
ret->jp78Lookup = NULL;
|
||
ret->jp90Lookup = NULL;
|
||
ret->jp04Lookup = NULL;
|
||
ret->kanaFeature = NULL;
|
||
ret->haniFeature = NULL;
|
||
ret->GSUB_table = NULL;
|
||
ret->variantSelectors = FT_Face_GetVariantSelectors(face);
|
||
ft_error = FT_OpenType_Validate(
|
||
face, FT_VALIDATE_GSUB,
|
||
&base, &gdef, &gpos, &ret->GSUB_table, &jstf);
|
||
if (ft_error == FT_Err_Unimplemented_Feature) {
|
||
#ifdef _DEBUG
|
||
fprintf(stderr, "warning: FT_OpenType_Validate is disabled. "
|
||
"Replace FreeType2 with otvalid-enabled version.\n");
|
||
#endif
|
||
return ret;
|
||
} else if (ft_error != 0 || ret->GSUB_table == 0) {
|
||
#ifdef _DEBUG
|
||
fprintf(stderr, "warning: %s has no GSUB table.\n",
|
||
face->family_name);
|
||
#endif
|
||
return ret;
|
||
}
|
||
scan_GSUB_Header(ret, ret->GSUB_table);
|
||
if (ret->Lookup[VERT_LOOKUP_INDEX].SubTableCount == 0) {
|
||
#ifdef _DEBUG
|
||
fprintf(stderr, "warning: %s has no vrt2/vert feature.\n",
|
||
face->family_name);
|
||
#endif
|
||
}
|
||
// free((void*)GSUB_table);
|
||
return ret;
|
||
}
|
||
|
||
void ft2vert_final(FT_Face face, struct ft2vert_st *vert){
|
||
int i, j;
|
||
for (i = 0; i < sizeof(vert->Lookup) / sizeof(vert->Lookup[0]); i++) {
|
||
for (j = 0; j < vert->Lookup[i].SubTableCount; j++) {
|
||
free(vert->Lookup[i].SubTable[j].SingleSubst.Substitute);
|
||
free(vert->Lookup[i].SubTable[j].Coverage.GlyphArray);
|
||
free(vert->Lookup[i].SubTable[j].Coverage.RangeRecord);
|
||
}
|
||
free(vert->Lookup[i].SubTable);
|
||
}
|
||
FT_OpenType_Free(face, vert->GSUB_table);
|
||
free(vert);
|
||
// FT_Bytes kanaFeature;
|
||
// FT_Bytes haniFeature;
|
||
// FT_Bytes vertLookup;
|
||
// FT_Bytes vrt2Lookup;
|
||
// FT_Bytes jp78Lookup;
|
||
// FT_Bytes jp90Lookup;
|
||
// FT_Bytes jp04Lookup;
|
||
// FT_UInt32* variantSelectors;
|
||
}
|
||
|
||
/********** converting part *****************/
|
||
|
||
static FT_UInt get_vert_nth_gid(struct SubTable_st *t, FT_UInt gid, int n) {
|
||
switch (t->SingleSubst.SubstFormat) {
|
||
case 1:
|
||
return gid + t->SingleSubst.DeltaGlyphID;
|
||
case 2:
|
||
return t->SingleSubst.Substitute[n];
|
||
}
|
||
#ifdef _DEBUG
|
||
fprintf(stderr, "get_vert_nth_gid: internal error");
|
||
#endif
|
||
return 0;
|
||
}
|
||
|
||
|
||
FT_UInt ft2gsub_get_gid(const struct ft2vert_st *ft2vert, const FT_UInt gid, const int l) {
|
||
int i, k;
|
||
int j = 0; /* StartCoverageIndex */
|
||
|
||
for (k = 0; k < ft2vert->Lookup[l].SubTableCount; k++) {
|
||
struct SubTable_st *t = &ft2vert->Lookup[l].SubTable[k];
|
||
switch (t->Coverage.CoverageFormat) {
|
||
case 1:
|
||
for (i = 0; i < t->Coverage.GlyphCount; i++) {
|
||
if (t->Coverage.GlyphArray[i] == gid) {
|
||
return get_vert_nth_gid(t, gid, i);
|
||
}
|
||
}
|
||
break;
|
||
case 2:
|
||
for (i = 0; i < t->Coverage.RangeCount; i++) {
|
||
struct RangeRecord_st *r = &t->Coverage.RangeRecord[i];
|
||
if (r->Start <= gid && gid <= r->End) {
|
||
return get_vert_nth_gid(t, gid, gid - r->Start + j);
|
||
}
|
||
j += r->End - r->Start + 1;
|
||
}
|
||
break;
|
||
#ifdef _DEBUG
|
||
default:
|
||
|
||
fprintf(stderr, "ft2vert_get_gid: internal error");
|
||
#endif
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
FT_UInt ft2vert_get_gid(const struct ft2vert_st *ft2vert, const FT_UInt gid) {
|
||
FT_UInt tmp = ft2gsub_get_gid(ft2vert, gid, VERT_LOOKUP_INDEX);
|
||
return tmp ? tmp : gid;
|
||
}
|
||
|
||
int glyphs_comp(const void *_a, const void *_b) {
|
||
const struct ivs_otft_desc *a = (const struct ivs_otft_desc *)_a;
|
||
const struct ivs_otft_desc *b = (const struct ivs_otft_desc *)_b;
|
||
|
||
if (a->baseChar < b->baseChar)
|
||
return -1;
|
||
else if (a->baseChar > b->baseChar)
|
||
return 1;
|
||
return 0;
|
||
}
|
||
|
||
FT_UInt ft2_subst_uvs(const FT_Face face, const FT_UInt gid, const FT_UInt vsindex, const FT_UInt baseChar)
|
||
{
|
||
FT_UInt newglyph;
|
||
const struct ivs_otft_desc key = { baseChar }, *found;
|
||
struct ft2vert_st *ft2vert = (struct ft2vert_st *)face->generic.data;
|
||
if (!ft2vert)
|
||
return 0;
|
||
|
||
// <20><><EFBFBD>݂<EFBFBD><DD82><EFBFBD><EFBFBD>Ȃ<EFBFBD>UVS Subtable<6C><65><EFBFBD><EFBFBD><EFBFBD>T<EFBFBD><54>
|
||
if (ft2vert->variantSelectors)
|
||
return FT_Face_GetCharVariantIndex(face, baseChar, 0xE0100 + vsindex);
|
||
|
||
// GSUB<55>e<EFBFBD>[<5B>u<EFBFBD><75><EFBFBD><EFBFBD>OpenType feature<72>ɂ<EFBFBD><C982><EFBFBD><EFBFBD>V<EFBFBD>~<7E><><EFBFBD><EFBFBD><EFBFBD>[<5B>g<EFBFBD><67><EFBFBD><EFBFBD>
|
||
if (vsindex >= sizeof ivs_otft_index / sizeof ivs_otft_index[0])
|
||
return 0;
|
||
found = (const struct ivs_otft_desc *)bsearch(&key, ivs_otft + ivs_otft_index[vsindex], ivs_otft_count[vsindex], sizeof(struct ivs_otft_desc), glyphs_comp);
|
||
if (!found)
|
||
return 0;
|
||
|
||
// <20>V<EFBFBD>~<7E><><EFBFBD><EFBFBD><EFBFBD>[<5B>g<EFBFBD>ł<EFBFBD><C582><EFBFBD>feature<72><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><C282><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̂Œu<C592><75><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂<EFBFBD><DD82>B
|
||
newglyph = ft2gsub_get_gid(ft2vert, gid, found->otft_index);
|
||
// <20>u<EFBFBD><75><EFBFBD>ɐ<EFBFBD><C990><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>炻<EFBFBD><E782BB><EFBFBD><EFBFBD><EFBFBD>Ԃ<EFBFBD>
|
||
if (newglyph)
|
||
return newglyph;
|
||
// <20>t<EFBFBD>H<EFBFBD><48><EFBFBD>g<EFBFBD><67>GSUB<55>e<EFBFBD>[<5B>u<EFBFBD><75><EFBFBD>ɒu<C992><75><EFBFBD><EFBFBD><EFBFBD>`<60><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>Ȃ<EFBFBD><C882>B
|
||
// 'jp04'<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>邪'jp90'<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>Ȃ<EFBFBD><C882>Ƃ<EFBFBD><C682><EFBFBD>JIS90<39>t<EFBFBD>H<EFBFBD><48><EFBFBD>g<EFBFBD>Ƃ݂Ȃ<DD82><C882>A
|
||
// 'jp90'<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>邪'jp04'<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>Ȃ<EFBFBD><C882>Ƃ<EFBFBD><C682><EFBFBD>JIS2004<30>t<EFBFBD>H<EFBFBD><48><EFBFBD>g<EFBFBD>Ƃ݂Ȃ<DD82><C882>B
|
||
// JIS90<39>t<EFBFBD>H<EFBFBD><48><EFBFBD>g<EFBFBD><67>'jp90'<27><><EFBFBD>v<EFBFBD><76><EFBFBD><EFBFBD><EFBFBD>ꂽ<EFBFBD>ꍇ<EFBFBD><EA8D87>JIS2004<30>t<EFBFBD>H<EFBFBD><48><EFBFBD>g'jp04'<27><><EFBFBD>v<EFBFBD><76><EFBFBD><EFBFBD><EFBFBD>ꂽ<EFBFBD>ꍇ<EFBFBD><EA8D87>
|
||
// <20>f<EFBFBD>t<EFBFBD>H<EFBFBD><48><EFBFBD>g<EFBFBD><67><EFBFBD>`<60><><EFBFBD>v<EFBFBD><76><EFBFBD><EFBFBD><EFBFBD>ꂽ<EFBFBD><EA82BD><EFBFBD>`<60>ł<EFBFBD><C582><EFBFBD><EFBFBD>Ƃ݂Ȃ<DD82><C882>Ă<EFBFBD><C482>̂܂ܕԂ<DC95><D482>B
|
||
if (ft2vert->jp04Lookup && !ft2vert->jp90Lookup && found->otft_index == JP90_LOOKUP_INDEX
|
||
|| ft2vert->jp90Lookup && !ft2vert->jp04Lookup && found->otft_index == JP04_LOOKUP_INDEX)
|
||
return gid;
|
||
// <20>ǂ<EFBFBD><C782><EFBFBD><EFBFBD>ł<EFBFBD><C582>Ȃ<EFBFBD><C882><EFBFBD><EFBFBD>t<CE83>H<EFBFBD><48><EFBFBD>g<EFBFBD>͗v<CD97><76><EFBFBD><EFBFBD><EFBFBD>ꂽ<EFBFBD><EA82BD><EFBFBD>`<60><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>Ȃ<EFBFBD><C882>Ƃ݂Ȃ<DD82><C882>B
|
||
return 0;
|
||
}
|
||
|
||
//#endif /* USE_ZEIT */
|