??xml version="1.0" encoding="utf-8" standalone="yes"?>国产成人久久精品激情,欧洲性大片xxxxx久久久,99精品国产综合久久久久五月天 http://www.shnenglu.com/winmain/category/12308.htmlProgramming is so coolzh-cnSat, 06 Mar 2010 14:22:12 GMTSat, 06 Mar 2010 14:22:12 GMT60[转]GUI库比较一N?/title><link>http://www.shnenglu.com/winmain/archive/2010/03/02/108735.html</link><dc:creator>Code Knight</dc:creator><author>Code Knight</author><pubDate>Tue, 02 Mar 2010 11:57:00 GMT</pubDate><guid>http://www.shnenglu.com/winmain/archive/2010/03/02/108735.html</guid><wfw:comment>http://www.shnenglu.com/winmain/comments/108735.html</wfw:comment><comments>http://www.shnenglu.com/winmain/archive/2010/03/02/108735.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/winmain/comments/commentRss/108735.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/winmain/services/trackbacks/108735.html</trackback:ping><description><![CDATA[原帖Q?a href="http://www.shnenglu.com/lingjingqiu/archive/2009/01/06/71363.html">http://www.shnenglu.com/lingjingqiu/archive/2009/01/06/71363.html</a><br> <table style="WIDTH: 1029px; HEIGHT: 1706px" border=1> <tbody> <tr> <td style="FONT-SIZE: 10pt">界面库名U?br></td> <td style="VERTICAL-ALIGN: top">接口设计<br></td> <td style="VERTICAL-ALIGN: top">界面~辑?br></td> <td style="VERTICAL-ALIGN: top">高布局功能<br></td> <td style="VERTICAL-ALIGN: top">q面l制<br></td> <td style="VERTICAL-ALIGN: top">q_兼容?br></td> <td style="VERTICAL-ALIGN: top">语言支持<br></td> <td style="VERTICAL-ALIGN: top">IDE兼容?br></td> <td style="VERTICAL-ALIGN: top">视图-模型分离机制<br></td> <td style="VERTICAL-ALIGN: top">q行?br></td> <td style="VERTICAL-ALIGN: top">其它<br></td> </tr> <tr> <td>Windows Forms<br></td> <td style="VERTICAL-ALIGN: top">接口优秀。C++下用CLI扩展Q其它语a为原生支持?br></td> <td style="VERTICAL-ALIGN: top">界面~辑器完_(d)包括布局、属性、消息关联的完整讄。不可预览?br></td> <td style="VERTICAL-ALIGN: top">Table LayoutQSplitter LayoutQFlow Layout{,Anchor和Dock机制。多分L率界面下表现良好?br></td> <td style="VERTICAL-ALIGN: top">GDI+Q面向对象的2Dl制接口Q用简ѝ?br></td> <td style="VERTICAL-ALIGN: top">需?Netq_支持。WIndows或LinuxQMonoQ非官方支持Q,支持Windows CE<br></td> <td style="VERTICAL-ALIGN: top">C++/CLI, 支持.net的语a?br></td> <td style="VERTICAL-ALIGN: top">仅VS?br></td> <td style="VERTICAL-ALIGN: top">布局和视图方案徏立在代码中。部分组件支持Model-View架构?br></td> <td style="VERTICAL-ALIGN: top">需要部|对应的.net<br></td> <td style="VERTICAL-ALIGN: top">商业协议<br></td> </tr> <tr> <td style="VERTICAL-ALIGN: top">MFC<br></td> <td style="VERTICAL-ALIGN: top">Z宏和虚函敎ͼ使用Ҏ(gu)格式注释Q用自定义的RTTIpȝ。类接口设计优良。通过回调函数和虚l承重蝲调用客户代码?br></td> <td style="VERTICAL-ALIGN: top">Z资源~辑器,仅能对空间基本布局和少量属性进行调整。不可预览?br></td> <td style="VERTICAL-ALIGN: top">~Z高布局功能Q多分L率需要是手工或程序中调整?br></td> <td style="VERTICAL-ALIGN: top">GDI?qing)GDI装Q可选GDI+<br></td> <td style="VERTICAL-ALIGN: top">WindowsQW(xu)indows CE<br></td> <td style="VERTICAL-ALIGN: top">C++ OnlyQ?br>支持COM时可以实现BinaryU别复用?br></td> <td style="VERTICAL-ALIGN: top">仅Visual Studio<br></td> <td style="VERTICAL-ALIGN: top">使用资源保存控g的基本控件布局Q提供Doc-View机制和控件数据交换支持视囑ֈR?br></td> <td style="VERTICAL-ALIGN: top">需要部|MFCq行时库?br></td> <td style="VERTICAL-ALIGN: top">商业协议<br></td> </tr> <tr> <td style="VERTICAL-ALIGN: top">WTL<br></td> <td style="VERTICAL-ALIGN: top">Z模板和虚函数。类接口cM于MFC。需要用多重(h)ѝ通过模板特化和回调函C客户代码交互?br></td> <td style="VERTICAL-ALIGN: top">同MFC<br></td> <td style="VERTICAL-ALIGN: top">同MFC<br></td> <td style="VERTICAL-ALIGN: top">同MFC<br></td> <td style="VERTICAL-ALIGN: top">同MFC<br></td> <td style="VERTICAL-ALIGN: top">同MFCQ对COM的支持比MFC完善很多?br></td> <td style="VERTICAL-ALIGN: top">Visual StudioQW(xu)indows下支持标准的C++~译器?br></td> <td style="VERTICAL-ALIGN: top">使用资源文g保存I间布局?br></td> <td style="VERTICAL-ALIGN: top">?br></td> <td style="VERTICAL-ALIGN: top">自由协议<br></td> </tr> <tr> <td style="VERTICAL-ALIGN: top">wxWidget<br></td> <td style="VERTICAL-ALIGN: top">宏,自定义RTTI。用回调函C用户代码交互?br></td> <td style="VERTICAL-ALIGN: top">无官方界面编辑器。可使用W三方界面编辑器。部分编辑器h完整的所见即所得功能,且具有预览能力?br></td> <td style="VERTICAL-ALIGN: top">使用Sizer实现多分辨率的布局。功能偏弱?br></td> <td style="VERTICAL-ALIGN: top">wxDC{?br></td> <td style="VERTICAL-ALIGN: top">WindowsQLinuxQUnixQMacOS{?br></td> <td style="VERTICAL-ALIGN: top">C++, .NET, Python,<br>Lua,<br>Ruby{?br></td> <td style="VERTICAL-ALIGN: top">良好的编译器兼容性,~ZIDEl承?br></td> <td style="VERTICAL-ALIGN: top">可以界面属性生成到代码中,也可以用XML格式保存?br></td> <td style="VERTICAL-ALIGN: top">wx的动态链接库或静(rn)态链接?br></td> <td style="VERTICAL-ALIGN: top">自由协议<br></td> </tr> <tr> <td style="VERTICAL-ALIGN: top">Qt<br></td> <td style="VERTICAL-ALIGN: top">使用宏和自定义的RTTI。用Singal-Slot机制实现用户代码交互。可通过l承实现扩展?br></td> <td style="VERTICAL-ALIGN: top">Qt DesignerQ具备完整的所见即所得编辑功能。可预览界面?br></td> <td style="VERTICAL-ALIGN: top">具备完整的布局功能。多分L?多^C表现良好?br></td> <td style="VERTICAL-ALIGN: top">QCanvas{?br></td> <td style="VERTICAL-ALIGN: top">WindowsQLinuxQUnixQMacOS{?br></td> <td style="VERTICAL-ALIGN: top">C++QPython{?br></td> <td style="VERTICAL-ALIGN: top">可集成到Eclipse和VS<br></td> <td style="VERTICAL-ALIGN: top">使用资源文g保存界面信息。部分组件具备Model-View-Delegate架构<br></td> <td style="VERTICAL-ALIGN: top">qt的动态链接库?br></td> <td style="VERTICAL-ALIGN: top">开源协?商业协议<br></td> </tr> <tr> <td style="VERTICAL-ALIGN: top">GTK+<br></td> <td style="VERTICAL-ALIGN: top">使用signal-slot机制完成用户代码交互?br></td> <td style="VERTICAL-ALIGN: top">GLADEQ具备所见即所得的界面~辑功能<br></td> <td style="VERTICAL-ALIGN: top">Layout ContainersQ具备较完整的布局能力?br></td> <td style="VERTICAL-ALIGN: top">GTK Graphics Context<br></td> <td style="VERTICAL-ALIGN: top">WindowsQLinuxQUnixQMacOS{?/td> <td style="VERTICAL-ALIGN: top">CQC++QPythonQ?NET{?br></td> <td style="VERTICAL-ALIGN: top">Q暂时未知)(j)<br></td> <td style="VERTICAL-ALIGN: top">使用代码完成界面讄。部分组件具备Model-View架构?br></td> <td style="VERTICAL-ALIGN: top">GTK Runtime<br></td> <td style="VERTICAL-ALIGN: top">开源协?br></td> </tr> </tbody> </table> <p><br># re: C++下Windows Forms + MFC + WTL + wxWidgets + Qt + GTK+ 非官方综合比?2009-01-06 19:05 qtopia <br>Nokia 最q推?Qt CreatorQ是较好的IDE环境  回复  更多评论 <br>   </p> <p><br># re: C++下Windows Forms + MFC + WTL + wxWidgets + Qt + GTK+ 非官方综合比?2009-01-06 19:05 t <br>博主q可以增加一?#8220;国际化支?#8221;  回复  更多评论 <br>   </p> <p><br># re: C++下Windows Forms + MFC + WTL + wxWidgets + Qt + GTK+ 非官方综合比较[未登录] 2009-01-08 12:48 kenlistian <br>我觉得wxwidget是不错的选择?nbsp; 回复  更多评论 <br>   </p> <p><br># re: C++下Windows Forms + MFC + WTL + wxWidgets + Qt + GTK+ 非官方综合比?2009-01-11 20:25 www <br>wxwidget做简单的q可? 做复杂的界面,嘿嘿,那就ȝ(ch)? win下还是MFC最?  回复  更多评论 <br>   </p> <p><br># re: C++下Windows Forms + MFC + WTL + wxWidgets + Qt + GTK+ 非官方综合比?2009-01-19 00:49 ArenAK <br>有没有哪一个是作者比较喜Ƣ用的呢Q及(qing)其原因?  回复  更多评论 <br>   </p> <p><br># re: C++下Windows Forms + MFC + WTL + wxWidgets + Qt + GTK+ 非官方综合比较[未登录] 2009-01-19 16:35 六水 <br>写的好~  回复  更多评论 <br>   </p> <p><br># re: C++下Windows Forms + MFC + WTL + wxWidgets + Qt + GTK+ 非官方综合比?2009-02-05 11:08 I明{ <br>@六水<br>我就知道你是友情赞助的。。?nbsp; 回复  更多评论 <br>   </p> <p><br># re: C++下Windows Forms + MFC + WTL + wxWidgets + Qt + GTK+ 非官方综合比较[未登录] 2009-02-11 22:35 六水 <br>q你也知道?  回复  更多评论 <br>   </p> <p><br># re: C++下Windows Forms + MFC + WTL + wxWidgets + Qt + GTK+ 非官方综合比?2009-02-25 10:19 aladdina <br>wxWidgets的代码质量不是很高,有一些比较初U的bug。我用过一D|间的wxWidgetsQ自己测试没问题Q但是用hM(x)发回一些crash report?/p> <p>另外QwxWidgets和Qt除了(jin)对于一些常见应用,比如H口、DC的封装之外,q提供了(jin)很多pȝ接口的封装,比如clipboard, thread, socket{?/p> <p>Qt有Qt Creator作ؓ(f)IDEQ工E项目文件可以跨q_Q另外,工程文g也可以用qmake转成q_无关的makefile。准备最q有I试QtQ个得商业代码质量还是要E微好一些?/p> <p>  回复  更多评论 <br>   </p> <p><br># re: C++下Windows Forms + MFC + WTL + wxWidgets + Qt + GTK+ 非官方综合比?2009-09-18 12:09 idol <br>gtk 哪有 signal-slot机制Q用的明明是 callbacks  回复  更多评论 </p> <img src ="http://www.shnenglu.com/winmain/aggbug/108735.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/winmain/" target="_blank">Code Knight</a> 2010-03-02 19:57 <a href="http://www.shnenglu.com/winmain/archive/2010/03/02/108735.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]游戏中的炚w字体和TrueType字体http://www.shnenglu.com/winmain/archive/2010/02/28/108626.htmlCode KnightCode KnightSun, 28 Feb 2010 12:19:00 GMThttp://www.shnenglu.com/winmain/archive/2010/02/28/108626.htmlhttp://www.shnenglu.com/winmain/comments/108626.htmlhttp://www.shnenglu.com/winmain/archive/2010/02/28/108626.html#Feedback0http://www.shnenglu.com/winmain/comments/commentRss/108626.htmlhttp://www.shnenglu.com/winmain/services/trackbacks/108626.html炚w字库
  包括现在Q有很多游戏都还是用的炚w字库。因为操作v来比较方便,加上q方面的l验已经U篏?jin)好几年了(jin)。通常如果只是一U字体就可以满需要的话,它会(x)是一个比较好、快的解军_法。但是它?个缺?
