📄 kanjifont.cxx
字号:
#include "KanjiInfo.h"
#include "Kanjifont.h"
#include <winnls.h>
// Black square used for invalid kanji.
#define KANJI_BAD 0x2223
#define X ((char *) &x)
/**
* Reverse the byte alignment of a given unsigned long
*
* @param unsigned long
* @return unsigned long
*/
inline unsigned long TrueTypeKanjiFont::SWAPLONG(unsigned long x) {
char p;
p = X[0];
X[0] = X[3];
X[3] = p;
p = X[1];
X[1] = X[2];
X[2] = p;
return x;
}
/**
* Reverse the byte alignment of a given unsigned short
*
* @param unsigned short
* @return unsigned short
*/
inline unsigned short TrueTypeKanjiFont::SWAPSHORT(unsigned short x) {
char p;
p = X[0];
X[0] = X[1];
X[1] = p;
return (x);
}
TrueTypeKanjiFont::TrueTypeKanjiFont()
: font(NULL), cmap(NULL), gsub(NULL) {}
TrueTypeKanjiFont::~TrueTypeKanjiFont() {
if(font)
::DeleteObject (font);
font = NULL;
if(cmap)
delete [] cmap;
if(gsub)
delete [] gsub;
cmap = NULL;
gsub = NULL;
return;
}
/**
* Draw string of characters
*
* @param hdc Display contect to render to.
* @param jis Character to render
* @param x,y Location in the context.
*/
BOOL TrueTypeKanjiFont::TextOut(HDC hdc, int x , int y, LPCTSTR str) {
for(int n=0; n < strlen(str); ++n, x+=_width ) {
if(!DrawGlyph(hdc, str[n], x, y))
return FALSE;
}
return TRUE;
}
/**
* Basic render routine for TrueType fonts.
*
* @param hdc Display contect to render to.
* @param jis Character to render
* @param x,y Location in the context.
*/
BOOL TrueTypeKanjiFont::DrawGlyph(HDC hdc,int jis,int x,int y) {
unsigned short glyph;
::SetBkMode(hdc,TRANSPARENT);
font = (HFONT)::SelectObject(hdc,font);
glyph = FindGlyph(jis);
if(glyph == FindGlyph(KANJI_BAD))
return FALSE;
::ExtTextOut(
hdc,
x+_hshift,
y+_vshift,
ETO_GLYPH_INDEX,NULL,
(TCHAR*)&glyph,
1,
NULL);
font = (HFONT)::SelectObject(hdc,font); // Restore font
return TRUE;
}
/**
* This is a variant on the KanjiFont::draw routine that streatches
* the font to fill a given rectange. This is used for the big
* character in the character-info dialog box.
*
* @param hdc Context to render into.
* @param jis JIS code to render (will be converted on the fly).
* @param rect Rectangle that the character should fill to.
* @param vertical Non-zero for vertical printing.
*
* Because TrueType fonts are generate rotated for vertical printing,
* the vertical flag is not used, and this routine simply prints the
* character in the center of the selected box.
*/
BOOL TrueTypeKanjiFont::StretchGlyph(HDC hdc,int jis, const RECT& rc, bool vertical) {
return DrawGlyph(hdc, jis,
rc.left + (rc.right-rc.left+1 - _width)/2 - _hshift,
rc.bottom - (rc.bottom-rc.top+1 - _height) / 2);
}
/**
* Convert JIS character code into an glyph index for the font.
*
* @param jis JIS code to be processed.
*
* @return Glyph index to be used in rendering the character. If
* the glyph is not present, the routine will automatically return
* the default blank character.
*/
int TrueTypeKanjiFont::FindGlyph(int jis) {
int i;
jis = jis2unicode(jis); // Convert to UNICODE
for (i = 0; (i < count) && (jis > end[i]); i++); // Find segment containning charcter
if (jis < start[i])
return FindGlyph(KANJI_BAD);
if (!offset[i]) jis += delta[i]; // Displacement character
else jis = *(offset[i]/2 + (jis - start[i]) + &offset[i]); // Get value from glyph array.
if (!jis)
return FindGlyph(KANJI_BAD);
if (gsub) { // If this is here we are printing vertical.
for (i = 0; (i < vcount) && (from[i] < jis); i++); // Find the glyph in the substitution list.
if (from[i] == jis) jis = to[i]; // Do we need to stubstitue.
}
return (jis); // Return value.
}
#define CMAP (*((unsigned long *) "cmap")) // Character map tag
#define GSUB (*((unsigned long *) "GSUB")) // Glyph substitution tag
#define VERT (*((unsigned long *) "vert")) // Vertical printing tag
//
// Macro used for addressing within the TrueType font structure. This calucates and address from
// the base of one structure and casts the result to the final type. Note the offset can only
// be short, since the swap is done here.
//
#define ADDRESS(t,b,o) (struct t *) (((char *) b)+SWAPSHORT(o))
/**
* This routine opens a font up for operations.
*
* @param hdc Display context for the font (screen or printer).
* @param name Name of font to open.
* @param size pixel size
*
* @return BOOL - success
*/
BOOL TrueTypeKanjiFont::CreateFont(HDC hdc,TCHAR *name,int size,bool vertical) {
//
// Open the kanji font.
//
LOGFONT lf;
memset(&lf,0,sizeof(lf));
lstrcpy(lf.lfFaceName,name);
lf.lfHeight = -size;
lf.lfCharSet = SHIFTJIS_CHARSET;
// lf.lfEscapement = lf.lfOrientation = (vertical ? 900 : 0);
font = ::CreateFontIndirect(&lf);
if(!font)
return FALSE;
//
// Access the font thrugh the DC
//
TEXTMETRIC tm;
font = (HFONT) SelectObject(hdc,font);
//
// Get the metric information from the font.
//
GetTextMetrics (hdc,&tm);
_width = (short) tm.tmMaxCharWidth;
_height = -size;
_leading = _height/8;
_spacing = _width/12;
_hshift = (short)0;//_spacing/2-1;
_vshift = (short)0;// -height;
struct cmap_header { // cmap header structure
unsigned short version; // file version number (not used).
unsigned short number; // Number of encodings
};
struct table { // Encoding sub-tables
unsigned short platform_id; // platform id (we want 3 == PC)
unsigned short encoding_id; // encoding id (we want 1 == UNICODE)
unsigned long offset; // offset from start of cmap to the actual sub-table
} *tables;
struct subtable { // A partial version of a cmap sub-table
unsigned short format; // format (should be 4)
unsigned short length; // length of sub-table
unsigned short version; // version (not used)
unsigned short segCountX2; // twice the number of segments in the sub table
unsigned short searchRange; // junk
unsigned short entrySelector; // junk
unsigned short rangeShift; // junk
unsigned short endCount; // start of end list table
} *sub; // -- Rest of table is calculated on the fly, since this table cannot be represented with a C++ structure.
int i;
long j;
j = ::GetFontData(hdc,CMAP,0,NULL,0); // Size of the cmap data
// if (!(cmap = (char *) malloc(j)))
// return (true); // Make a memory block for this
if(!j)
return FALSE;
cmap = new char[j];
// Read the cmap.
if (GDI_ERROR == ::GetFontData(hdc,CMAP,0,cmap,j))
return FALSE;
// Get number of sub-tables.
j = SWAPSHORT(((struct cmap_header *) cmap)->number);
// Get sub-tables
tables = (struct table *) (cmap+sizeof(struct cmap_header));
// Find our sub-table (3,1)
for (i = 0; i < j; i++) {
if ((SWAPSHORT(tables[i].platform_id) == 3) && (SWAPSHORT(tables[i].encoding_id) == 1))
break;
}
// Could not find sub-table
if (i >= j)
return FALSE;
// Find the actual sub-table
sub = (struct subtable *) (cmap+ SWAPLONG(tables[i].offset));
if (SWAPSHORT(sub->format) != 4) // Check, is the table format 4.
return FALSE;
count = SWAPSHORT(sub->segCountX2)/2; // Get count (number of segments)
end = &sub->endCount; // Get address of segment tables
start = end+count+1;
delta = start+count;
offset = delta+count;
glyph = offset+count; // Get address of the glyph array
j = SWAPSHORT(sub->length)/2; // Swap bytes in the sub-table
for (i = 0; i < j; i++)
((unsigned short *) sub)[i] = SWAPSHORT(((unsigned short *) sub)[i]);
//
// If the font is to be printed vertical we will need to change the offsets and change some of
// the gylphs for vertical printing.
//
if (vertical) {
#pragma pack(push,1) // Necessary to get the structure alignement correct!
struct gsub_header { // Header structure for the GSUB
long version; // version (not used)
unsigned short script_list; // offset to script list (not actually used)
unsigned short feature_list; // offset to the feature list (this is checked)
unsigned short lookup_list; // offset to the lookup list.
} *header;
struct feature_element { // List element for featchers stored in the GSUB
unsigned long tag; // Tag.
unsigned short offset; // Offset in the feature list.
};
struct feature_list { // Features stored in this GSUB
unsigned short count; // Number of features in the GSUB
struct feature_element elements; // List of actual feature elements.
} *feature_list;
struct feature { // Description of an actual feature parameters
unsigned short param; // parameters (not used).
unsigned short count; // Number of indexes (assumed to be 1).
unsigned short index; // Actual index to feature.
} *feature;
struct lookup_list { // Contains offset to lookup lists
unsigned short count; // Number of lookup lists (not used, we get index from feature)
unsigned short offset; // Offset to list
} *lookup_list;
struct lookup { // Describes a lookup table and process.
unsigned short type; // lookup type (assumed to be 1 = substitution).
unsigned short flags; // not used.
unsigned short count; // Number of lists in the set (assumed to be 1)
unsigned short offset; // Offset to the first part of the list.
} *lookup;
struct sub_table { // This describes the replacment glyph list or substituiton table
unsigned short format; // format (assumed to be 2 = output glyphs)
unsigned short offset; // offset to the the from (coverage table).
unsigned short count; // number of entires.
unsigned short glyphs; // glyph list (fisrt glyph)
} *sub_table;
struct coverage { // Table indicates what glyphs are to be replaced with substitions
unsigned short format; // format (assumed to be 1)
unsigned short count; // number of entries (assumed to match sub-table)
unsigned short glyphs; // glyph list (first glyph)
} *coverage;
#pragma pack(pop) // Restore the structure alignment
j = ::GetFontData(hdc,GSUB,0,NULL,0); // Get size of the gsub
if(!j)
return FALSE;
gsub = new char[j];
// Allocat space
//if (!(gsub = (char *) malloc(j))) return (true);
::GetFontData(hdc,GSUB,0,gsub,j);
header = (struct gsub_header *) gsub;
// Find the feature list.
feature_list = ADDRESS(feature_list,gsub,header->feature_list);
j = SWAPSHORT(feature_list->count);
for (i = 0; (i < j) && (VERT != (&feature_list->elements)[i].tag); i++);
// No vert then we cannot use this font
if (i >= j)
return FALSE;
feature = ADDRESS(feature,feature_list,(&feature_list->elements)[i].offset); // Get feature for 'vert'
lookup_list = ADDRESS(lookup_list,gsub,header->lookup_list); // This is the base of the lookup tables.
lookup = ADDRESS(lookup,lookup_list,(&lookup_list->offset)[SWAPSHORT(feature->index)]); // Select lookup table we need
sub_table = ADDRESS(sub_table,lookup,lookup->offset); // Glyphs that are the substitues.
coverage = ADDRESS(coverage,sub_table,sub_table->offset); // Glyphs that are to be replaced.
vcount = SWAPSHORT(coverage->count); // These are the reall working values.
from = &coverage->glyphs;
to = &sub_table->glyphs;
for (i = 0; i < vcount; i++) { // Need to swap the byte order
from[i] = SWAPSHORT(from[i]);
to [i] = SWAPSHORT(to [i]);
}
//
// Correct the character placement for veritcal printing
//
_vshift = 0;
}
//
// Clean-up and restore the default font.
//
font = (HFONT)::SelectObject(hdc,font);
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -