Permalink
Browse files

Use vertical substitution

  • Loading branch information...
1 parent 547e08d commit a5aae3278d5540351f78493f766c713bb2e1d676 @tnzk committed Oct 28, 2011
Showing with 778 additions and 24 deletions.
  1. +5 −2 Makefile
  2. +23 −0 common.h
  3. +37 −19 document.cpp
  4. +3 −0 document.h
  5. +1 −1 script.txt
  6. +2 −2 shineshockd.cpp
  7. +342 −0 ttgsubtable.cpp
  8. +365 −0 ttgsubtable.hpp
View
7 Makefile
@@ -1,5 +1,5 @@
-all: shineshockd.o document.o utf8decoder.o
- g++ -o shineshockd shineshockd.o document.o utf8decoder.o `pkg-config --libs opencv freetype2`
+all: shineshockd.o document.o utf8decoder.o ttgsubtable.o
+ g++ -o shineshockd shineshockd.o document.o utf8decoder.o ttgsubtable.o `pkg-config --libs opencv freetype2`
shineshockd.o: shineshockd.cpp
g++ -c shineshockd.cpp `pkg-config --cflags freetype2`
@@ -10,6 +10,9 @@ document.o: document.cpp
utf8decoder.o: utf8decoder.cpp
g++ -c utf8decoder.cpp
+ttgsubtable.o: ttgsubtable.cpp
+ g++ -c ttgsubtable.cpp `pkg-config --cflags freetype2`
+
clean:
rm -f *.png
rm -f *.o
View
23 common.h
@@ -0,0 +1,23 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+
+
+#define int32_t signed long
+#define uint32_t unsigned long
+
+//typedef signed long int32_t;
+//typedef unsigned long uint32_t;
+
+typedef signed long long __int64;
+typedef unsigned long long __uint64;
+
+typedef __int64 int64_t;
+typedef __uint64 uint64_t;
+
+#endif
View
56 document.cpp
@@ -14,20 +14,37 @@ Document::Document( string src_name, string tmpl_name)
src = NULL;
tmpl = NULL;
+ // Initialize FreeType2
+ printf("Initialize FreeType2...");
+ FT_Error error;
FT_Init_FreeType( &library );
- FT_New_Face( library, "mplus-1c-heavy.ttf", 0, &face );
+ FT_New_Face( library, "F910ComicW4.otf", 0, &face );
slot = face->glyph;
- FT_Set_Char_Size( face, 0, 5 * 64, 600, 600);
+ FT_Set_Char_Size( face, 0, 5 * 64, 300, 300);
+ printf("Done.\n");
+
+ // Pase GRUB table
+ printf("Parse GSUB table...");
+ unsigned long length = 0;
+ unsigned char* buf = (unsigned char*)malloc(2800000);
+ error = FT_Load_Sfnt_Table( face, FT_MAKE_TAG('G','S','U','B'), 0, buf, &length);
+ error = FT_Load_Sfnt_Table( face, FT_MAKE_TAG('G','S','U','B'), 0, buf, NULL);
+ gsubt.LoadGSUBTable((FT_Bytes)buf);
+ printf("Done.\n");
+
}
bool Document::Load()
{
- src = cvLoadImage("image.bmp", CV_LOAD_IMAGE_COLOR);
+
+ // Load the source image and template
+ // TODO: use any other file name
+ src = cvLoadImage("image.bmp", CV_LOAD_IMAGE_COLOR);
tmpl = cvLoadImage("template.bmp", CV_LOAD_IMAGE_COLOR);
if(src == 0 || tmpl == 0) return false;
+ // Create target image and generate buffer for template matching
said = cvCloneImage(src);
- cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 1.0, 1.0, 0, 4, 4);
result = cvCreateImage( cvSize( src->width - tmpl->width + 1, src->height - tmpl->height + 1), 32, 1);
return true;
@@ -39,8 +56,6 @@ int Document::Match( double threshould)
for( int y = 0; y < result->height; y++) {
for( int x = 0; x < result->width; x++) {
CvScalar s = cvGet2D(result,y,x);
- int xx = x + tmpl->width - 1;
- int yy = y + tmpl->height - 1;
if(s.val[0] >= threshould)
detections.push_back( Detection( x, y, s.val[0]));
}
@@ -50,27 +65,35 @@ int Document::Match( double threshould)
bool Document::Say( char* s, int detection_id)
{
+ // Draw the string specified onto a marker detected
Utf8Decoder u8d(s, (int)strlen(s));
IplImage* dst = this->said;
Detection detection = detections[detection_id];
- int cpos_x = detection.x;
+ int cpos_x = detection.x + 200;
int cpos_y = detection.y;
+ // TODO: make these modifiable
unsigned char fcr = 0x00;
unsigned char fcg = 0x54;
unsigned char fcb = 0xff;
for ( int n = 0; n < u8d.length(); n++ ){
- FT_Bitmap bitmap;
+ // Get correspoindng glyph ID from Unicode index.
+ // Use vertical substitution if the glyph has.
long int unicode_index = u8d.get(n);
+ long int glyph_index = FT_Get_Char_Index( face, unicode_index);
+ uint32_t substitute_glyph;
+ if( gsubt.GetVerticalGlyph( glyph_index, &substitute_glyph)) {
+ glyph_index = substitute_glyph;
+ }
- FT_Load_Char( face, unicode_index, FT_LOAD_RENDER);
- bitmap = slot->bitmap;
-
- int offset_y = cpos_y + ((64 - slot->metrics.horiBearingY) / 64) + 32;
+ FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER | FT_LOAD_VERTICAL_LAYOUT);
+ FT_Bitmap bitmap = slot->bitmap;
+ int offset_x = cpos_x + slot->metrics.vertBearingX / 64;
+ int offset_y = cpos_y + slot->metrics.vertBearingY / 64;
for( int i = 0; i < bitmap.rows * bitmap.width; i++){
- int x = ( i % bitmap.width) + cpos_x;
+ int x = ( i % bitmap.width) + offset_x;
int y = offset_y + ( i / bitmap.width);
unsigned char* src_b = (unsigned char*)(dst->imageData + dst->widthStep * y + x * 3);
unsigned char* src_g = (unsigned char*)(dst->imageData + dst->widthStep * y + x * 3 + 1);
@@ -88,18 +111,13 @@ bool Document::Say( char* s, int detection_id)
tmp = fcb * gph_a + *src_b * src_a;
*src_b = (tmp > 255) ? 255 : tmp;
}
- cpos_x += slot->metrics.horiAdvance / 64;
+ cpos_y += (slot->metrics.vertAdvance) / 64;
}
return true;
}
void Document::Everything()
{
- vector<Detection>::iterator it = detections.begin();
- while( it != detections.end()) {
- printf(" %3i, %3i: %20.20f\n", it->x, it->y, it->sim);
- it++;
- }
cvSaveImage( "shineshok_result.png", this->said);
}
View
3 document.h
@@ -3,6 +3,8 @@
#include <string>
#include <ft2build.h>
#include FT_FREETYPE_H
+#include FT_TRUETYPE_TABLES_H
+#include "ttgsubtable.hpp"
#include "utf8decoder.h"
using namespace std;
@@ -25,6 +27,7 @@ class Document {
IplImage* result;
CvFont font;
vector<Detection> detections;
+ CTTGSUBTable gsubt;
// To use FreeType
FT_Library library;
View
2 script.txt
@@ -1,3 +1,3 @@
-あさってのクラスマッチの
+あさっての~クラスマッチの
AagGc
最近鬱なんですよー
View
4 shineshockd.cpp
@@ -2,7 +2,7 @@
#include <fstream>
#include <string>
#include <vector>
-#include <stdio.h>
+//#include <stdio.h>
#include "document.h"
using namespace cv;
@@ -16,7 +16,7 @@ int main( int argc, char** argv)
}
double threshould = atof( argv[1]);
-
+
Document doc( "image.bmp", "template.bmp");
puts( doc.Load() ? "Successfully loaded." : "Load failed.");
printf( "%i markers detected.\n", doc.Match( threshould));
View
342 ttgsubtable.cpp
@@ -0,0 +1,342 @@
+#include "ttgsubtable.hpp"
+
+bool CTTGSUBTable::LoadGSUBTable(FT_Bytes gsub){
+ header.Version = gsub[0] << 24 | gsub[1] << 16 | gsub[2] << 8 | gsub[3];
+ if(header.Version != 0x00010000){
+ return false;
+ }
+ header.ScriptList = gsub[4] << 8 | gsub[5];
+ header.FeatureList = gsub[6] << 8 | gsub[7];
+ header.LookupList = gsub[8] << 8 | gsub[9];
+ return Parse(
+ &gsub[header.ScriptList],
+ &gsub[header.FeatureList],
+ &gsub[header.LookupList]);
+}
+
+// これがなかなか大変そうだが
+bool CTTGSUBTable::GetVerticalGlyph(uint32_t glyphnum, uint32_t *vglyphnum){
+ // FeatureからTagが'vrt2'か'vert'のものを探してみる
+ uint32_t tag[] = {
+ (uint8_t)'v' << 24 |
+ (uint8_t)'r' << 16 |
+ (uint8_t)'t' << 8 |
+ (uint8_t)'2',
+
+ (uint8_t)'v' << 24 |
+ (uint8_t)'e' << 16 |
+ (uint8_t)'r' << 8 |
+ (uint8_t)'t',
+ };
+ for(int i = 0;i < sizeof(tag) / sizeof(tag[0]);i++){
+ for(int j = 0;j < FeatureList.FeatureCount;j++){
+ if(FeatureList.FeatureRecord[j].FeatureTag == tag[i]
+ && GetVerticalGlyphSub(glyphnum,
+ vglyphnum,
+ &FeatureList.FeatureRecord[j].Feature)){
+ return true;
+ }
+ }
+ }
+ // 見つからなかった
+ return false;
+}
+
+bool CTTGSUBTable::GetVerticalGlyphSub(
+ uint32_t glyphnum,
+ uint32_t *vglyphnum,
+ struct TFeature *Feature){
+ // FeatureからリンクしているLookupTableのLookupTypeが1(=Single)を探す
+ for(int i = 0;i < Feature->LookupCount;i++){
+ int index = Feature->LookupListIndex[i];
+ if(index < 0 || LookupList.LookupCount < index){
+ continue;
+ }
+ if(LookupList.Lookup[index].LookupType == 1){
+ // Single
+ if(GetVerticalGlyphSub2(
+ glyphnum,
+ vglyphnum,
+ &LookupList.Lookup[index])){
+ return true;
+ }
+ }
+ }
+ // 見つからなかった
+ return false;
+}
+
+bool CTTGSUBTable::GetVerticalGlyphSub2(
+ uint32_t glyphnum,
+ uint32_t *vglyphnum,
+ struct TLookup *Lookup){
+ // SubTableの中から家捜しする
+ for(int i = 0;i < Lookup->SubTableCount;i++){
+ switch(Lookup->SubTable[i]->SubstFormat){
+ case 1:{
+ TSingleSubstFormat1 *tbl1 = (TSingleSubstFormat1*)Lookup->SubTable[i];
+ if(GetCoverageIndex(tbl1->Coverage, glyphnum) >= 0){
+ *vglyphnum = glyphnum + tbl1->DeltaGlyphID;
+ return true;
+ }
+ break;
+ }
+ case 2:{
+ TSingleSubstFormat2 *tbl2 = (TSingleSubstFormat2*)Lookup->SubTable[i];
+ int index = GetCoverageIndex(tbl2->Coverage, glyphnum);
+ if(0 <= index && index < tbl2->GlyphCount){
+ *vglyphnum = tbl2->Substitute[index];
+ return true;
+ }
+ break;
+ }
+ }
+ }
+ return false;
+}
+
+int CTTGSUBTable::GetCoverageIndex(struct TCoverageFormatBase *Coverage, uint32_t g){
+ int i;
+ if(Coverage == NULL){
+ return -1;
+ }
+ switch(Coverage->CoverageFormat){
+ case 1:{
+ TCoverageFormat1 *c1 = (TCoverageFormat1*)Coverage;
+ for(i = 0;i < c1->GlyphCount;i++){
+ if((uint32_t)c1->GlyphArray[i] == g){
+ return i; // Found.
+ }
+ }
+ return -1; // Not found.
+ }
+ case 2:{
+ TCoverageFormat2 *c2 = (TCoverageFormat2*)Coverage;
+ for(i = 0;i < c2->RangeCount;i++){
+ uint32_t s = c2->RangeRecord[i].Start;
+ uint32_t e = c2->RangeRecord[i].End;
+ uint32_t si = c2->RangeRecord[i].StartCoverageIndex;
+ if(si + s <= g && g <= si + e){
+ return si + g - s;
+ }
+ }
+ return -1; // Not found.
+ }
+ }
+ return -1;
+}
+
+bool CTTGSUBTable::Parse(
+ FT_Bytes scriptlist,
+ FT_Bytes featurelist,
+ FT_Bytes lookuplist){
+ ParseScriptList(scriptlist, &ScriptList);
+ ParseFeatureList(featurelist, &FeatureList);
+ ParseLookupList(lookuplist, &LookupList);
+ return true;
+}
+
+void CTTGSUBTable::ParseScriptList(FT_Bytes raw, struct TScriptList *rec){
+ int i;
+ FT_Bytes sp = raw;
+ rec->ScriptCount = GetUInt16(sp);
+ if(rec->ScriptCount <= 0){
+ return; // 無い
+ }
+ rec->ScriptRecord = new struct TScriptRecord[rec->ScriptCount];
+ for(i = 0;i < rec->ScriptCount;i++){
+ rec->ScriptRecord[i].ScriptTag = GetUInt32(sp);
+ uint16_t offset = GetUInt16(sp);
+ ParseScript(
+ &raw[offset],
+ &rec->ScriptRecord[i].Script);
+ }
+}
+
+void CTTGSUBTable::ParseScript(FT_Bytes raw, struct TScript *rec){
+ int i;
+ FT_Bytes sp = raw;
+ rec->DefaultLangSys = GetUInt16(sp);
+ rec->LangSysCount = GetUInt16(sp);
+ if(rec->LangSysCount <= 0){
+ return;
+ }
+ rec->LangSysRecord = new struct TLangSysRecord[rec->LangSysCount];
+ for(i = 0;i < rec->LangSysCount;i++){
+ rec->LangSysRecord[i].LangSysTag = GetUInt32(sp);
+ uint16_t offset = GetUInt16(sp);
+ ParseLangSys(
+ &raw[offset],
+ &rec->LangSysRecord[i].LangSys);
+ }
+}
+
+void CTTGSUBTable::ParseLangSys(FT_Bytes raw, struct TLangSys *rec){
+ int i;
+ FT_Bytes sp = raw;
+ rec->LookupOrder = GetUInt16(sp);
+ rec->ReqFeatureIndex = GetUInt16(sp);
+ rec->FeatureCount = GetUInt16(sp);
+ if(rec->FeatureCount <= 0)
+ return;
+ rec->FeatureIndex = new uint16_t[rec->FeatureCount];
+}
+
+void CTTGSUBTable::ParseFeatureList(FT_Bytes raw, TFeatureList *rec){
+ int i;
+ FT_Bytes sp = raw;
+ rec->FeatureCount = GetUInt16(sp);
+ if(rec->FeatureCount <= 0){
+ return;
+ }
+ rec->FeatureRecord = new struct TFeatureRecord[rec->FeatureCount];
+ for(i = 0;i < rec->FeatureCount;i++){
+ rec->FeatureRecord[i].FeatureTag = GetUInt32(sp);
+ uint16_t offset = GetUInt16(sp);
+ ParseFeature(
+ &raw[offset],
+ &rec->FeatureRecord[i].Feature);
+ }
+}
+
+void CTTGSUBTable::ParseFeature(FT_Bytes raw, TFeature *rec){
+ int i;
+ FT_Bytes sp = raw;
+ rec->FeatureParams = GetUInt16(sp);
+ rec->LookupCount = GetUInt16(sp);
+ if(rec->LookupCount <= 0){
+ return;
+ }
+ rec->LookupListIndex = new uint16_t[rec->LookupCount];
+ for(i = 0;i < rec->LookupCount;i++){
+ rec->LookupListIndex[i] = GetUInt16(sp);
+ }
+}
+
+void CTTGSUBTable::ParseLookupList(FT_Bytes raw, TLookupList *rec){
+ int i;
+ FT_Bytes sp = raw;
+ rec->LookupCount = GetUInt16(sp);
+ if(rec->LookupCount <= 0){
+ return;
+ }
+ rec->Lookup = new struct TLookup[rec->LookupCount];
+ for(i = 0;i < rec->LookupCount;i++){
+ uint16_t offset = GetUInt16(sp);
+ ParseLookup(
+ &raw[offset],
+ &rec->Lookup[i]);
+ }
+}
+
+void CTTGSUBTable::ParseLookup(FT_Bytes raw, TLookup *rec){
+ int i;
+ FT_Bytes sp = raw;
+ rec->LookupType = GetUInt16(sp);
+ rec->LookupFlag = GetUInt16(sp);
+ rec->SubTableCount = GetUInt16(sp);
+ if(rec->SubTableCount <= 0){
+ return;
+ }
+ rec->SubTable = new struct TSubTableBase*[rec->SubTableCount];
+ for(i = 0;i < rec->SubTableCount;i++){
+ rec->SubTable[i] = NULL; // とりあえず安全のためNULLを入れておく
+ }
+ // こちらで改めてやる。
+ // とりあえずLookupTypeが1のときだけで縦書きは出来るんじゃなかろうか。
+ if(rec->LookupType != 1)
+ return;
+ for(i = 0;i < rec->SubTableCount;i++){
+ uint16_t offset = GetUInt16(sp);
+ ParseSingleSubst(
+ &raw[offset],
+ &rec->SubTable[i]);
+ }
+}
+
+void CTTGSUBTable::ParseCoverage(FT_Bytes raw, TCoverageFormatBase **rec){
+ FT_Bytes sp = raw;
+ uint16_t Format = GetUInt16(sp);
+ switch(Format){
+ case 1:
+ *rec = new TCoverageFormat1();
+ ParseCoverageFormat1(raw, (TCoverageFormat1*)*rec);
+ break;
+ case 2:
+ *rec = new TCoverageFormat2();
+ ParseCoverageFormat2(raw, (TCoverageFormat2*)*rec);
+ break;
+ }
+}
+void CTTGSUBTable::ParseCoverageFormat1(FT_Bytes raw, TCoverageFormat1 *rec){
+ int i;
+ FT_Bytes sp = raw;
+ GetUInt16(sp); // 読み捨て(Format)
+ rec->GlyphCount = GetUInt16(sp);
+ if(rec->GlyphCount <= 0){
+ return;
+ }
+ rec->GlyphArray = new uint16_t[rec->GlyphCount];
+ for(i = 0;i < rec->GlyphCount;i++){
+ rec->GlyphArray[i] = GetUInt16(sp);
+ }
+}
+void CTTGSUBTable::ParseCoverageFormat2(FT_Bytes raw, TCoverageFormat2 *rec){
+ int i;
+ FT_Bytes sp = raw;
+ GetUInt16(sp); // 読み捨て(Format)
+ rec->RangeCount = GetUInt16(sp);
+ if(rec->RangeCount <= 0){
+ return;
+ }
+ rec->RangeRecord = new TRangeRecord[rec->RangeCount];
+ for(i = 0;i < rec->RangeCount;i++){
+ rec->RangeRecord[i].Start = GetUInt16(sp);
+ rec->RangeRecord[i].End = GetUInt16(sp);
+ rec->RangeRecord[i].StartCoverageIndex = GetUInt16(sp);
+ }
+}
+
+void CTTGSUBTable::ParseSingleSubst(FT_Bytes raw, TSubTableBase **rec){
+ FT_Bytes sp = raw;
+ uint16_t Format = GetUInt16(sp);
+ switch(Format){
+ case 1:
+ *rec = new TSingleSubstFormat1();
+ ParseSingleSubstFormat1(raw, (TSingleSubstFormat1*)*rec);
+ break;
+ case 2:
+ *rec = new TSingleSubstFormat2();
+ ParseSingleSubstFormat2(raw, (TSingleSubstFormat2*)*rec);
+ break;
+ }
+}
+
+void CTTGSUBTable::ParseSingleSubstFormat1(FT_Bytes raw, TSingleSubstFormat1 *rec){
+ FT_Bytes sp = raw;
+ GetUInt16(sp); // 読み捨て(Format)
+ uint16_t offset = GetUInt16(sp);
+ ParseCoverage(
+ &raw[offset],
+ &rec->Coverage);
+ rec->DeltaGlyphID = GetInt16(sp);
+}
+
+void CTTGSUBTable::ParseSingleSubstFormat2(FT_Bytes raw, TSingleSubstFormat2 *rec){
+ int i;
+ FT_Bytes sp = raw;
+ GetUInt16(sp); // 読み捨て(Format)
+ uint16_t offset = GetUInt16(sp);
+ ParseCoverage(
+ &raw[offset],
+ &rec->Coverage);
+ rec->GlyphCount = GetUInt16(sp);
+ if(rec->GlyphCount <= 0){
+ return;
+ }
+ rec->Substitute = new uint16_t[rec->GlyphCount];
+ for(i = 0;i < rec->GlyphCount;i++){
+ rec->Substitute[i] = GetUInt16(sp);
+ }
+}
+
View
365 ttgsubtable.hpp
@@ -0,0 +1,365 @@
+#ifndef TTGSUBTable_H
+#define TTGSUBTable_H
+
+// Use FreeType2 library.
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include "common.h"
+
+class CTTGSUBTable{
+public:
+ CTTGSUBTable(void):loaded(false){};
+ CTTGSUBTable(FT_Bytes gsub):loaded(false){
+ LoadGSUBTable(gsub);
+ }
+ virtual ~CTTGSUBTable(){}
+
+ bool IsOk(void) const{return loaded;}
+ bool LoadGSUBTable(FT_Bytes gsub);
+
+ bool GetVerticalGlyph(uint32_t glyphnum, uint32_t *vglyphnum);
+ // メンバ構造体
+ struct tt_gsub_header{
+ uint32_t Version;
+ uint16_t ScriptList;
+ uint16_t FeatureList;
+ uint16_t LookupList;
+ };
+ // ScriptList 用
+ struct TLangSys{
+ uint16_t LookupOrder; // NULL
+ uint16_t ReqFeatureIndex; // if no required features = 0xFFFF
+ uint16_t FeatureCount;
+ uint16_t *FeatureIndex; // Array
+
+ TLangSys():LookupOrder(0),ReqFeatureIndex(0),FeatureCount(0),FeatureIndex(NULL){}
+ ~TLangSys(){if(FeatureIndex) delete[] FeatureIndex;}
+ private:
+ // コピー殺し
+ TLangSys(const TLangSys&);
+ TLangSys& operator=(const TLangSys&);
+ };
+ struct TLangSysRecord{
+ uint32_t LangSysTag;
+ struct TLangSys LangSys;
+
+ TLangSysRecord():LangSysTag(0){}
+ private:
+ // コピー殺し
+ TLangSysRecord(const TLangSysRecord&);
+ TLangSysRecord& operator=(const TLangSysRecord&);
+ };
+ struct TScript{
+ uint16_t DefaultLangSys; // May-be NULL?
+ uint16_t LangSysCount;
+ struct TLangSysRecord *LangSysRecord; // Array
+
+ TScript():DefaultLangSys(0),LangSysCount(0),LangSysRecord(NULL){}
+ ~TScript(){if(LangSysRecord) delete[] LangSysRecord;}
+ private:
+ // コピー殺し
+ TScript(const TScript&);
+ TScript& operator=(const TScript&);
+ };
+ struct TScriptRecord{
+ uint32_t ScriptTag;
+ struct TScript Script;
+
+ TScriptRecord():ScriptTag(0){}
+ private:
+ // コピー殺し
+ TScriptRecord(const TScriptRecord&);
+ TScriptRecord& operator=(const TScriptRecord&);
+ };
+ struct TScriptList{
+ uint16_t ScriptCount;
+ struct TScriptRecord *ScriptRecord; // Array
+
+ TScriptList():ScriptCount(0),ScriptRecord(NULL){}
+ ~TScriptList(){if(ScriptRecord) delete[] ScriptRecord;}
+ private:
+ // コピー殺し
+ TScriptList(const TScriptList&);
+ TScriptList& operator=(const TScriptList&);
+ };
+
+ // FeatureList 用
+ struct TFeature{
+ uint16_t FeatureParams;
+ int LookupCount;
+ uint16_t *LookupListIndex; // Array
+
+ TFeature():FeatureParams(0),LookupCount(0),LookupListIndex(NULL){}
+ ~TFeature(){if(LookupListIndex) delete[] LookupListIndex;}
+ private:
+ // コピー殺し
+ TFeature(const TFeature&);
+ TFeature& operator=(const TFeature&);
+ };
+ struct TFeatureRecord{
+ uint32_t FeatureTag;
+ struct TFeature Feature;
+
+ TFeatureRecord():FeatureTag(0){}
+ private:
+ // コピー殺し
+ TFeatureRecord(const TFeatureRecord&);
+ TFeatureRecord& operator=(const TFeatureRecord&);
+ };
+ struct TFeatureList{
+ int FeatureCount;
+ struct TFeatureRecord *FeatureRecord; // Array
+
+ TFeatureList():FeatureCount(0),FeatureRecord(NULL){}
+ ~TFeatureList(){if(FeatureRecord) delete[] FeatureRecord;}
+ private:
+ // コピー殺し
+ TFeatureList(const TFeatureList&);
+ TFeatureList& operator=(const TFeatureList&);
+ };
+
+ // LookupList 用
+ enum TLookupFlag{
+ LOOKUPFLAG_RightToLeft = 0x0001,
+ LOOKUPFLAG_IgnoreBaseGlyphs = 0x0002,
+ LOOKUPFLAG_IgnoreLigatures = 0x0004,
+ LOOKUPFLAG_IgnoreMarks = 0x0008,
+ LOOKUPFLAG_Reserved = 0x00F0,
+ LOOKUPFLAG_MarkAttachmentType = 0xFF00,
+ };
+ struct TCoverageFormatBase{
+ uint16_t CoverageFormat;
+
+ TCoverageFormatBase():CoverageFormat(0){}
+ virtual ~TCoverageFormatBase(){}
+ private:
+ // コピー殺し
+ TCoverageFormatBase(const TCoverageFormatBase&);
+ TCoverageFormatBase& operator=(const TCoverageFormatBase&);
+ };
+ struct TCoverageFormat1: public TCoverageFormatBase{
+ uint16_t GlyphCount;
+ uint16_t *GlyphArray; // Array
+
+ TCoverageFormat1():GlyphCount(0),GlyphArray(NULL){CoverageFormat = 1;}
+ ~TCoverageFormat1(){if(GlyphArray) delete[] GlyphArray;}
+ private:
+ // コピー殺し
+ TCoverageFormat1(const TCoverageFormat1&);
+ TCoverageFormat1& operator=(const TCoverageFormat1&);
+ };
+ struct TRangeRecord{
+ uint16_t Start;
+ uint16_t End;
+ uint16_t StartCoverageIndex;
+
+ TRangeRecord():Start(0),End(0),StartCoverageIndex(0){}
+ private:
+ // コピー殺し
+ TRangeRecord(const TRangeRecord&);
+ TRangeRecord& operator=(const TRangeRecord&);
+ };
+ struct TCoverageFormat2: public TCoverageFormatBase{
+ uint16_t RangeCount;
+ struct TRangeRecord *RangeRecord; // Array
+
+ TCoverageFormat2():RangeCount(0),RangeRecord(NULL){CoverageFormat = 2;}
+ ~TCoverageFormat2(){if(RangeRecord) delete[] RangeRecord;}
+ private:
+ // コピー殺し
+ TCoverageFormat2(const TCoverageFormat2&);
+ TCoverageFormat2& operator=(const TCoverageFormat2&);
+ };
+ struct TClassDefFormatBase{
+ uint16_t ClassFormat;
+
+ TClassDefFormatBase():ClassFormat(0){}
+ virtual ~TClassDefFormatBase(){}
+ private:
+ // コピー殺し
+ TClassDefFormatBase(const TClassDefFormatBase&);
+ TClassDefFormatBase& operator=(const TClassDefFormatBase&);
+ };
+ struct TClassDefFormat1: public TClassDefFormatBase{
+ uint16_t StartGlyph;
+ uint16_t GlyphCount;
+ uint16_t *ClassValueArray; // Array
+
+ TClassDefFormat1():StartGlyph(0),GlyphCount(0),ClassValueArray(NULL){ClassFormat = 1;}
+ ~TClassDefFormat1(){if(ClassValueArray) delete[] ClassValueArray;}
+ private:
+ // コピー殺し
+ TClassDefFormat1(const TClassDefFormat1&);
+ TClassDefFormat1& operator=(const TClassDefFormat1&);
+ };
+ struct TClassRangeRecord{
+ uint16_t Start;
+ uint16_t End;
+ uint16_t Class;
+
+ TClassRangeRecord():Start(0),End(0),Class(0){}
+ private:
+ // コピー殺し
+ TClassRangeRecord(const TClassRangeRecord&);
+ TClassRangeRecord& operator=(const TClassRangeRecord&);
+ };
+ struct TClassDefFormat2: public TClassDefFormatBase{
+ uint16_t ClassRangeCount;
+ struct TClassRangeRecord *ClassRangeRecord; // Array
+
+ TClassDefFormat2():ClassRangeCount(0),ClassRangeRecord(NULL){ClassFormat = 2;}
+ ~TClassDefFormat2(){if(ClassRangeRecord) delete[] ClassRangeRecord;}
+ private:
+ // コピー殺し
+ TClassDefFormat2(const TClassDefFormat2&);
+ TClassDefFormat2& operator=(const TClassDefFormat2&);
+ };
+ struct TDevice{
+ uint16_t StartSize;
+ uint16_t EndSize;
+ uint16_t DeltaFormat;
+
+ TDevice():StartSize(0),EndSize(0),DeltaFormat(0){}
+ private:
+ // コピー殺し
+ TDevice(const TDevice&);
+ TDevice& operator=(const TDevice&);
+ };
+ struct TSubTableBase{
+ uint16_t SubstFormat;
+
+ TSubTableBase():SubstFormat(0){}
+ virtual ~TSubTableBase(){}
+ private:
+ // コピー殺し
+ TSubTableBase(const TSubTableBase&);
+ TSubTableBase& operator=(const TSubTableBase&);
+ };
+ // LookupType 1: Single Substitution Subtable
+ struct TSingleSubstFormat1: public TSubTableBase{
+ TCoverageFormatBase *Coverage;
+ int16_t DeltaGlyphID;
+
+ TSingleSubstFormat1():DeltaGlyphID(0),Coverage(NULL){SubstFormat = 1;}
+ ~TSingleSubstFormat1(){if(Coverage) delete Coverage;}
+ private:
+ // コピー殺し
+ TSingleSubstFormat1(const TSingleSubstFormat1&);
+ TSingleSubstFormat1& operator=(const TSingleSubstFormat1&);
+ };
+ struct TSingleSubstFormat2: public TSubTableBase{
+ TCoverageFormatBase *Coverage;
+ uint16_t GlyphCount;
+ uint16_t *Substitute; // Array
+
+ TSingleSubstFormat2():Coverage(NULL),GlyphCount(0),Substitute(NULL){SubstFormat = 2;}
+ ~TSingleSubstFormat2(){if(Coverage) delete Coverage;if(Substitute) delete[] Substitute;}
+ private:
+ // コピー殺し
+ TSingleSubstFormat2(const TSingleSubstFormat2&);
+ TSingleSubstFormat2& operator=(const TSingleSubstFormat2&);
+ };
+ struct TLookup{
+ uint16_t LookupType;
+ uint16_t LookupFlag;
+ uint16_t SubTableCount;
+ struct TSubTableBase **SubTable; // Array
+
+ TLookup():LookupType(0),LookupFlag(0),SubTableCount(0),SubTable(NULL){}
+ ~TLookup(){
+ if(SubTableCount > 0 && SubTable != NULL){
+ for(int i = 0;i < SubTableCount;i++){
+ delete SubTable[i];
+ }
+ delete[] SubTable;
+ }
+ }
+ private:
+ // コピー殺し
+ TLookup(const TLookup&);
+ TLookup& operator=(const TLookup&);
+ };
+ struct TLookupList{
+ int LookupCount;
+ struct TLookup *Lookup; // Array
+
+ TLookupList():LookupCount(0),Lookup(NULL){}
+ ~TLookupList(){if(Lookup) delete[] Lookup;}
+ private:
+ // コピー殺し
+ TLookupList(const TLookupList&);
+ TLookupList& operator=(const TLookupList&);
+ };
+
+ // メンバ関数
+ bool Parse(
+ FT_Bytes scriptlist,
+ FT_Bytes featurelist,
+ FT_Bytes lookuplist);
+ void ParseScriptList(FT_Bytes raw, TScriptList *rec);
+ void ParseScript(FT_Bytes raw, TScript *rec);
+ void ParseLangSys(FT_Bytes raw, TLangSys *rec);
+
+ void ParseFeatureList(FT_Bytes raw, TFeatureList *rec);
+ void ParseFeature(FT_Bytes raw, TFeature *rec);
+
+ void ParseLookupList(FT_Bytes raw, TLookupList *rec);
+ void ParseLookup(FT_Bytes raw, TLookup *rec);
+
+ void ParseCoverage(FT_Bytes raw, TCoverageFormatBase **rec);
+ void ParseCoverageFormat1(FT_Bytes raw, TCoverageFormat1 *rec);
+ void ParseCoverageFormat2(FT_Bytes raw, TCoverageFormat2 *rec);
+
+ void ParseSingleSubst(FT_Bytes raw, TSubTableBase **rec);
+ void ParseSingleSubstFormat1(FT_Bytes raw, TSingleSubstFormat1 *rec);
+ void ParseSingleSubstFormat2(FT_Bytes raw, TSingleSubstFormat2 *rec);
+
+ // こういう不毛な命名は好きじゃないのだが
+ bool GetVerticalGlyphSub(
+ uint32_t glyphnum,
+ uint32_t *vglyphnum,
+ struct TFeature *Feature);
+ bool GetVerticalGlyphSub2(
+ uint32_t glyphnum,
+ uint32_t *vglyphnum,
+ struct TLookup *Lookup);
+ // if not found, this function returns -1.
+ int GetCoverageIndex(struct TCoverageFormatBase *Coverage, uint32_t g);
+
+ // データ採取用
+ uint8_t GetUInt8(FT_Bytes& p) const{
+ uint8_t ret = p[0];
+ p += 1;
+ return ret;
+ }
+ int16_t GetInt16(FT_Bytes& p) const{
+ uint16_t ret = p[0] << 8 | p[1];
+ p += 2;
+ return *(int16_t*)&ret;
+ }
+ uint16_t GetUInt16(FT_Bytes& p) const{
+ uint16_t ret = p[0] << 8 | p[1];
+ p += 2;
+ return ret;
+ }
+ int32_t GetInt32(FT_Bytes& p) const{
+ uint32_t ret = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
+ p += 4;
+ return *(int32_t*)&ret;
+ }
+ uint32_t GetUInt32(FT_Bytes& p) const{
+ uint32_t ret = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
+ p += 4;
+ return ret;
+ }
+
+ // メンバ変数
+ bool loaded;
+ struct tt_gsub_header header;
+ struct TScriptList ScriptList;
+ struct TFeatureList FeatureList;
+ struct TLookupList LookupList;
+};
+
+#endif

0 comments on commit a5aae32

Please sign in to comment.