1. 如果攑֤昄Q不做处理的话,昄出来的汉字,是很隄的?br>2. 像是UCDOS所提供的点阵字库,只有24炚w的有几种字体Q如Q宋(hu)体、黑体、揩?#8230;Q?6炚w的好象就只有?hu)体一U?br>3. 炚w字库Q通常是有版权的,其是第三方制作的汉字库Q如Q方正)(j)?br>  在这L(fng)情况下,当我们写好这L(fng)一个显C函敎ͼq是解决了(jin)如:(x)攑֤、快速显C等问题的话Q可供选择的字体还是太q于局限了(jin)。所以,在字体的要求比较强的情况下,炚w字库q不是一个好的解x(chng)法,他不够灵zR尽我们对于它的操作是如此得熟l,可以写出优美的代码来展示我们的编E技巧?/font>


TTF
  TTF是True Type Font的简U。在Windows\Fonts目录下面Q我们可以看到许多后~为ttf的文Ӟ它就是接下来我们接下来所要谈到的?br>  TTF是一U矢量字库。我们经常可以听到矢量这个词Q像是FLASH中的矢量囑ŞQ在100*100分L率下制作的flashQ就它攑֤为全屏,昄出的画面也不?x)出现马赛克。所谓矢量,其实说白?jin)就是用点和U来描述囑ŞQ这P在图形需要放大的时候,只要把所有这个图形的点和U放大相应的倍数可以了(jin)。而且Q在|站上有很多的TTF字库可以下蝲Q或者你可以M一些专门的字库光盘。然后在你发行你_ֿ(j)制作的游戏时Q可以顺便捎上这些后~?ttf 的文件就行了(jin)。包括Quakeq样的惊世之作,也都是用的TTF字库?br>  q样Q我们就可以解决炚w汉字的一些问题。通过TTFQ我们在字体的质量和字库的数量上获得?jin)暂时性的胜利?/font>


字库的读取和昄
  先前谈到炚w字库Q只需要很单的一些操作,可以显C出惌的汉字。下面我l出一个读取hzk16的函敎ͼ它需要一个Surface以供昄用:(x)
  #include <io.h>
  #include <stdio.h>
  #include <conio.h>
  
  // d16x16
  void DispHZ16(int x, int y, BYTE *Str, LPDIRECTDRAWSURFACE surf)
  {
   const int Mask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
   FILE *HzkFp;
   WORD i, j, k=0, m;
   WORD HzNum;
   WORD QuHao;
   WORD WeiHao;
   long offset;
   BYTE dotBuffer[32];
  
   HzkFp = fopen("HZK16", "rb");
  
   HzNum = strlen((const char *)Str)/2;
  
   DDSURFACEDESC ddsd;
   LPWORD lpSurface;
   HRESULT ddrval;
  
   ddsd.dwSize = sizeof(ddsd);
  
   while((ddrval=surf->Lock(NULL, &ddsd, 0, NULL))==DDERR_WASSTILLDRAWING);
   if(ddrval == DD_OK)
   lpSurface = (LPWORD)ddsd.lpSurface;
  
   for(i = 0; i<HzNum; i++)
   {
   QuHao = Str[i*2]-160;
   WeiHao = Str[i*2+1]-160;
  
   offset = ((QuHao - 1) * 94 + (WeiHao-1))*32;
  
   fseek(HzkFp, offset, SEEK_SET);
   fread(dotBuffer, 32, 1, HzkFp);
  
   for(j=0;j<16;j++)
   for(k=0;k<2;k++)
   for(m=0;m<8;m++)
   if(dotBuffer[j*2+k] & Mask[m])
   {
   lpSurface[ddsd.lPitch*(y+j+1) + x+k*8+m] = 0x000000;
   }
   x+=16;
   }
  
   surf->Unlock(NULL);
  
   fclose(HzkFp);
  }
  其实原理很简单:(x)
1. 打开字库
2. 计算字符串长度(q个函数只支持中文)(j)Qƈ且Lock Surface
3. 依次计算出每个汉字所对应的区码和位码Q汉字的W?个字节是区码Q第2个字节就是位码)(j)Q然后通过公式计算?gu)个汉字在字库中的偏移量?x)
offset = ((QuHao - 1) * 94 + (WeiHao-1))*32;
4. d一?2个字节的炚w
5. l制到Surface?br>  以上只是16Q?6炚w字库的显C方法,24Q?4的读取方法与之类|大家可以参照相关资料来书写出自己的代码?br>  
  如何昄TTF字库呢,有很多种手段Q下面我按从单到复杂的的序依次介绍:
