WizFontsEnumerator.cpp
上传用户:xsxdsb
上传日期:2009-12-14
资源大小:672k
文件大小:9k
源码类别:

书籍源码

开发平台:

Visual C++

  1. // WizFontsEnumerator.cpp: implementation of the CWizFontsEnumerator class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "WizFontsEnumerator.h"
  6. #ifdef _DEBUG
  7. #undef THIS_FILE
  8. static char THIS_FILE[]=__FILE__;
  9. #define new DEBUG_NEW
  10. #endif
  11. namespace
  12. {
  13. UCHAR TTDefaults[] = { 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72 };
  14. const int TTDefaultsSize =  sizeof(TTDefaults)/sizeof(TTDefaults[0]);
  15. }
  16. //////////////////////////////////////////////////////////////////////
  17. CWizFontsEnumerator::Font::Font(const LOGFONT& lf, DWORD fontType, LPCTSTR Script)
  18. : m_Name(lf.lfFaceName) ,  m_bItalics(false), m_bBold(false), 
  19.   m_bUnderline(false),  m_bRegular(false),
  20.   m_dwFontType(fontType),  m_bInited(false)
  21. {
  22. if (Script && *Script)
  23. AddScript(Script);
  24. }
  25. void CWizFontsEnumerator::Font::operator=(const Font& f)
  26. {
  27. m_Name = f.m_Name ;
  28. m_bItalics = f.m_bItalics ; 
  29. m_bBold = f.m_bBold ; 
  30. m_bUnderline= f.m_bUnderline;
  31. m_bRegular = f.m_bRegular;
  32. m_dwFontType= f.m_dwFontType;
  33. m_Script.RemoveAll();
  34. for (int i = 0; i < f.m_Script.GetSize(); i++)
  35. m_Script.Add(f.m_Script[i]);
  36. m_sizes.SetSize(f.m_sizes.GetSize());
  37. for (i = 0; i < f.m_sizes.GetSize(); i++)
  38. m_sizes[i] = f.m_sizes[i];
  39. m_bInited = f.m_bInited;
  40. }
  41. struct Font_EnumStep
  42. {
  43. Font_EnumStep(CWizFontsEnumerator::Font& f, CDC& dc)
  44. : rTHIS(f) , r_dc(dc) 
  45. {
  46. cyPixelsPerInch = dc.GetDeviceCaps(LOGPIXELSY);
  47. }
  48. CWizFontsEnumerator::Font& rTHIS;
  49. CDC& r_dc;
  50. int cyPixelsPerInch;
  51. };
  52. int CALLBACK DetailsEnumProc (const ENUMLOGFONTEX *lpelfe, const NEWTEXTMETRICEX *lpntme, unsigned long FontType, LPARAM lParam) 
  53. {
  54. Font_EnumStep* p = reinterpret_cast<Font_EnumStep*>(lParam);
  55. return p->rTHIS.DoEnumStep (lpelfe, lpntme, FontType, *p);
  56. }
  57. int CWizFontsEnumerator::Font::DoEnumStep (const ENUMLOGFONTEX *lpelf, const NEWTEXTMETRICEX *lpntm, unsigned long FontType, Font_EnumStep& data)
  58. {
  59. ASSERT(&(data.rTHIS) == this);
  60. if (FontType & TRUETYPE_FONTTYPE)
  61. {
  62. if (!(lpntm->ntmTm.ntmFlags & (NTM_BOLD | NTM_ITALIC)))
  63. {
  64. TRACE("ntFont %s add regular", lpelf->elfLogFont.lfFaceName);
  65. m_bRegular = true;
  66. }
  67. if (lpntm->ntmTm.ntmFlags & NTM_ITALIC)
  68. {
  69. TRACE("ntFont %s add Italics", lpelf->elfLogFont.lfFaceName);
  70. m_bItalics = true;
  71. }
  72. if (lpntm->ntmTm.ntmFlags & NTM_BOLD)
  73. {
  74. TRACE("ntFont %s add Bold", lpelf->elfLogFont.lfFaceName);
  75. m_bBold = true;
  76. }
  77. }
  78. else
  79. {
  80. if (FontType & RASTER_FONTTYPE)
  81. {
  82. int height = lpntm->ntmTm.tmHeight - lpntm->ntmTm.tmInternalLeading;
  83. int size_pp = MulDiv(height, 72, data.cyPixelsPerInch); //, height);
  84. TRACE("ntFont %s add size %d", lpelf->elfLogFont.lfFaceName, size_pp);
  85. AddSize(size_pp, height);
  86. }
  87. if (lpelf->elfLogFont.lfWeight >= FW_BOLD && lpelf->elfLogFont.lfItalic)
  88. {
  89. TRACE("ntFont %s add bold & italics", lpelf->elfLogFont.lfFaceName);
  90. m_bItalics = true;
  91. m_bBold = true;
  92. }
  93. else if (lpelf->elfLogFont.lfWeight >= FW_BOLD)
  94. {
  95. TRACE("ntFont %s add bold", lpelf->elfLogFont.lfFaceName);
  96. m_bBold = true;
  97. }
  98. else if (lpelf->elfLogFont.lfItalic)
  99. {
  100. TRACE("ntFont %s add italics", lpelf->elfLogFont.lfFaceName);
  101. m_bItalics = true;
  102. }
  103. else
  104. {
  105. TRACE("ntFont %s add regular", lpelf->elfLogFont.lfFaceName);
  106. m_bRegular = true;
  107. }
  108. }
  109. return 1;
  110. }
  111. void CWizFontsEnumerator::Font::DoInit() 
  112. {
  113. // Init flags
  114. m_bRegular = m_bItalics = m_bBold = m_bUnderline = false;
  115. // Init for enumeration
  116. CClientDC dc(NULL);
  117. LOGFONT lf;
  118. memset (&lf, 0, sizeof(lf));
  119. lf.lfCharSet = DEFAULT_CHARSET;
  120. strcpy(lf.lfFaceName, m_Name);
  121. Font_EnumStep temp(const_cast<Font&>(*this), dc);
  122. // Enumeration procedure
  123. EnumFontFamiliesEx (dc.m_hAttribDC, &lf, (FONTENUMPROC)::DetailsEnumProc, reinterpret_cast<LPARAM>(&temp), 0);
  124. // Finish init:
  125. m_bUnderline = true; // Always availible so far
  126. // Allow for "synthesized" italic && bold variants
  127. if (m_bRegular)
  128. m_bItalics = m_bBold = true;
  129. }
  130. void CWizFontsEnumerator::Font::Initialize() const
  131. {
  132. if (m_bInited)
  133. return;
  134. const_cast<Font*>(this)->DoInit();
  135. m_bInited = true;
  136. }
  137. void CWizFontsEnumerator::Font::FillSizes(CWordArray& sizes) const
  138. {
  139. sizes.SetSize(0);
  140. if (m_dwFontType != RASTER_FONTTYPE)
  141. {
  142. sizes.SetSize(TTDefaultsSize);
  143. for (int i = 0; i < TTDefaultsSize; i++)
  144. sizes[i] = TTDefaults[i];
  145. }
  146. else
  147. {
  148. Initialize();
  149. sizes.SetSize(m_sizes.GetSize());
  150. for (int i = 0; i < m_sizes.GetSize(); i++)
  151. sizes[i] = m_sizes[i];
  152. }
  153. }
  154. bool CWizFontsEnumerator::Font::CanBeItalics () const
  155. {
  156. Initialize();
  157. return m_bItalics;
  158. }
  159. bool CWizFontsEnumerator::Font::CanBeBold () const
  160. {
  161. Initialize();
  162. return m_bBold;
  163. }
  164. bool CWizFontsEnumerator::Font::CanBeUnderline () const
  165. {
  166. Initialize();
  167. return m_bUnderline;
  168. }
  169. bool CWizFontsEnumerator::Font::CanBeRegular () const
  170. {
  171. Initialize();
  172. return m_bRegular;
  173. }
  174. bool CWizFontsEnumerator::Font::MustBeRegular () const
  175. {
  176. Initialize();
  177. return (m_bRegular && !(m_bItalics || m_bUnderline || m_bBold));
  178. }
  179. bool CWizFontsEnumerator::Font::MustBeItalics () const
  180. {
  181. Initialize();
  182. return (m_bItalics && !(m_bRegular /*|| m_bUnderline || m_bBold*/));
  183. }
  184. bool CWizFontsEnumerator::Font::MustBeBold () const
  185. {
  186. Initialize();
  187. return (m_bBold && !(m_bRegular /*|| m_bItalics  || m_bUnderline*/));
  188. }
  189. bool CWizFontsEnumerator::Font::MustBeUnderline () const
  190. {
  191. Initialize();
  192. return false;// (m_bUnderline && !(m_bRegular || m_bItalics || m_bBold));
  193. }
  194. void CWizFontsEnumerator::Font::AddSize(int pp_size, int lf_height)
  195. {
  196. m_sizes.Add(WORD(pp_size));
  197. }
  198. void CWizFontsEnumerator::Font::AddScript(LPCTSTR Script)
  199. m_Script.Add(Script);
  200. }
  201. //////////////////////////////////////////////////////////////////////
  202. // Construction/Destruction
  203. //////////////////////////////////////////////////////////////////////
  204. CWizFontsEnumerator::CWizFontsEnumerator()
  205. {
  206. }
  207. CWizFontsEnumerator::~CWizFontsEnumerator()
  208. {
  209. }
  210. //回调函数
  211. int CWizFontsEnumerator::DoEnumStep (const ENUMLOGFONTEX *lpelfe, const NEWTEXTMETRICEX *lpntme, unsigned long FontType)
  212. {
  213. CString script = lpelfe->elfScript;
  214. TRACE("nFont %s", lpelfe->elfLogFont.lfFaceName);
  215. //如果该字体存在,则加入到数组m_aFonts中
  216. int nFont = FindFont(lpelfe->elfLogFont.lfFaceName);
  217. if (nFont >= 0)
  218. {
  219. m_aFonts.ElementAt(nFont).AddScript(script);
  220. TRACE(" Add script %s", (LPCTSTR)script);
  221. return 1;
  222. }
  223. // add font to list
  224. Font f (lpelfe->elfLogFont, FontType, script);
  225. int i = m_aFonts.Add(f);
  226. if (i < 0)
  227. //抛出异常
  228. ASSERT(0); 
  229. AfxThrowMemoryException();
  230. }
  231. TRACE(" Script %s", (LPCTSTR)script);
  232. return 1;
  233. }
  234. //回调函数
  235. int CALLBACK EnumProc (const ENUMLOGFONTEX *lpelfe, const NEWTEXTMETRICEX *lpntme, unsigned long FontType, LPARAM lParam) 
  236. {
  237. CWizFontsEnumerator* pTHIS = reinterpret_cast<CWizFontsEnumerator*>(lParam);
  238. return pTHIS->DoEnumStep (lpelfe, lpntme, FontType);
  239. }
  240. //罗列出所有字体
  241. void CWizFontsEnumerator::DoEnumerate (HDC hdc)
  242. {
  243. //先清空保存字体的数组
  244. ASSERT(NULL != hdc);
  245. m_aFonts.RemoveAll();
  246. LOGFONT lf;
  247. memset (&lf, 0, sizeof(lf));
  248. lf.lfCharSet = DEFAULT_CHARSET;
  249. lf.lfFaceName[0]= 0;
  250. //列出字体,回调函数为EnumProc
  251. EnumFontFamiliesEx (hdc, &lf, (FONTENUMPROC)::EnumProc, reinterpret_cast<LPARAM>(this), 0);
  252. #ifdef _DEBUG
  253. TRACE("nFound %d fonts:", m_aFonts.GetSize());
  254. for (int i = 0; i < m_aFonts.GetSize(); i++)
  255. {
  256. const Font* p = GetFont(i);
  257. TRACE("n %s", (LPCTSTR)(p->Name()));
  258. for (int j = 0; j < p->GetScriptsCount(); j++)
  259. TRACE("nt %s", (LPCTSTR)(p->GetScript(j)));
  260. }
  261. #endif
  262. }
  263. void CWizFontsEnumerator::InternalEnumerate (HDC hdc, bool bWayBack)
  264. {
  265. // If no valid DC supplied
  266. if (NULL == hdc && bWayBack)
  267. {
  268. TRACE0("Warning! NULL hDC at CWizFontsEnumerator::Enumerate"); 
  269. // Get main app window (hopefully)
  270. CClientDC some(NULL);
  271. //CWnd* pSomeWnd = AfxGetMainWnd();
  272. InternalEnumerate(some, false); // No way back here again
  273. }
  274. else
  275. DoEnumerate (hdc);
  276. }
  277. void CWizFontsEnumerator::InternalEnumerate (CDC* pdc, bool bWayBack)
  278. {
  279. if (NULL != pdc)
  280. InternalEnumerate(pdc->m_hAttribDC, bWayBack);
  281. else
  282. {
  283. TRACE0("Warning! NULL pDC at CWizFontsEnumerator::Enumerate");
  284. if (bWayBack) // try to figure up something
  285. InternalEnumerate ((HDC)NULL, bWayBack);
  286. }
  287. }
  288. void CWizFontsEnumerator::InternalEnumerate (CWnd* pWnd, bool bWayBack)
  289. {
  290. if (NULL == pWnd)
  291. {
  292. TRACE0("Warning! NULL Window at CWizFontsEnumerator::Enumerate"); 
  293. if (bWayBack) // try to figure up something
  294. InternalEnumerate((HDC)NULL, bWayBack);
  295. }
  296. else
  297. {
  298. // Two attempts to get DC: client DC and, if fails,
  299. // window DC
  300. // BLOCK
  301. {
  302. CClientDC dc(pWnd);
  303. if (dc.m_hAttribDC != NULL)
  304. {
  305. InternalEnumerate(&dc, bWayBack);
  306. return;
  307. }
  308. }
  309. // BLOCK
  310. {
  311. CWindowDC dc(pWnd);
  312. InternalEnumerate(&dc, bWayBack);
  313. }
  314. }
  315. }
  316. void CWizFontsEnumerator::Enumerate (HDC hdc)
  317. {
  318. InternalEnumerate(hdc, true);
  319. }
  320. void CWizFontsEnumerator::Enumerate (CDC* pdc)
  321. {
  322. InternalEnumerate(pdc, true);
  323. }
  324. void CWizFontsEnumerator::Enumerate (CWnd* pWnd)
  325. {
  326. InternalEnumerate(pWnd, true);
  327. }