FDC.cpp
上传用户:hmc_gdtv
上传日期:2013-08-04
资源大小:798k
文件大小:8k
源码类别:

Windows Mobile

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 2001,2002,2003 Mike Matsnev.  All Rights Reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice immediately at the beginning of the file, without modification,
  10.  *    this list of conditions, and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. Absolutely no warranty of function or purpose is made by the author
  15.  *    Mike Matsnev.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  * 
  28.  * $Id: FDC.cpp,v 1.18.2.5 2003/09/27 11:30:55 mike Exp $
  29.  * 
  30.  */
  31. #include <afx.h>
  32. #include "config.h"
  33. #include "FDC.h"
  34. #include "ptr.h"
  35. #include "Attr.h"
  36. #include "Unicode.h"
  37. #include "Colors.h"
  38. #ifdef _DEBUG
  39. #undef THIS_FILE
  40. static char THIS_FILE[]=__FILE__;
  41. #define new DEBUG_NEW
  42. #endif
  43. ///////////////////////////////////////////////////////////////////////////////
  44. // Font cache
  45. struct Font {
  46.   HFONT   m_font;
  47.   int   m_size;
  48.   int   m_refcount;
  49.   int   m_height;
  50.   int   m_ascent;
  51.   int   m_angle;
  52.   int   m_hwidth;
  53.   unsigned m_flags;
  54.   bool   m_ok;
  55.   Font() : m_font(NULL), m_height(-1), m_ascent(-1), m_ok(false),
  56.     m_angle(0), m_hwidth(-1) { }
  57.   ~Font() { DeleteObject(m_font); }
  58.   void   Grab() { ++m_refcount; }
  59.   void   Release() { if (--m_refcount==0) delete this; }
  60. };
  61. struct FontCache {
  62.   CPtrArray m_lru;
  63.   int     m_cachemax; // max number of entries in cache
  64.   CString   m_face;
  65.   int     m_basesize;
  66.   bool     m_defbold;
  67.   int     m_cleartype;
  68.   int     m_angle;
  69.   FontCache();
  70.   ~FontCache() { RemoveAll(); }
  71.   Font     *AllocFont();
  72.   void     RemoveAll();
  73.   void     Release(Font *f);
  74.   void     SetDefault(const TCHAR *f,int bs,bool b,int ct,int an);
  75.   Font     *FindOrAlloc(int size,unsigned flags,int an);
  76. };
  77. #define FNT(i)   ((Font*)(m_lru[(i)]))
  78. static FontCache g_fcache;
  79. FontCache::FontCache() :
  80.   m_cachemax(6), m_face(_T("Tahoma")),
  81.   m_basesize(12), m_defbold(false), m_cleartype(0), m_angle(0)
  82. {
  83. }
  84. void FontCache::RemoveAll() {
  85.   for (int i=0;i<m_lru.GetSize();++i) {
  86.     FNT(i)->m_ok=false;
  87.     FNT(i)->Release();
  88.   }
  89.   m_lru.RemoveAll();
  90. }
  91. Font *FontCache::AllocFont() {
  92.   if (m_lru.GetSize()<m_cachemax || FNT(0)->m_refcount>1) { // allocate new
  93.     Font    *f=new Font;
  94.     f->m_refcount=1;
  95.     m_lru.Add(f);
  96.     return f;
  97.   }
  98.   // reuse
  99.   Font   *f=FNT(0);
  100.   m_lru.RemoveAt(0);
  101.   m_lru.Add(f);
  102.   DeleteObject(f->m_font);
  103.   f->m_ok=false;
  104.   f->m_ascent=f->m_height=-1;
  105.   return f;
  106. }
  107. void  FontCache::SetDefault(const TCHAR *f,int bs,bool b,int ct,int an) {
  108.   if (m_face!=f || ct!=m_cleartype)
  109.     RemoveAll();
  110.   m_face=f;
  111.   m_basesize=bs;
  112.   m_defbold=b;
  113.   m_cleartype=ct;
  114.   m_angle=an;
  115. }
  116. Font  *FontCache::FindOrAlloc(int size,unsigned flags,int an) {
  117.   int i;
  118.   Font *f;
  119.   for (i=0;i<m_lru.GetSize();++i) {
  120.     f=FNT(i);
  121.     if (f->m_size==size && f->m_flags==flags && f->m_angle==an) {
  122.       if (i!=m_lru.GetUpperBound()) {
  123. m_lru.RemoveAt(i);
  124. m_lru.Add(f);
  125.       }
  126.       return f;
  127.     }
  128.   }
  129.   f=AllocFont();
  130.   LOGFONT   lf;
  131.   memset(&lf,0,sizeof(lf));
  132.   lf.lfHeight=-size;
  133.   lf.lfEscapement=lf.lfOrientation=an;
  134.   lf.lfWeight=flags&Attr::BOLD ? FW_BOLD : FW_NORMAL;
  135.   lf.lfItalic=flags&Attr::ITALIC ? 1 : 0;
  136.   lf.lfUnderline=flags&Attr::UNDERLINE ? 1 : 0;
  137.   lf.lfCharSet=DEFAULT_CHARSET;
  138.   lf.lfOutPrecision=OUT_DEFAULT_PRECIS;
  139.   lf.lfClipPrecision=CLIP_DEFAULT_PRECIS;
  140. #ifdef _WIN32_WCE
  141.   lf.lfQuality=m_cleartype ? CLEARTYPE_QUALITY : DEFAULT_QUALITY;
  142. #else
  143.   if (m_cleartype==1)
  144.     lf.lfQuality=CLEARTYPE_QUALITY;
  145.   else if (m_cleartype==2)
  146.     lf.lfQuality=ANTIALIASED_QUALITY;
  147.   else
  148.     lf.lfQuality=NONANTIALIASED_QUALITY;
  149. #endif
  150.   lf.lfPitchAndFamily=DEFAULT_PITCH|FF_DONTCARE;
  151.   if (flags&CFDC::FORCETAHOMA)
  152.     _tcsncpy(lf.lfFaceName,_T("Tahoma"),LF_FACESIZE-1);
  153.   else if (flags&Attr::XFONT) {
  154.     _tcsncpy(lf.lfFaceName,_T("NewtonUni"),LF_FACESIZE-1);
  155.     lf.lfHeight-=2; // adjust relative size to tahoma
  156.   } else
  157.     _tcsncpy(lf.lfFaceName,m_face,LF_FACESIZE-1);
  158.   f->m_font=CreateFontIndirect(&lf);
  159.   f->m_size=size;
  160.   f->m_flags=flags;
  161.   f->m_angle=an;
  162.   f->m_ok=true;
  163.   return f;
  164. }
  165. void  FontCache::Release(Font *f) {
  166.   int i;
  167.   for (i=0;i<m_lru.GetSize();++i)
  168.     if (FNT(i)==f) {
  169.       if (f->m_refcount>1) {
  170. f->Release();
  171. if (i>0 && FNT(i)->m_refcount>1) {
  172.   m_lru.RemoveAt(i);
  173.   m_lru.InsertAt(0,f);
  174. }
  175. while (m_lru.GetSize()>m_cachemax && FNT(0)->m_refcount==1) {
  176.   f=FNT(0);
  177.   m_lru.RemoveAt(0);
  178.   f->Release();
  179. }
  180.       }
  181.       return;
  182.     }
  183.   f->Release();
  184. }
  185. void  CFDC::SetDefaultFont(const TCHAR *face,int basesize,bool bold,
  186.    int cleartype,int angle) {
  187.   g_fcache.SetDefault(face,basesize,bold,cleartype,angle);
  188. }
  189. void  CFDC::SelectFontAbs(int size,unsigned flags,bool zesc) {
  190.   Font *f=(Font*)m_hFont;
  191.   if (g_fcache.m_defbold && !(flags&FORCENORMALWEIGHT))
  192.     flags|=Attr::BOLD;
  193.   int ang=zesc ? 0 : g_fcache.m_angle;
  194.   if (f && f->m_ok && f->m_size==size && f->m_flags==flags && f->m_angle==ang)
  195.     return;
  196.   if (f)
  197.     g_fcache.Release(f);
  198.   f=g_fcache.FindOrAlloc(size,flags,ang);
  199.   f->Grab();
  200.   m_hFont=(void*)f;
  201.   HGDIOBJ obj=SelectObject(m_hDC,f->m_font);
  202.   if (!m_hOrigFont)
  203.     m_hOrigFont=obj;
  204. }
  205. void  CFDC::SelectFont(int size,unsigned flags,bool zesc) {
  206.   SelectFontAbs(size+g_fcache.m_basesize,flags,zesc);
  207. }
  208. CFDC::CFDC(HWND hWnd,PAINTSTRUCT *ps) :
  209.   m_hFont(NULL), m_hOrigFont(NULL), m_hOrigPen(NULL), m_hWnd(hWnd), m_ps(ps),
  210.   m_lpx(0)
  211. {
  212.   if (m_ps)
  213.     m_hDC=BeginPaint(m_hWnd,m_ps);
  214.   else
  215.     m_hDC=GetDC(m_hWnd);
  216.   SetBkMode(m_hDC,TRANSPARENT);
  217.   ::SetTextColor(m_hDC,m_fg=C_NORM);
  218.   ::SetBkColor(m_hDC,m_bg=C_BG);
  219.   m_pfg=RGB(0,0,0); // default pen is black
  220. }
  221. CFDC::~CFDC() {
  222.   if (m_hOrigFont)
  223.     SelectObject(m_hDC,m_hOrigFont);
  224.   if (m_hOrigPen)
  225.     DeleteObject(SelectObject(m_hDC,m_hOrigPen));
  226.   if (m_hFont)
  227.     g_fcache.Release((Font*)m_hFont);
  228.   if (m_ps)
  229.     EndPaint(m_hWnd,m_ps);
  230.   else
  231.     ReleaseDC(m_hWnd,m_hDC);
  232. }
  233. void  CFDC::GetFontSize(int& height,int& ascent) {
  234.   Font *f=(Font*)m_hFont;
  235.   if (!f || f->m_height<0) {
  236.     TEXTMETRIC tm;
  237.     GetTextMetrics(m_hDC,&tm);
  238.     height=tm.tmAscent+tm.tmDescent+tm.tmExternalLeading;
  239.     ascent=tm.tmAscent;
  240.     if (f) {
  241.       f->m_height=height;
  242.       f->m_ascent=ascent;
  243.     }
  244.   } else {
  245.     height=f->m_height;
  246.     ascent=f->m_ascent;
  247.   }
  248. }
  249. int  CFDC::GetHypWidth() {
  250.   Font *f=(Font*)m_hFont;
  251.   if (!f || f->m_hwidth<0) {
  252.     SIZE    sz;
  253.     ::GetTextExtentPoint32(m_hDC,_T("-"),1,&sz);
  254.     if (f)
  255.       f->m_hwidth=sz.cx;
  256.     return sz.cx;
  257.   }
  258.   return f->m_hwidth;
  259. }
  260. void  CFDC::SetCacheSize(int cs) {
  261.   if (cs>0 && cs<100)
  262.     g_fcache.m_cachemax=cs;
  263. }
  264. int  CFDC::GetLPX() {
  265.   if (!m_lpx)
  266.     m_lpx=GetDeviceCaps(m_hDC,LOGPIXELSX);
  267.   return m_lpx;
  268. }
  269. void  CFDC::GetTextExtent(const wchar_t *str,int len,
  270.   int width,int& nch,int *dx,SIZE& sz)
  271. {
  272.   GetTextExtentExPoint(m_hDC,str,len,width,&nch,dx,&sz);
  273. }
  274. void  CFDC::SetColor(COLORREF c) {
  275.   if (c!=m_pfg) {
  276.     HGDIOBJ obj=::SelectObject(m_hDC,::CreatePen(PS_SOLID,0,c));
  277.     if (m_hOrigPen)
  278.       DeleteObject(obj);
  279.     else
  280.       m_hOrigPen=obj;
  281.     m_pfg=c;
  282.   }
  283. }