1. 使用Windows APIQ也是大家所熟?zhn)的TextOut。通过它,q需要一个HDCQ设备句柄)(j)Q我们就可以随意地在屏幕M地方昄出文字了(jin)?br>2. 在http://www.freetype.orgQ有一个FreeType的免费库Q而且是OpenSource的。它目前?个版本:(x)1.0?2.0。其区别在于Q?.0只能dTTF格式的,?.0支持更多的文件格式,在用它之前误l阅L要遵循的LicenceQ以下是摘自 FreeType2.0对字库的支持列表Q?br>o TrueType fonts (and collections)
o Type 1 fonts
o CID-keyed Type 1 fonts
o CFF fonts
o OpenType fonts (both TrueType and CFF variants)
o SFNT-based bitmap fonts
o X11 PCF fonts
o Windows FNT fonts
3. 自己研究TTF的格式,然后自己来操作?br>?br>....... ╮╮
    \?倒!
    ?br>虽然我们惌把每一件事情都做好Q但是也不是每一件事情都要亲历亲为。如果你非要q样Q也行^____^Q但是过不了(jin)多久Q你׃(x)陷入泥沼Q到时候你?x)发现自q热情正在慢慢被磨灭,什么叫做抓狂,怿你很快就?x)知道^_^?br>
在有多种选择可以取舍的情况下Q我们需要考虑一下,Ҏ(gu)一下各U解x(chng)法的优劣?br>
  在DirectDraw时代Q我们都不自觉地喜欢上了(jin)GetDCQ因?#8230;…多方便啊。可是现在已l到?jin)DirectX8.1时代?jin)(我要使劲地摇那些q沉醉于DirectX7中,为如何在使用alpha时提升那可怜的1?个fps的朋友们Q醒醒,该v床了(jin)Q)(j)QHDC已经被M$列ؓ(f)用品。怎么办呢Q是的,你可能已l想C(jin)Q我们还?sh)直保存着H口的hWnd呢,可以通过它来得到hdcQ从而调用那些需要hdc的APIQ可是,q样做是更ؓ(f)愚蠢的,q样对你是没有一点好处的Q不信,你就试试吧。有一句话Q请牢记Q要想你的游戏有更快的速度的话Q请不要再去HDC?jin)?br>  我们非常清楚hdc是一个超慢的解决办法Q它无法在我们的高速游戏中?0分及(qing)根{下面来看看FreeTypeQ它更像是一个Service。它的解x(chng)法是Q先通过一pd的初始化和设|,告诉FreeType字体的名字和大小{,然后它会(x)动态地甌一个GraphicQ再把我们要昄的字dq个 Graphic上,你还可以把它保存?sh)tga格式。不q我们最l所惌的不是这个,所以可能我们还需要从q个Graphic上逐点d或者用 CopyRectQ然后再d我们的画面上。其实它已经是很方便的了(jin)Q可是需要你d?fn)如何配|和使用它,q是很花旉的一件事情,而且它最大的优点是可以跨q_Q我们需要它吗?如果有一个更为简单的办法Q像是如果Textout不是那么慢的话,好?#8230;…
  在这里,Z谈一下另2个字体显C类QID3DXFont和CD3DFONT。可能早有Z(x)说怎么在上面的列表中没有它们?原因我会(x)在下面慢慢地说明Q?br>  ID3DXFontQ它存在于D3DX库中Q一个现成的字体c,不过对于它的处理Ҏ(gu)……我实在不敢恭l_(d)引用一位大师所说的话来表达我的看法? 在内部实CQ?ID3DXFont::DrawText()函数实做了(jin)我上面讨论的工作Q先建立一张GDI兼容的位图,把文本绘制到位图上,而后把位图拷贝到U理贴图上去Q最后把U理渲染到屏q上。这样你p齐了(jin)所有的龟速的原始GDI函数Q还包括?jin)一大堆的额外开销 ?最l,q个函数比原来GDI的DrawTextEx()函数要慢上超q六?#8230;…
  CD3DFONTQ是由M$在D3D的框架代码中提供。不q它只能昄英文Q有很多朋友通过自己定制和修改这个类Q来实现自己的中文显C。不q效果都不是很好。其实原理,跟ID3DXFont的方法差不多Q不q处理方法要聪明?jin)一炏V?/font>


分析与思?br>  那么我们应该怎么办呢Q通常我们?x)惻I如果可以像处理英文那P把所有的汉字都保存在一张位NQ该有多好。这P昄的速度׃是问题(sh)(jin)Q直接可以CopyRect上去。可是,q样可能吗?首先Q必L一U字体都要生成这L(fng)一个巨型位图。而且据说在GB2312中,一共有6000多个汉字Q就是?6*16Qoh my godQ这个位图该有多大啊Q据说会(x)?.5M^__^Q!Q!而且在DirectX8.1中,对于TextureQ显C的最单位,好象是原来 DirectSurface的概念一栗说q多遍?jin),不要再用DirectX8以前的东西了(jin)。不要试着d忆那些美好的q去Q我很明白,要你一下子攑ּ原来多年所获得的成,是一件很痛苦的事情,但是包袱太重Q是?x)?jing)响进步的。就像是我们的国?#8230;…扯远?jin)?j)Q不同的昑֍Q支持的最大容量也是不同的。比方说早期的VoodooQ只支持256*256大小的Texture。而在我的昑֍QGeforce2 MX 200Q上试Q支持最?048*2048大小的Texture。对于这L(fng)g不确定性,我们只能取其最|也就?56*256?br>  汉字虽然很多Q但是常用的汉字Q其实也只有那么几百个。像q样的字Q鬯、鞴Q你一辈子?x)看到多次呢?如果可以做一个类gCache的东西,保存着常用的那些个汉字Q在需要显C的的时候,先在Cache中查找,如果有的话,马上画上去Q如果没有,׃字库中提取到Cache中。这L(fng)话,在?Texture来保存汉字的位图信息的同Ӟ对于每个汉字Q我们还要定义一个结构,然后用一个东西把它串hQ综合它?个,也就实现?jin)我们所要的 Cache?jin)。刚开始,我所定义的结构是q样的:(x)
  struct Char{
   char hz[3]; // 保存汉字
   int frequency;// 使用频率
   RECT rect; // q个字对应位囄区域
   Bool isUsing; // 是否使用
  }
  对于汉字和英文,我在q里大概地讲一下原理:(x)汉字是由2个字节保存,而英文只需?个。而判断一个字是否是汉字,只需判断W?个byte是否>128Q在原来的GB2312中,汉字?个字节都?gt;128的。而新的GBK字库Q汉字的W?个字节不一?gt;128Q我惌是扩大了(jin)字库定w的原因。我的意思是_(d)如果l一个字W串你,随机l其中一个位|,然后我问你这个位|是什么?你的回答只能是:(x)1 英文 2 汉字的首字节 3 汉字的尾字节。而这个问题的解法Qؓ(f)?jin)稳妥v见,你必M字符串的开始判断vQ。也是说在char[3]中,如果保存的是汉字Q则char[0]保存汉字W?个字节,char[1]保存汉字W?个字节,W?个存?#8217;\0’Q如果是英文的话Q则只用到char[0]Q其它的全部?#8217;\0’?br>  接下来,对于使用char[3]来保存汉字,是否真的很合适呢Q因为如果把它当作一个字W串来看的话Q在查找时就需要?strcmp 来比较字W串?jin),q样一定是?x)?jing)响速度的。如果不把它看作字符Ԍ字符串的最后一个字节需要以’\0’l尾Q,只用char[2]的话Q我们可以只是简单地调用宏MAKEWORDQ把2个byte压成1个WORD。当把文字作Z个WORD来看的时候,q样查找比较时可以用WORD内徏?=操作Q这栯比调用strcmp函数要快得多?br>  int frequency用来标志每个WORD的用频率。设惻I如果一个字已经存在于Cache中,以后每对它调用一ơ,pfrequency++。这样做q有一个用意是Q是否可以在一个合适的时候,以frequency为参照来对这整个Cache排个序,把常用的字放在前面。那么在昄Ӟ可以先在 Cache中查找所要显C的字是否已l存在于Cache中,如果有则直接昄Q没有的话才需要采取某U手D将字加入到Cache中。一些常用的字(像:(x)我、的、着、了(jin)、过……Q,使得昄的速度会(x)大大提高?br>  其实上面说了(jin)半天的CacheQ它具体是什么呢Q其实就是指的最绘制单位,在DirectX7里是SurfaceQ而在DirectX8中就?Texture。用它来存放显C的汉字,q样Q就不用每次都从字库中读取或是调用如TextOutq类GDI慢的函C(jin)。因为每ơ在l制一个文字之前,都会(x)先在q个Cache中找Q有的话q接画上去Q没有才?x)调用TextOut操作。而这样做的原因,我们先设想一下:(x)游戏一般会(x)控制?0fps或是60fps的速度不停地刷斎ͼ如果在GameLoop中有M的代码是龟速的话Q这样就?x)导致fps的最大数的降低,也就意味着在保?0fps?60fps的同Ӟ能绘制到屏幕上的物体的数量减了(jin)。这是我们Z么要使用Texture来作为Cache的实现的原因。再一个,文字在屏q上昄时一般会(x)保持一D|_(d)q个旉可能?U?3U,我们的游戏也׃(x)相应地更?0fps?80fpsQ这是因Zh们需要阅d们。或者是一些如标题q样的文字,它们L不会(x)更新的,或是更新得很慢。我们完全可以在W一旉Q比方说我们的画面有60fpsQ在W?个fpsӞ我们得知要显C文?#8221;?#8221;Q然后先在Cache中找Q结果很p:(x)没有扑ֈQ这旉上用TextOut写到Texture上(现在q是属于W?个fps的时间范围内Q,而接下来?9?fpsQ甚x(chng)多)(j)Q都不用再调TextOut?jin),而是直接从我们的CacheQTexture上Copy到屏q上Q速度得到?jin)保障。谈到GDI的函敎ͼZ(jin)实现讑֤无关性,它们的速度都很慢。其实它们也不像说得那么慢,如果不是每一帧都要调用它们,也算是蛮快的^_^。那么这个RECT rectQ就代表着q个文字所对应在Texture上的区域位置?br>  使用什么东西来把这n个Char串v来呢Q一般会(x)惛_的是链表Q原因无非有2个:(x)1 随时有新的字加进来,而内存是不连l的 2 它几乎没有容量的限制Q除非是内存用完?jin)?j)。不q链表的讉K速度是很慢的Q如果用像数组q样的东西就好了(jin)。仔l想惻I在这里,我们用来存储?CacheQ最大也是256*256Q理׃面说?jin)?j)Q所以大应该会(x)是固定的。我们只需要在数组中的l每一个汉字加上一个标志,说明q个位置的用情c(din)那么就使用数组吧,q样的话Q访问的速度要更快一些,直接首地址+偏移量就够了(jin)Q不必像链表Q在查找旉要逐node讉K。当?dng)我绝不?x)惛_?new Char来申误个数l。因样做实在没有必要Q请不要q于q信自己的能力,在STL中已l有vector?jin),Z么还要自己写呢?^_^最后的一?bool成员变量isUsingQ也是上面所_(d)用来标志使用情况的?/font>


