2 * Kimikage NScripter Plugins Project
\r
4 * This software is distributed under a BSD-style license.
\r
5 * See license.txt for more information.
\r
13 #undef GetGlyphOutline
\r
15 Glyph::Glyph( void )
\r
21 Glyph::Glyph( const Glyph& glyph )
\r
23 character = glyph.character;
\r
24 memcpy( &metrics, &glyph.metrics, sizeof( metrics ) );
\r
25 bufferSize = glyph.bufferSize;
\r
26 if ( bufferSize > 0 )
\r
28 buffer = new unsigned char[bufferSize];
\r
29 memcpy( buffer, glyph.buffer, bufferSize );
\r
37 Glyph::Glyph( unsigned int character )
\r
41 this->character = character;
\r
42 const unsigned int index =
\r
43 ( mode & GGO_GLYPH_INDEX ) ? cm.getGlyphIndex( character ) : character;
\r
45 //
\95K
\97v
\83o
\83b
\83t
\83@
\83T
\83C
\83Y
\81C
\83\81\83g
\83\8a\83N
\83X
\8eæ
\93¾(lpvBuffer=NULL)
\r
46 const DWORD bufferRequest = GetGlyphOutline( cm.getDC(), index, mode, &metrics, 0, NULL, &transform );
\r
47 if ( bufferRequest == GDI_ERROR ) return;
\r
49 if ( bufferRequest == 0 )
\r
51 // GetGlyphOutline
\82Ì
\83o
\83O
\82É
\82æ
\82è0
\82É
\82È
\82ç
\82È
\82¢
\8fê
\8d\87\82ª
\82 \82é
\r
52 metrics.gmBlackBoxX = 0;
\r
53 metrics.gmBlackBoxY = 0;
\r
56 // GetGlyphOutline
\82Ì
\95Ô
\82·
\83o
\83b
\83t
\83@
\83T
\83C
\83Y
\82Í
\90M
\97p
\82µ
\82Ä
\82Í
\82¢
\82¯
\82È
\82¢
\82ç
\82µ
\82¢
\r
57 //
\82ä
\82¦
\82É
\83\81\83g
\83\8a\83N
\83X
\82©
\82ç
\8cv
\8eZ
\82µ
\82½
\92l
\82Æ
\94ä
\8ar
\82µ
\82Ä
\91å
\82«
\82¢
\82Ù
\82¤
\82ð
\8dÌ
\97p
\r
58 bufferSize = static_cast<size_t>( getHeight() * getPitch() );
\r
59 if ( bufferSize < bufferRequest ) bufferSize = bufferRequest;
\r
61 buffer = new unsigned char[bufferSize];
\r
62 GetGlyphOutline( cm.getDC(), index, mode, &metrics, bufferSize, buffer, &transform );
\r
64 switch( mode & ~GGO_GLYPH_INDEX )
\r
66 case GGO_GRAY4_BITMAP:
\r
67 for( size_t i = 0; i < bufferSize; ++i )
\r
69 const int alpha = (255 * buffer[i]) >> 4; // 0~16 -> 0~255
\r
70 buffer[i] = static_cast<unsigned char>( alpha );
\r
73 case GGO_GRAY8_BITMAP:
\r
74 for( size_t i = 0; i < bufferSize; ++i )
\r
76 const int alpha = (255 * buffer[i]) >> 6; // 0~64 -> 0~255
\r
77 buffer[i] = static_cast<unsigned char>( alpha );
\r
87 if ( NULL != buffer )
\r
93 void Glyph::setFont( const LOGFONTA *font )
\r
95 cm.selectFont( font );
\r
96 GetTextMetrics( cm.getDC(), &textMetrics );
\r
100 void Glyph::setTransformation( double xScale, double xAngle, double yAngle )
\r
102 const double deg2rad = 0.0174532925199432957692369; // pi / 180
\r
105 //
\82±
\82Ì
\95Ï
\8a·
\8ds
\97ñ
\82Í
\89¡
\83x
\83N
\83g
\83\8b\82É
\91Î
\82·
\82é
\82à
\82Ì
\82ç
\82µ
\82¢
\r
106 const double m11 = xScale * std::cos( yAngle );
\r
107 const double m21 = xScale * std::sin( xAngle );
\r
108 const double m12 = -std::sin( yAngle );
\r
109 const double m22 = std::cos( xAngle );
\r
110 doubleToFixed( m11, transform.eM11 );
\r
111 doubleToFixed( m12, transform.eM12 );
\r
112 doubleToFixed( m21, transform.eM21 );
\r
113 doubleToFixed( m22, transform.eM22 );
\r
116 void Glyph::doubleToFixed( double d, FIXED &f )
\r
118 int i = static_cast<int>( 0x10000 * d );
\r
119 f.fract = static_cast<WORD>( i & 0xFFFF );
\r
120 f.value = static_cast<WORD>( i >> 16 );
\r
123 UINT Glyph::detectMode( void )
\r
125 HMODULE hGdi = GetModuleHandleA( "gdi32.dll" );
\r
126 GetGlyphOutline = reinterpret_cast<GetGlyphOutlinePtr>( GetProcAddress( hGdi, "GetGlyphOutlineW" ) );
\r
127 // GetGlyphOutline = NULL;
\r
128 if ( GetGlyphOutline )
\r
130 return GGO_GRAY8_BITMAP;
\r
132 GetGlyphOutline = reinterpret_cast<GetGlyphOutlinePtr>( GetGlyphOutlineA );
\r
133 return GGO_GLYPH_INDEX | GGO_GRAY8_BITMAP;
\r
137 const Glyph *Glyph::get( unsigned int character )
\r
139 return cache.fetch( character );
\r
142 // ------------------------------------------------------------------------
\r
144 Glyph::Cache::Cache( size_t capacity )
\r
146 this->capacity = capacity;
\r
150 Glyph::Cache::~Cache( void )
\r
155 const Glyph *Glyph::Cache::fetch( unsigned int character )
\r
157 if ( glyphs.count( character ) <= 0 )
\r
159 add( character ); //
\91¶
\8dÝ
\82µ
\82È
\82¯
\82ê
\82Î
\92Ç
\89Á
\r
163 //
\90æ
\93ª
\82É
\88Ú
\93®
\r
164 order.remove( character ); //
\88ê
\92U
\8dí
\8f\9c\r
165 order.push_front( character ); //
\90æ
\93ª
\82É
\8dÄ
\91}
\93ü
\r
167 return glyphs[character];
\r
170 void Glyph::Cache::add( unsigned int character )
\r
172 remove( character ); //
\94O
\82Ì
\82½
\82ß
\8aù
\91¶
\83f
\81[
\83^
\82ð
\8dí
\8f\9c\r
173 reduce(); //
\92Ç
\89Á
\82·
\82é
\83O
\83\8a\83t
\82ð
\8fÁ
\82³
\82È
\82¢
\82½
\82ß
\82É
\90æ
\82É
\8eÀ
\8ds
\r
174 const Glyph *g = new Glyph( character );
\r
175 glyphs[character] = g;
\r
176 allocated += g->getBufferSize();
\r
177 order.push_front( character );
\r
180 void Glyph::Cache::remove( unsigned int character )
\r
182 if ( glyphs.count( character ) > 0 ) // character
\82ª
\91¶
\8dÝ
\82·
\82é
\82©
\r
184 const Glyph *g = glyphs[character];
\r
185 allocated -= g->getBufferSize();
\r
187 glyphs.erase( character );
\r
188 order.remove( character );
\r
192 void Glyph::Cache::reduce()
\r
194 while( allocated > capacity )
\r
196 const unsigned int &character = order.back(); //
\8dÅ
\8cã
\82Ìfetch
\82©
\82ç
\88ê
\94Ô
\8e\9e\8aÔ
\82ª
\82½
\82Á
\82½
\95¶
\8e\9a\r
197 const Glyph *g = glyphs[character];
\r
198 allocated -= g->getBufferSize();
\r
200 glyphs.erase( character );
\r
205 void Glyph::Cache::flush( void )
\r
207 std::map<unsigned int, const Glyph *>::iterator it;
\r
208 for( it = glyphs.begin(); it != glyphs.end(); ++it )
\r
210 delete (*it).second;
\r
218 Glyph::GetGlyphOutlinePtr Glyph::GetGlyphOutline = NULL;
\r
219 const UINT Glyph::mode = Glyph::detectMode();
\r
220 CharacterMap Glyph::cm;
\r
221 TEXTMETRICA Glyph::textMetrics;
\r
222 Glyph::Cache Glyph::cache( 1024 * 256 );
\r
223 MAT2 Glyph::transform = {{1,0}, {0,0}, {0,0}, {0,1}};
\r