OSDN Git Service

fix CMakeList.txt for windows
[moflib/moflib.git] / moflib-1.0 / moflib / moflib / mof / Font.cpp
1 #include "mof/Font.hpp"
2 #include <list>
3 #include <windows.h>
4 #include "mof/ConsoleIO.hpp"
5 #include <vector>
6 #include "mof/utilities.hpp"
7
8 #pragma comment(lib, "gdi32.lib")
9
10 const TCHAR* mof::Font::MS_GOTHIC = _T("\82l\82\83S\83V\83b\83N");
11 const TCHAR* mof::Font::MS_P_GOTHIC = _T("\82l\82\82o\83S\83V\83b\83N");
12
13
14 namespace
15 {
16     struct FontManager 
17     {
18         std::vector<mof::tstring> additionalFontResources;
19         
20         ~FontManager()
21         {
22             foreach( mof::tstring& filename , additionalFontResources )
23             {
24                 RemoveFontResource( filename.c_str() );
25             }
26         }
27     } g_fontManager;
28 }
29
30 struct GlyphData{
31     int iOfs_x , iOfs_y , iBmp_w , iBmp_h , level , width;
32     BYTE* pBmpBuffer;
33     bool valid;
34
35    GlyphData(GLYPHMETRICS& GM , TEXTMETRIC& TM , int _level , int bufSize){
36         iOfs_x = GM.gmptGlyphOrigin.x;
37         iOfs_y = TM.tmAscent - GM.gmptGlyphOrigin.y;
38         iBmp_w = GM.gmBlackBoxX + (4-(GM.gmBlackBoxX%4))%4;
39         iBmp_h = GM.gmBlackBoxY;
40         level = _level;
41         width =  GM.gmCellIncX;
42         pBmpBuffer = new BYTE[bufSize];
43         valid = true;
44    }
45
46    ~GlyphData(){
47         delete[] pBmpBuffer;
48    }
49 };
50
51 struct mof::Font::Impl{
52     HFONT hFont;
53     size_t fontSize;
54         mof::tstring font_name_;
55         mof::font_context context_;
56
57     Impl(const TCHAR* font_name, size_t fontSize_, const mof::font_context& context)
58         : font_name_(font_name), hFont(NULL) ,fontSize(fontSize_), context_(context)
59     {
60     }
61
62     ~Impl(){
63         DeleteObject(hFont);
64     }
65
66 };
67
68 mof::Font::Font(const TCHAR* fontName , size_t size)
69 : m_pImpl(new Impl(fontName, size, mof::font_context()))
70 {
71     LOGFONT lf = {m_pImpl->fontSize , 0, 0, 0, FW_REGULAR, 0, 0, 0, SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS,
72         CLIP_DEFAULT_PRECIS , DEFAULT_QUALITY, DEFAULT_PITCH, "" };
73     //LOGFONT lf = {m_pImpl->fontSize , 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, OUT_TT_ONLY_PRECIS,
74     //    CLIP_DEFAULT_PRECIS , PROOF_QUALITY, FIXED_PITCH | FF_MODERN , "" };
75     strcpy_s(lf.lfFaceName , fontName );
76
77     if(!(m_pImpl->hFont = CreateFontIndirect(&lf))){
78        throw std::runtime_error("Failed --- CreateFontIndirect");
79     }
80 }
81
82
83 mof::Font::Font(const TCHAR* fontName , size_t size, const mof::font_context& context)
84 : m_pImpl(new Impl(fontName, size, context))
85 {
86     LOGFONT lf = {m_pImpl->fontSize , 0, 0, 0, FW_REGULAR, 0, 0, 0, SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS,
87         CLIP_DEFAULT_PRECIS , DEFAULT_QUALITY, DEFAULT_PITCH, "" };
88     //LOGFONT lf = {m_pImpl->fontSize , 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, OUT_TT_ONLY_PRECIS,
89     //    CLIP_DEFAULT_PRECIS , PROOF_QUALITY, FIXED_PITCH | FF_MODERN , "" };
90     strcpy_s(lf.lfFaceName , fontName );
91
92     if(!(m_pImpl->hFont = CreateFontIndirect(&lf))){
93        throw std::runtime_error("Failed --- CreateFontIndirect");
94     }
95 }
96
97 mof::Font::~Font(){
98     
99 }
100
101 mof::tstring mof::Font::name() const { return m_pImpl->font_name_; }
102 size_t mof::Font::size() const { return m_pImpl->fontSize; }
103 mof::font_context mof::Font::context() const { return m_pImpl->context_; }
104
105 mof::PixelMap* mof::Font::createText(const mof::tstring& text) const{
106
107     // \83f\83o\83C\83X\83R\83\93\83e\83L\83X\83g\8eæ\93¾
108     // \83f\83o\83C\83X\82É\83t\83H\83\93\83g\82ð\8e\9d\82½\82¹\82È\82¢\82ÆGetGlyphOutline\8aÖ\90\94\82Í\83G\83\89\81[\82Æ\82È\82é
109     HDC hdc = GetDC(NULL);
110     HFONT oldFont = static_cast<HFONT>(SelectObject(hdc , m_pImpl->hFont));
111     TEXTMETRIC TM;
112     GetTextMetrics( hdc, &TM );
113
114     int sumWidth = 0;
115     int maxHeight = 0;
116     typedef std::list<GlyphData*>::iterator GDITR;
117     std::list<GlyphData*> glyphDataList;
118     for(int i = 0 ; text.c_str()[i] ; ){
119
120
121         // \95\8e\9a\83R\81[\83h\8eæ\93¾
122         UINT code = 0;
123         #if _UNICODE
124             // unicode\82Ì\8fê\8d\87\81A\95\8e\9a\83R\81[\83h\82Í\92P\8f\83\82É\83\8f\83C\83h\95\8e\9a\82ÌUINT\95Ï\8a·\82Å\82·
125             code = (UINT)str[i++];
126         #else
127             // \83}\83\8b\83`\83o\83C\83g\95\8e\9a\82Ì\8fê\8d\87\81A
128             // 1\83o\83C\83g\95\8e\9a\82Ì\83R\81[\83h\82Í1\83o\83C\83g\96Ú\82ÌUINT\95Ï\8a·\81A
129             // 2\83o\83C\83g\95\8e\9a\82Ì\83R\81[\83h\82Í[\90æ\93±\83R\81[\83h]*256 + [\95\8e\9a\83R\81[\83h]\82Å\82·
130             if(IsDBCSLeadByte(text[i])){
131                 code = (text[i] << 8) | (text[i+1] & 0xff); // \95\8e\9a
132                 code &= 0x0000ffff;
133                 i += 2;
134             }
135             else{
136                 code = text[i++];
137             }
138         #endif
139
140         unsigned int spaceCode = (_T(" ")[0]);
141         unsigned int wSpaceCode = (_T("\81@")[0] << 8) | (_T("\81@")[1] & 0xff);
142         wSpaceCode &= 0x0000ffff;
143
144
145         // \83t\83H\83\93\83g\83r\83b\83g\83}\83b\83v\8eæ\93¾
146         GLYPHMETRICS GM;
147         CONST MAT2 Mat = {{0,1},{0,0},{0,0},{0,1}};
148         DWORD size = GetGlyphOutline(hdc, code , GGO_GRAY8_BITMAP, &GM, 0, NULL, &Mat);
149         GlyphData* pGD = new GlyphData(GM , TM , 65 , size);
150         GetGlyphOutline(hdc, code, GGO_GRAY8_BITMAP, &GM, size, pGD->pBmpBuffer , &Mat);
151
152         if(code == spaceCode || code == wSpaceCode){
153             //\8bó\94\92\82Í\89½\8cÌ\82©\82¤\82Ü\82­\8f\91\82«\8d\9e\82ß\82È\82¢\82±\82Æ\82Ö\82Ì\91Î\8f\88
154             pGD->valid = false;
155         }
156         glyphDataList.push_back(pGD);
157         sumWidth += pGD->width;//\91S\91Ì\82Ì\95\9d
158         maxHeight = max(maxHeight , TM.tmHeight);
159     }
160
161     
162     // \83f\83o\83C\83X\83R\83\93\83e\83L\83X\83g\82Æ\83t\83H\83\93\83g\83n\83\93\83h\83\8b\82Ì\8aJ\95ú
163     SelectObject(hdc, oldFont);
164     ReleaseDC(NULL, hdc);
165
166     typedef mof::PixelMap::size_type size_type;
167     boost::array<size_type , 2> sizes = {{ sumWidth , maxHeight }};
168     mof::PixelMap* pPixelMap = new mof::PixelMap(sizes);
169
170     // \83t\83H\83\93\83g\8fî\95ñ\82Ì\8f\91\82«\8d\9e\82Ý
171     // iOfs_x, iOfs_y : \8f\91\82«\8fo\82µ\88Ê\92u(\8d\8fã)
172     // iBmp_w, iBmp_h : \83t\83H\83\93\83g\83r\83b\83g\83}\83b\83v\82Ì\95\9d\8d\82
173     // Level : \83¿\92l\82Ì\92i\8aK (GGO_GRAY4_BITMAP\82È\82Ì\82Å17\92i\8aK)
174
175     DWORD Alpha, Color;
176     int hoseiX = 0;
177     for(int y = 0 ; y < maxHeight ; y++){
178         for(int x = 0 ; x < sumWidth ; x++){
179             (*pPixelMap)[x][y] = 0;
180         }
181     }
182
183         mof::Color4f color = context().font_color;
184         color.alpha = 0;
185         mof::Color code = color.toColorCode();
186     for(GDITR itr = glyphDataList.begin() ; itr != glyphDataList.end() ; ++itr){
187        for(int y = (*itr)->iOfs_y;  y < (*itr)->iOfs_y + (*itr)->iBmp_h;  y++){
188             if(!(*itr)->valid)break;//\8bó\94\92\95\8e\9a\82È\82ç\8f\91\82«\8d\9e\82Ý\82ð\96³\8e\8b\82·\82é
189             for(int x = (*itr)->iOfs_x + hoseiX ; x < (*itr)->iOfs_x + (*itr)->iBmp_w + hoseiX && x < sumWidth ;  x++){
190                 Alpha = (255 * (*itr)->pBmpBuffer[x - ((*itr)->iOfs_x + hoseiX) + (*itr)->iBmp_w * ( y - (*itr)->iOfs_y ) ] ) / ((*itr)->level-1);
191                 //Color = 0x00ffffff | (Alpha<<24);
192                                 Color = code | (Alpha<<24);
193                 
194                 (*pPixelMap)[x][y] = Color;
195                 
196             }
197        }
198        hoseiX += (*itr)->width;
199        delete *itr;
200    }
201
202     return pPixelMap;
203 }
204
205
206 bool mof::Font::addFontResource(const mof::tstring& filename ){
207     g_fontManager.additionalFontResources.push_back(filename);
208     return AddFontResource( filename.c_str() ) ? true : false ;
209 }