实际的操?br>  上面考虑?jin)那么多Q我认ؓ(f)都是实际操作之前所应该有的。先谈谈如何昄吧,因ؓ(f)在DirectX8.1中已l将DirectDraw?Direct3D融合为DirectGraphics?jin)。所以无法像原来那样?#8230;………哦,实在有太多东西要讲了(jin)Q我q是推荐几篇文章l你吧^_^Q?br>  http://vip.6to23.com/mays/develop/directx/200201/Geczy3Din2D.htm
  http://vip.6to23.com/mays/develop/directx/200201/GESurface.htm
  http://vip.6to23.com/mays/develop/directx/200112/2DGtoDX8.htm
  http://vip.6to23.com/mays/develop/directx/200201/DX8adv2D.htm
  接下来,我会(x)假设你已l具备了(jin)在DirectX8.1中绘囄基本概念?jin),所以在你(h)l往(xin)下阅M前,请务必先仔细阅读以上推荐的文章?br>  前面提到Q需要一个vector来对应Texture上各个位|文字的信息Q上面已l创Z(jin)一个结构CharQ则q个vector的定义ؓ(f)Q?br>   vector <Char> _vBuf; // 记录~冲中现有的文字情况
  首先Q由于可以利用硬件的攑֤~小Q所以字体的大小_ֺ要求不是很高Q只需要支?6*16?4*24大小的字体就可以?jin)。我们需要一个这L(fng)初始化函敎ͼ(x)
  bool CFont::
  /*-------------------------------------------------------------
  LPDIRECT3DDEVICE8 pd3dDevice --- D3DDevice讑֤
  char szFontName[] --- 字体?? ?hu)?
  int nSize --- 字体大小, 只支?6?4
  int nLevel --- U理的大?br>  -------------------------------------------------------------*/
  Init( LPDIRECT3DDEVICE8 pd3dDevice, char szFontName[], int nSize, int nLevel )?br>  
  在DirectX8.1中,由SetTexture(…)所贴的囄大小Q也是Texture的大,是有大小限制的,长和宽都必须?^nQ而且位图大Q所p的显存越大,q样留给其他昄用的昑֭少?jin)。所以,必须Ҏ(gu)需求的不同Q来自定Texture(也就是Cache)的大。因为汉字点阵大的原因Q所以从实用角度而言Q比方说只是昄fps或是短小的标题)(j)Q开辟一?4*64大小的TextureQ才能满x(chng)低情况下的需要(q时如果选择16炚w的话可以存放16个汉字,24炚w可以存放7个,依次cL……Q?br>  Ҏ(gu)讄Q创建TextureQ?br>   _TextureSize = 32 << nLevel; // U理大小
   _TextSize = nSize; // 文字大小
   _TextureSize = 32 << nLevel; // U理大小
  
   _RowNum = _TextureSize / _TextSize; // 计算一行可以容U_个文字
   _Max = _RowNum * _RowNum; // 计算~冲最大?br>  
  创徏字体Q还是需要用Win32 API。也是先创Z个HDCQ?br>   _hDc = CreateCompatibleDC(NULL);
  
  然后创徏一个BITMAP和一个FONTQ将它们与HDC兌h?br>   LOGFONT LogFont;
   ZeroMemory( &LogFont, sizeof(LogFont) );
   LogFont.lfHeight = -_TextSize;
   LogFont.lfWidth = 0;
   LogFont.lfEscapement = 0;
   LogFont.lfOrientation = 0;
   LogFont.lfWeight = FW_BOLD;
   LogFont.lfItalic = FALSE;
   LogFont.lfUnderline = FALSE;
   LogFont.lfStrikeOut = FALSE;
   LogFont.lfCharSet = DEFAULT_CHARSET;
   LogFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
   LogFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
   LogFont.lfQuality = DEFAULT_QUALITY;
   LogFont.lfPitchAndFamily = DEFAULT_PITCH;
   lstrcpy( LogFont.lfFaceName, szFontName );
  
   _hFont = CreateFontIndirect( &LogFont );
   if ( NULL == _hFont )
   {
   DeleteDC( _hDc );
   return false;
   }
  
  Q只需要创Z个字体大的BITMAP卛_Q?br>   BITMAPINFO bmi;
   ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER));
   bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
   bmi.bmiHeader.biWidth = _TextSize;
   bmi.bmiHeader.biHeight = -_TextSize;
   bmi.bmiHeader.biPlanes = 1;
   bmi.bmiHeader.biBitCount = 32;
   bmi.bmiHeader.biCompression = BI_RGB;
  
  Q这里需要定义一个指针指向位囄数据Q?br>   DWORD * _pBits; // 位图的数据指针)(j)
  
   _hBmp = CreateDIBSection( _hDc, &bmi, DIB_RGB_COLORS,
   (void **) &_pBits, NULL, 0 );
   if ( NULL == _hBmp || NULL == _pBits )
   {
   DeleteObject( _hFont );
   DeleteDC( _hDc );
   return false;
   }
  
   // hBmp和hFont加入到hDc
   SelectObject( _hDc, _hBmp );
   SelectObject( _hDc, _hFont );
  
  接着讄背景色和文字Ԍ(x)
   SetTextColor( _hDc, RGB(255,255,255) );
   SetBkColor( _hDc, 0 );
  
  讄文字Z寚wQ?br>   SetTextAlign( _hDc, TA_TOP );
  
  创徏Texture所需要的点~冲Q?br>   if ( FAILED( _pd3dDevice->CreateVertexBuffer( _Max * 6 * sizeof(FONT2DVERTEX),
   D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,
   D3DPOOL_DEFAULT, &_pVB ) ) )
   {
   DeleteObject( _hFont );
   DeleteObject( _hBmp );
   DeleteDC( _hDc );
   return false;
   }
  
  创徏Texture
   if ( FAILED( _pd3dDevice->CreateTexture( _TextureSize, _TextureSize, 1, 0,
   D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &_pTexture ) ) )
   {
   DeleteObject( _hFont );
   DeleteObject( _hBmp );
   DeleteDC( _hDc );
   SAFE_RELEASE(_pVB);
   return false;
   }
  
  讄渲染讑֤的渲染属性:(x)
   _pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
   _pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
   _pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
   _pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
   _pd3dDevice->SetRenderState( D3DRS_ALPHAREF, 0x08 );
   _pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
   _pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
  
   _pd3dDevice->SetTexture( 0, _pTexture );
   _pd3dDevice->SetVertexShader( D3DFVF_FONT2DVERTEX );
   _pd3dDevice->SetStreamSource( 0, _pVB, sizeof(FONT2DVERTEX) );
  
  讄~冲的最大容?br>   _vBuf.resize( _Max );
  
  q样Q初始化完成?jin)。接下来是如何把一个汉字写到Texture中,以及(qing)如何q行理。定义函敎ͼ(x)
  // 得到文字在纹理中的位|?br>  void CFont::
  /*-------------------------------------------------------------
  char c1 --- 文字的第1个字?br>  char c2 --- 文字的第2个字?br>  int & tX --- 写入U理中的坐标x
  int & tY --- 写入U理中的坐标y
  -------------------------------------------------------------*/
  Char2Texture( char c1, char c2, int & tX, int & tY )
  {
   WORD w = MAKEWORD(c1, c2); // 把此字变?sh)WORD
   vector<Char>::iterator it = find( _vBuf.begin(), _vBuf.end(), w );
   if ( it == _vBuf.end() ) // 如果没找?br>   {
   it = find( _vBuf.begin(), _vBuf.end(), 0 ); // 查找I闲位置
   if ( it == _vBuf.end() ) // ~冲已满
   {
   for(; it!=_vBuf.begin(); it-- )
   {
   it->hz = 0;
   }
  // Log.Output( "字体~冲已满, 清空!" );
   }
  
   // 计算当前I闲的Char在缓冲中是第几个
   int at = it-_vBuf.begin();
  
   // 得到I闲位置的坐?br>   tX = (at % _RowNum) * _TextSize;
   tY = (at / _RowNum) * _TextSize;
  
   // 讄q个CharZ用中
   (*it).hz = w;
  
   RECT rect = {0, 0, _TextSize, _TextSize};
   char sz[3] = {c1, c2, '\0'};
   // 填充背景为黑?透明?
   FillRect( _hDc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH) );
   // 往(xin)hBitmap上写?br>   ::TextOut( _hDc, 0, 0, sz, c1 & 0x80 ? 2 : 1 );
  
   // 锁定表面, 把汉字写入纹? 白色的是?可见), 黑色?透明)
   D3DLOCKED_RECT d3dlr;
   _pTexture->LockRect(0, &d3dlr, NULL, D3DLOCK_NOSYSLOCK);
   BYTE * pDstRow = (BYTE*)( (WORD *)d3dlr.pBits + tY * _TextureSize + tX );
  
   for (DWORD y=0; y<_TextSize; y++)
   {
   WORD * pDst16 = (WORD*)pDstRow;
   for (DWORD x=0; x<_TextSize; x++)
   {
   BYTE bAlpha = (BYTE)((_pBits[_TextSize * y + x] & 0xff) >> 4);
   if (bAlpha > 0)
   *pDst16++ = (bAlpha << 12) | 0x0fff;
   else
   *pDst16++ = 0x0000;
   }
   pDstRow += d3dlr.Pitch;
   }
   _pTexture->UnlockRect( NULL );
   }
   else
   {
   // 计算当前I闲的Char在缓冲中是第几个
   int at = it-_vBuf.begin();
  
   // 得到q个字的坐标
   tX = (at % _RowNum) * _TextSize;
   tY = (at / _RowNum) * _TextSize;
   }
  }
  以上代码中的注释已经很清楚了(jin)Q相信无L多言。这里唯一需要声明的是:(x)原来所定义的Charl构是这L(fng)
  struct Char{
   char hz[3]; // 保存汉字
   int frequency;// 使用频率
   RECT rect; // q个字对应位囄区域
   Bool isUsing; // 是否使用
  }
  后来因ؓ(f)char hz[3]合成为WORDQ所以改为WORD hz。然后对于int frequencyQ这个词频应该如何表玎ͼ我一直没有想到很好的Ҏ(gu)。frequency应该在何?+呢?是在每次被用的时候吗Q但是这L(fng)话,上面说过Q游戏是?0fps的速度在刷斎ͼ如果停上1分钟的话Q变量很快就?x)溢Z(jin)。就是使用像是DWORD或__int64q样的巨型变量保存,也是不安全的。除非能在某个合适的时候将frequency清零Q但是这?#8220;时?#8221;是什么时候呢Q或者设|一个最大|?5535Q但是这样也基本上没什么用途,很快Q所有在vector中的Char中的frequency都会(x)++?5535的。回忆一下最初,是因为想把常用字攑ֈvector的前面,以便每次find操作可以最快返回结果的。而经q我的测试,即不做q样的优化操作,速度也是很快的,毕竟Cache不是很大Q加上vector是连l内存空间。所以可以放弃用int frequency?br>  然后对于RECT rectQ因为没有了(jin)int frequencyQ意味着一旦将汉字写入到TextureQ其位置׃?x)变动?jin)。所以,很容易根据find函数操作后的iteratorQ直接计出q个汉字所在Texture的位|。这PRECT rect也不再必R?br>  而bool isUsingQ它本n是个鸡肋,要也可以Q这L(fng)构更加清晰。不q,直接通过观察WORD hz?或非0Q即可实现isUsing的作用了(jin)?br>  Z么要对结构Charq么_Nl琢呢?
