⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kanjifont.cxx

📁 Displays the Japanese text
💻 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 + -