1. 既然没有必要的东西,应该删?br>2. Charl构的大越大,vector所要求的内存越?br>3. 的l构Qfind可以更快地查扑և所l果
  Z么find?x)正常工作呢Q这里我要大概地讲一下find是如何查扑և所需的位|的Q它只是单地使用while从vector的begin一直遍历到endQ逐个判断Q直到找Cؓ(f)止。find要求必须实现自己的operator ==()Q进一步跟t到find的源码中Q发C是这栗于是前面的l构Char变成?jin)现在这P(x)
   struct Char{
   WORD hz; // 文字
  
   Char() : hz(0) {}
  
   // 用作查找文字
   inline bool operator == ( WORD h ) const
   {
   return hz==h ? true : false;
   }
   };
  是不是很单?^___^
  
  l于C(jin)昄的函C(jin)Q?br>  // 得到文字在纹理中的位|?br>  bool CFont::
  /*-------------------------------------------------------------
  char szText[] --- 昄的字W串
  int x --- 屏幕坐标x
  int y --- 屏幕坐标y
  D3DCOLOR --- 颜色?qing)alpha?br>  int nLen --- 字符串长?br>  float fScale --- 攑֤比例
  -------------------------------------------------------------*/
  TextOut( char szText[], int x, int y, D3DCOLOR color, int nLen, float fScale )
  {
   Assert( szText!=NULL );
  
   float sx = x, sy = y,
   offset=0, w=0, h=0, tx1=0, ty1=0, tx2=0, ty2=0;
   w = h = (float)_TextSize * fScale;
  
   char ch[3] = {0,0,0};
   FONT2DVERTEX * pVertices = NULL;
   UINT wNumTriangles = 0;
   _pVB->Lock(0, 0, (BYTE**)&pVertices, D3DLOCK_DISCARD);
  
   if ( -1 == nLen || // 默认?1
   nLen > lstrlen( szText ) ) // 如果nLen大于字符串实际长? 则nLen=实际长度
   nLen = lstrlen( szText );
   for (int n=0; n<nLen; n++ )
   {
   ch[0] = szText[n];
  
   if ( ch[0]=='\n' )
   {
   sy+=h;
   sx=x;
   continue;
   }
  
   if ( ch[0] & 0x80 )
   {
   n++;
   ch[1] = szText[n];
   offset = w;
   }
   else
   {
   ch[1] = '\0';
   offset = w / 2 ;
   }
  
   int a, b;
   Char2Texture( ch[0], ch[1], a, b );
  
   // 计算U理左上?0.0-1.0
   tx1 = (float)(a) / _TextureSize;
   ty1 = (float)(b) / _TextureSize;
   // 计算U理右上?0.0-1.0
   tx2 = tx1 + (float)_TextSize / _TextureSize;
   ty2 = ty1 + (float)_TextSize / _TextureSize;
  
   // 填充点~冲?br>   *pVertices++ = FONT2DVERTEX(sx, sy + h, 0.9f, color, tx1, ty2);
   *pVertices++ = FONT2DVERTEX(sx, sy, 0.9f, color, tx1, ty1);
   *pVertices++ = FONT2DVERTEX(sx + w, sy + h, 0.9f, color, tx2, ty2);
   *pVertices++ = FONT2DVERTEX(sx + w, sy, 0.9f, color, tx2, ty1);
   *pVertices++ = FONT2DVERTEX(sx + w, sy + h, 0.9f, color, tx2, ty2);
   *pVertices++ = FONT2DVERTEX(sx, sy, 0.9f, color, tx1, ty1);
  
   wNumTriangles+=2;
  
   sx+=offset; // 坐标x增量
   }
   _pVB->Unlock();
   _pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, wNumTriangles );
  
   return true;
  }


l束?br>  记得有一句名aQ?Keep it simple and stupid.在实现功能的同时Q保持代码简单、清晰是非常重要的一件事。相信在往(xin)后的日子里,在不论是别h阅读或是你自己回儡时候,你都?x)发C如既往(xin)地遵守这个守则,是多么得重要Q?br>  怿通过上面我那无数的废话,加上代码中还够的注释Q聪明的你一定能够明白这其中的原理了(jin)吧。如果以上的内容q(sh)以让你完全搞清楚的话,你可以登录我的主:(x)
  

炎龙工作?br>  上面不仅包括?jin)上面所写的E序代码Q还有一个用来演C效果的一个很单的demo?br>  说明Q以上所实现的CFont是包含在我的游戏引擎中的一个部Ӟ而目前已l实现的部g包括有:(x)
1. CGameFrameQ游戏框架类Q?----- 装?jin)窗口?qing)D3D讑֤的徏立,需要派生出自己的子c?br>2. CAudio和CSoundQ声音类Q?----- 支持wav/mid/mp3的播?br>3. CDirectInputQ控制类Q?----- 键盘、鼠标操?br>4. CDirectShowQ视频类Q?----- 支持avi/mpg/mov{的播放
5. CSpriteXQ精늱Q?----- 方便游戏中对_的控?br>6. CFontQ字体类Q?----- 中英文字体的昄
7. CTimerQ时间类Q?----- 高精度时间的控制
8. FPSQfps c)(j) ----- fps的计?br>9. LOGQ日志类Q?----- 游戏中的错误反应以及(qing)状态记?br>  最重要的是Q这个Game Engine完全是开放源代码的。关于更新的情况、版本说明以?qing)源码下载,请随时关注我的主?br>接下来,我将?x)?h)l完善这个EngineQ可能加入的有:(x)高效_子pȝ、斜45度角地图……



Code Knight 2010-02-28 20:19 发表评论
]]>
[转]CEGUI中的汉字昄实现http://www.shnenglu.com/winmain/archive/2010/02/27/108576.htmlCode KnightCode KnightSat, 27 Feb 2010 13:38:00 GMThttp://www.shnenglu.com/winmain/archive/2010/02/27/108576.htmlhttp://www.shnenglu.com/winmain/comments/108576.htmlhttp://www.shnenglu.com/winmain/archive/2010/02/27/108576.html#Feedback0http://www.shnenglu.com/winmain/comments/commentRss/108576.htmlhttp://www.shnenglu.com/winmain/services/trackbacks/108576.html几日前,?nbsp;CEGUI做界面,发现无法应用CEGUI的window中setText()函数直接昄中文。上|google一下,原来l过单的字符转化可以昄中文Q偷着乐,CEGUI太方便了(jin)Q?/p>

 

Ҏ(gu)如下Q引用)(j)Qhttp://blog.csdn.net/kun1234567/archive/2008/04/11/2282761.aspx

CEGUI使用utf8~码格式。这意味着我们可以很简单的显CZ文?/p>

 

1、弄个包含中文的字体Q在q里我借用大多C子里?“CQ?windows/Font/simhei.ttf”文g。把q个文g拯到Datafiles文g夹的Font文g多w?/p>

 

2、随便照着一?.Font文gQ自己写一个simhei.font文g。可以用TXT写,然后保存Q有的朋友说需要保存(sh)ؓ(f)utf8~码格式Q实际上是不需要的?/p>

 

3、同时注意修改你加蝲到程序里的scheme文gQ将里面的字体文件设|成simhei.ttf。你也可以(h)l用FirstWindowq个例子Q这L(fng)话直接修Ҏ(gu)代码里的字体为simhei.tff?/p>

 

4、现在在E序里进行字W编码{换,我拿代码说明问题Q?/p>

 

std::wstring aa = L"123中文abcあいうえ?;

char buff[128] = "";

WideCharToMultiByte( CP_UTF8, 0, aa.c_str(), aa.size(), buff, sizeof(buff), 0, 0);

button1->setText ( CEGUI::String ( CEGUI::utf8* )buff );

 

原理是这L(fng)Q对于utf8来说Q英文字W和ansi~码在内存布局上没什么区别,都是一个UCHAR。但是对于非英文字符Q则是UCHAR+UCHAR+UCHAR。如果我们手工进行编码格式{换,?x)比较?ch)琐?/p>

 

比较h的方法就是,我们先用WCHAR(unicode内存布局,UCHAR+UCHAR+UCHAR+UCHAR)来储存需要显C的字符Ԍ然后调用Win32API来帮我们把宽字符转换成char(多字节字W集内存布局)?/p>

 

q就是基本方法了(jin)Q然后我们可以根据这个{换方针,利用Win32API随意的{换字W编码格式,从而满程序中的各U需求?/p>

 

 

       通过此方法可以显CZ文,q没来得急高兴就发现?jin)第二个问题Q这U方法显CZ文速度太慢Q显C几十个字需要等??U左叻I(j)。难道没有高效的Ҏ(gu)吗?

于是l箋(hu)Google(我很懒,别h能做的事情从来不ȝ(ch)自己Q懒得跟t代?Q结果还真让我找C(jin)两篇相关的文章:(x)一份是千里马肝的《游戏中汉字昄的实C技巧》,另一份是免费打工仔的《让OGRE支持中文》。从中找C(jin)原因Q?/p>

       原来在游戏中Q是点阵字库或tif字体里的文字写进U理Q根据需求脓(chung)到指定的位置。英文的昄非常单,只有26个字母,q再加一些标炏V符号什么的Q用一张位图,可以以显C所有的单词?jin)。而中文要像处理英文那P把所有的汉字都保存在一张位NQ那么每一U字体都要生成一个巨型位图。在 GB2312中,一共有6000多个汉字Q就是?6*16Q据说会(x)?.5MQ(马肝兄说的,我没过Q?/p>

    l箋(hu)GoogleQ也没有扑ֈ解决问题的直接办法,唉,再懒也得自己上阵?jin)?/p>

通过跟踪调试Q发C(jin)问题所在,原来|魁R是他:(x)

 

const FontGlyph *Font::getGlyphData (utf32 codepoint)

{

     if (codepoint > d_maxCodepoint)

         return 0;

 

         if (d_glyphPageLoaded)

         {

              uint page = codepoint / GLYPHS_PER_PAGE;

              uint mask = 1 << (page & (BITS_PER_UINT - 1));

              if (!(d_glyphPageLoaded [page / BITS_PER_UINT] & mask))

              {

                   d_glyphPageLoaded [page / BITS_PER_UINT] |= mask;

                   rasterize (codepoint & ~(GLYPHS_PER_PAGE - 1),

                       codepoint | (GLYPHS_PER_PAGE - 1));

              }

         }

 

         CodepointMap::const_iterator pos = d_cp_map.find (codepoint);

         return (pos != d_cp_map.end()) ? &pos->second : 0;

}

 

原来CEGUIҎ(gu)Unicode字符的编码顺序,为每256个字W分配一张纹理(例如~码0-255存放在纹理一Q编?68-1023 存放在纹理四Q。英文很Ҏ(gu)搞定?jin),那么几个字符一张纹理就够了(jin)Q可中文得靠运气了(jin)Q有时显C几个字p生成几张U理Q还要将每张U理用不需要的盔R字填满,x(chng)伤胦(ch)Q?/p>

发现?jin)问题,我便按照千里马肝的思想对函数进行了(jin)攚w,用的文字攑օ一张纹理中Q因为纹理最大承?56个字Q所以,当汉字超q?56个时Q则不常用的去掉,新的字W写入?/p>

后来我发现汉字的引用没有太多的规律,常用的一千多汉字出现的概率没有那么?zhn)D(废话Q要不怎么是常用呢!Q,没有办法很好地按照用的频率汉字限制在256个字以内Q写q纹理,q(ch)性一旦满?jin)就字全部释放掉,重新写入。(也需有我没找刎ͼq请高手指教Q?/p>

代码如下Q?/p>

const FontGlyph *Font::getGlyphData (utf32 codepoint)

{

     if (codepoint > d_maxCodepoint)

         return 0;

 

     if(codepoint < 256)  //军_保留一张纹理放英文和字W?/p>

     {

         if (d_glyphPageLoaded)

         {

              uint page = codepoint / GLYPHS_PER_PAGE;

              uint mask = 1 << (page & (BITS_PER_UINT - 1));

              if (!(d_glyphPageLoaded [page / BITS_PER_UINT] & mask))

              {

                   d_glyphPageLoaded [page / BITS_PER_UINT] |= mask;

                   rasterize (codepoint & ~(GLYPHS_PER_PAGE - 1),

                       codepoint | (GLYPHS_PER_PAGE - 1));

              }

         }

 

         CodepointMap::const_iterator pos = d_cp_map.find (codepoint);

         return (pos != d_cp_map.end()) ? &pos->second : 0;

     }

     else //昄汉字?/p>

     {

         CodepointMap::const_iterator pos;

 

         pos = d_hz_map.find (codepoint);

 

         if(pos != d_hz_map.end())

         {

              return (pos != d_hz_map.end()) ? &pos->second : 0;

         }

         else

         {

              rasterizeHZ(codepoint);

 

              pos = d_hz_map.find (codepoint);

              return (pos != d_hz_map.end()) ? &pos->second : 0;

         }

     }

}

 

void FreeTypeFont::rasterizeHZ (utf32 codepoint)

{

     int num;

     uint texsize = 512;

 

     if(d_hz_map.size() < 256)

     {

         float adv = d_fontFace->glyph->metrics.horiAdvance * float(FT_POS_COEF);

 

         d_hz_map[codepoint] = FontGlyph (adv);

     }

     else

     {

         d_hz_map.clear();

 

          ImagesetManager::getSingleton ().destroyImageset (hzImageset->getName ());

 

         hzImageset = ImagesetManager::getSingleton ().createImageset (

              d_name + "_auto_glyph_images_" ,

              System::getSingleton ().getRenderer ()->createTexture ());

 

         d_glyphImages.push_back (hzImageset);

 

         float adv = d_fontFace->glyph->metrics.horiAdvance * float(FT_POS_COEF);

 

         d_hz_map[codepoint] = FontGlyph (adv);

     }

 

     CodepointMap::const_iterator hzInter  = d_hz_map.find(codepoint);

 

     if (!hzInter->second.getImage())

     {

         // Render the glyph

         if (FT_Load_Char (d_fontFace, hzInter->first, FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT |

              (d_antiAliased ? FT_LOAD_TARGET_NORMAL : FT_LOAD_TARGET_MONO)))

         {

              std::stringstream err;

              err << "Font::loadFreetypeGlyph - Failed to load glyph for codepoint: ";

              err << static_cast<unsigned int> (hzInter->first);

              err << ".  Will use an empty image for this glyph!";

              Logger::getSingleton ().logEvent (err.str (), Errors);

 

              // Create a 'null' image for this glyph so we do not seg later

              Rect area(0, 0, 0, 0);

              Point offset(0, 0);

              String name;

              name += hzInter->first;

              hzImageset->defineImage(name, area, offset);

              ((FontGlyph &)hzInter->second).setImage(&hzImageset->getImage(name));

         }

         else

         {

              uint glyph_w = d_fontFace->glyph->bitmap.width + INTER_GLYPH_PAD_SPACE;

              uint glyph_h = d_fontFace->glyph->bitmap.rows + INTER_GLYPH_PAD_SPACE;

 

              // Check if glyph right margin does not exceed texture size

              uint x_next = m_nHZX + glyph_w;

              if (x_next > texsize)

              {

                  m_nHZX = INTER_GLYPH_PAD_SPACE;

                   x_next = m_nHZX + glyph_w;

                   m_nHZY = m_nHZYB;

              }

 

              // Check if glyph bottom margine does not exceed texture size

              uint y_bot = m_nHZY + glyph_h;

             

 

              // Copy rendered glyph to memory buffer in RGBA format

              drawGlyphToBuffer (hzmem_buffer + (m_nHZY * texsize) + m_nHZX, texsize);

 

              // Create a new image in the imageset

              Rect area(static_cast<float>(m_nHZX),

                   static_cast<float>(m_nHZY),

                   static_cast<float>(m_nHZX + glyph_w - INTER_GLYPH_PAD_SPACE),

                   static_cast<float>(m_nHZY + glyph_h - INTER_GLYPH_PAD_SPACE));

 

              Point offset(d_fontFace->glyph->metrics.horiBearingX * static_cast<float>(FT_POS_COEF),

                   -d_fontFace->glyph->metrics.horiBearingY * static_cast<float>(FT_POS_COEF));

 

              String name;

              name += hzInter->first;

              hzImageset->defineImage (name, area, offset);

              ((FontGlyph &)hzInter->second).setImage (&hzImageset->getImage (name));

 

              // Advance to next position

              m_nHZX = x_next;

              if (y_bot > m_nHZYB)

              {

                   m_nHZYB = y_bot;

              }

         }

     }

 

     // Copy our memory buffer into the texture and free it

     hzImageset->getTexture ()->loadFromMemory (hzmem_buffer, texsize, texsize, Texture::PF_RGBA);

 

}

 

     OKQ问题搞定,打完收工。试试,效果q(sh)错,可以z洗睡了(jin)。特自q一点体?x)写出来Q给新手提供个捷径,也希望高手批评指教?/p>

Code Knight 2010-02-27 21:38 发表评论
]]>
QT记之在VS2005中用QThttp://www.shnenglu.com/winmain/archive/2010/01/31/106885.htmlCode KnightCode KnightSun, 31 Jan 2010 06:44:00 GMThttp://www.shnenglu.com/winmain/archive/2010/01/31/106885.htmlhttp://www.shnenglu.com/winmain/comments/106885.htmlhttp://www.shnenglu.com/winmain/archive/2010/01/31/106885.html#Feedback0http://www.shnenglu.com/winmain/comments/commentRss/106885.htmlhttp://www.shnenglu.com/winmain/services/trackbacks/106885.html    如何在Windowsq_下用QT开发?
    一Q下载SDK?br>       请去官网(QT被NOKIA收购Q貌g用协议更宽松?jin)?j)下蝲win版本的QTSDK包。(地址如不知请癑ֺGOOGLE之)(j)
    二,讄开发环境相兛_?br>       pȝ环变QPATH下加入:(x)(yourqtinstallpath)\bin
                 d新的环境变量,名字?QMAKESPEC",gؓ(f)"win32-msvc2005".
       VS2005环境Qinclude和lib分别包含qt的include目录和qt的lib目录
    ? ~译你所需要的QT Lib
      通过"开?菜单 -> "Microsoft Visual Studio 2005" -> "Visual Studio Tools", q行命o(h)行(勿用cmdQ找不到nmake)
      (yourqtinstallpath)>configure -no-stl -no-dsp -vcproj
      待QMake完成 l箋(hu)单的敲入nmake卛_Q等待编译吧Q?br>    ?创徏QT工程 helloworld
       有三U办法把QT代码生成为VS工程
       1Q用qmake,如代码在C盘(sh)
       C:\> qmake -project -t vcapp -o projectname.pro
       C:\> qmake
       2Q编写pro工程文g。如果是商业版的׃用了(jin)。具体可以参考帮助文档qmake。新事本文gQ文件名修改为hello.proQ文件名没有 Ҏ(gu)要求哈;输入

        SOURCES +=main.cpp
        CONFIG +=qt

        ok 保存?/p>

        打开命o(h)行,切换目录到hello.cpp所在目录。生成Makefile文gQ输入:(x)

    qmake -o Makefile hello.pro Q?

    接下来生成项目文?vcproj文g?

    qmake -tp vc -o hello.vcproj hello.pro

   3Q直接?span class=ColorResultsClass highlight="true" realoffset="1237" alpha-value="20">Qt Visual Studio Integration v1.2.2 for.VS.2003.2005插g(详见http://blog.csdn.net/znf19850924/archive/2008/01/16/2047373.aspx)

    需要配|?span class=ColorResultsClass highlight="true" realoffset="1384" alpha-value="20">如下Q?/strong>
         "Tools" -> "Options" -> "Qt" -> "Builds", d我们刚才~译?span class=ColorResultsClass highlight="true" realoffset="1405" alpha-value="20">Qt代码,名字?Qt 4.3.2", 路径?yourqtinstallpath)

     启动一个新的工E?
         选择"Qt projects" -> "Qt Application"cd,输入工程名字,单击OK.

     双击工程文g里面?test.ui",马上出现?jin)所见及(qing)所得的H体~辑?在上面添加一个按?

     双击按钮,产生相应的消息响应函?

     d头文?
         #include <QMessageBox>

         在函数void Test::on_pushButton_clicked()体内d如下代码:
         QMessageBox box(this);
         box.setText("Haha, hit me.");
         box.exec();

    
       PS:另外可以直接使用QTSDK自带安装的QTCreate来进行QT工程Q在安装好SDK后不需要进行Q何配|就能够q行DEMOq看到效果,可能自n已经配置好,但是如何引入到VS中,暂时q(sh)知道Q没有研I?br>

Code Knight 2010-01-31 14:44 发表评论
]]>
VS05~译wxWidgetshttp://www.shnenglu.com/winmain/archive/2009/02/16/73974.htmlCode KnightCode KnightMon, 16 Feb 2009 14:59:00 GMThttp://www.shnenglu.com/winmain/archive/2009/02/16/73974.htmlhttp://www.shnenglu.com/winmain/comments/73974.htmlhttp://www.shnenglu.com/winmain/archive/2009/02/16/73974.html#Feedback0http://www.shnenglu.com/winmain/comments/commentRss/73974.htmlhttp://www.shnenglu.com/winmain/services/trackbacks/73974.html
DQ?
  1. 去http://www.wxwidgets.org/downloads/下蝲一个wxMSW版本的wxWidgets?
  2. q行安装文g。在安装好后讄环境变量WXWINQ指向wxWidgets的安装目录。因为安装过E仅仅是把文件拷贝到指定的目录,所以还需要对wxWidgetsq行~译?
  3. q入$(WXWIN)\build\msw目录Q用VS2005打开wx.dswQ提C是否进行项目{换,点确定。如果想要连接静(rn)态运行库Q在~译前应该对每个目q行讄?br>  
   
         ~译Debug版本的库Q用Visual Studio 2005打开build\msw\wx.dsw文gQSolution Configurations中选中Unicode DebugQ直接Build Solution可以编译出Debug版本的wxWidgets库了(jin)?默认的是Multi-Threaded debug dll)
    ~译Relase版本的库QRelease 版本的wxWidgets库虽然也可以通过cM的方法去~译Q但~译出来的库仍然依赖于visual studio 2005的运行时库。Debug版本的库依赖VS2005也就了(jin)Q反正是自己调试用的。Release版本可是要给别h用的Q再带上一大堆dll׃好了(jin)。ؓ(f)?jin)解册个问题,我们需要先在Solution Configuration中选中Unicode ReleaseQ然后在Solution Explorer中,针对每一个project在项目属性的C/C++ --> Code Generation --> Runtime Library中选Multi-Threaded?HOHO, ?0个项目要改属性啊~~~)。最后再Build Solution可以了(jin)?也就是LIB?

  
  ~译好后的wxWidgets?x)?(WXWIN)\lib\vc_lib目录下生成一pd的lib文gQ这些lib文g的名字遵循下面的命名规则Q不依赖于GUIlg的库?x)?wxbase"开_(d)紧跟着的是版本P然后的字母表明这个库是否是编译ؓ(f)Unicode('u')或是否是~译为Debug('d')Q名字中的最后部分是wxWidgetslg的名字?
  注意QwxWidgets~译完后?(WXWIN)\build\msw目录下会(x)生成许多预编译头文gQ占?jin)很大的I间Q如果确定以后不再编译wxWidgets库的话,可以考虑删掉?
  讄VC开发环?
  打开Tools -> Options -> Projects and Solutions -> VC++ Directories
  1. 在Include files中加?(WXWIN)\include?(WXWIN)\include\msvc
  2. 在Library files中加?(WXWIN)\lib\vc_lib
  创徏wxWidgets目
  新徏一个General -> Empty Project或Win32 -> Win32 Project目Q然后设|项目的一些属性,可以选择下面的其中一个来讄。譬如你如果打算使用UnicodeQ那么选择Unicode Debug或Unicode ReleaseQ如果你仅仅惌试程序而非发布Q则只需要选择Debug讄?
  DebugQ?
  Project Properties -> General -> Character Set: No Set
  Project Properties -> C/C++ -> Code Generation -> Runtime Library: Multi-threaded Debug DLL (/MDd)
  Project Properties -> Linker -> Input -> Additional Dependencies: wxbase28d.lib wxmsw28d_core.lib winmm.lib comctl32.lib rpcrt4.lib wsock32.lib oleacc.lib

  ReleaseQ?
  Project Properties -> General -> Character Set: No Set
  Project Properties -> C/C++ -> Code Generation -> Runtime Library: Multi-threaded (/MT)
  Project Properties -> Linker -> Input -> Additional Dependencies: wxbase28.lib wxmsw28_core.lib winmm.lib comctl32.lib rpcrt4.lib wsock32.lib oleacc.lib

  Unicode DebugQ?
  Project Properties -> General -> Character Set: Use Unicode Character Set
  Project Properties -> C/C++ -> Code Generation -> Runtime Library: Multi-threaded Debug DLL (/MDd)
  Project Properties -> Linker -> Input -> Additional Dependencies: wxbase28ud.lib wxmsw28ud_core.lib winmm.lib comctl32.lib rpcrt4.lib wsock32.lib oleacc.lib

  Unicode ReleaseQ?
  Project Properties -> General -> Character Set: Use Unicode Character Set
  Project Properties -> C/C++ -> Code Generation -> Runtime Library: Multi-threaded (/MT)
  Project Properties -> Linker -> Input -> Additional Dependencies: wxbase28u.lib wxmsw28u_core.lib winmm.lib comctl32.lib rpcrt4.lib wsock32.lib oleacc.lib

  问题
  1. 在编译时出现?jin)Cannot open include file: '../mswu/wx/setup.h': No such file or directory错误
  q是因ؓ(f)目属性的Character Set讄不正,必须与用的wxWidgets库的Character Set一致?
  2. 在编译时出现?jin)MSVCRT.lib(MSVCRT.dll) : error LNK2005: _free already defined in LIBC.lib(free.obj)
  q是因ؓ(f)没有q接正确的wxWidgets库,譬如Unicode Debug版本的项目就需要连接Unicode+Debug版本的wxWidgets?库名后缀?ud'的lib文g)。或者是wxWidgets和Application使用的Runtime Library不相同?
  3. q行是出现No Debugging Information对话?
  Project Properties -> Linker -> Debugging -> Generate Debug Info的值改成Yes (/DEBUG)?br>
#ifndef WXWIDGETS_EXAMPLE_HELLOWORLDAPP_H_20080722
#define WXWIDGETS_EXAMPLE_HELLOWORLDAPP_H_20080722

//对于支持预编译的~译器,包含此文?br>// For compilers that support precompilation, includes "wx.h".
#include <wx/wxprec.h>

//对于不支持预~译的编译器Q进行如下操?/span>
#ifndef WX_PRECOMP
// Include your minimal set of headers here, or wx.h
#include <wx/wx.h>
#endif

//定义wxAppc?/span>
class HelloWorldApp : public wxApp
{
public :
    
//在程序初始化时调?/span>
    virtual bool OnInit();
    
//在程序结束时调用
    virtual int OnExit();
};

//定义wxGetApp()函数Q可以取得HelloWorldAppcd的全局E序变量
DECLARE_APP(HelloWorldApp)

#endif //WXWIDGETS_EXAMPLE_HELLOWORLDAPP_H_20080722


#ifndef WXWIDGETS_EXAMPLE_HELLOWORLDAPP_H_20080722
#define WXWIDGETS_EXAMPLE_HELLOWORLDAPP_H_20080722

//对于支持预编译的~译器,包含此文?br>// For compilers that support precompilation, includes "wx.h".
#include <wx/wxprec.h>

//对于不支持预~译的编译器Q进行如下操?/span>
#ifndef WX_PRECOMP
// Include your minimal set of headers here, or wx.h
#include <wx/wx.h>
#endif

//定义wxAppc?/span>
class HelloWorldApp : public wxApp
{
public :
    
//在程序初始化时调?/span>
    virtual bool OnInit();
    
//在程序结束时调用
    virtual int OnExit();
};

//定义wxGetApp()函数Q可以取得HelloWorldAppcd的全局E序变量
DECLARE_APP(HelloWorldApp)

#endif //WXWIDGETS_EXAMPLE_HELLOWORLDAPP_H_20080722




Code Knight 2009-02-16 22:59 发表评论
]]>
þﶼǾƷ| þþþþAŷAV| þþѾƷre6| VVþþ| ۺþþ| 91þø˾Ʒ| þþþþþ޾Ʒ| þ°Ҳȥ| ޾ƷĻþò | þþžžþƷֱ| ۺϾƷ㽶þ| 91ƷɫۺϾþ| ݺݾƷþþĻ| þþƷhþþƷ帣ӰԺ1421 | 91ƷɫۺϾþ| þþþþžžƷӰԺ| ۺɫ77777þ| 2021˾Ʒþ| ɫɫۺϾþҹҹ| 97þþƷһ| þþþ?V| 㽶þۺӰ | þѾƷav | þùɫAVѿ| þþþƷSmվ| պƷþĻ| ھƷþþþù| ҹƷþþþþëƬ| 99þþƷһѿ| 99ξþþŷƷվ| Ʒպҹþ| AVĻþר| רþ| ھƷþù½| 99þҹɫƷվ| þþþþþþþþѾƷ| 97þó˾Ʒվ| 97þۺɫdžѿ| þùVһë| һaƬþëƬ| ŷþþXXX|