sitetext.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:13k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hxcom.h"
  36. #include "hxtypes.h"
  37. #include "hxwintyp.h"
  38. #include "hxmap.h"
  39. #include "hxslist.h"
  40. #include "ihxpckts.h"
  41. #include "hxwin.h"
  42. #include "hxengin.h"
  43. #include "hxsite2.h"
  44. #include "chxxtype.h"
  45. #include "hxvctrl.h"
  46. #include "hxvsurf.h"
  47. #include "hxcodec.h"
  48. #include "surface.h"
  49. #include "vidosurf.h"
  50. #include "chxpckts.h"
  51. #include "hxevent.h"
  52. #include "sitetext.h"
  53. #include "platform/mac/hx_moreprocesses.h"
  54. #define DEF_TEXT_HEIGHT 12
  55. #define POINTS_TO_PIXELS 1.5
  56. #define DEF_TEXT_GUTTER 1.2
  57. #define DEF_STAT_HEIGHT (int)((double)DEF_TEXT_HEIGHT * POINTS_TO_PIXELS * DEF_TEXT_GUTTER)
  58. #define DEF_HORZ_GUTTER 4
  59. #define ELIPSIS "..."
  60. #define ELIPSIS_LEN 3
  61. CHXSiteStatusText::CHXSiteStatusText()
  62.     : m_lRefCount(0)
  63.     , m_pSite(NULL)
  64.     , m_pParentSite(NULL)
  65.     , m_rgbBkgndColor(0x00008000)
  66.     , m_rgbTextColor(0x0000FF00)
  67.     , m_pStatusImage(NULL)
  68. {
  69.     memset(&m_statusPos, 0, sizeof(HXxPoint));
  70.     memset(&m_statusSize, 0, sizeof(HXxSize));
  71. }
  72.     
  73. CHXSiteStatusText::~CHXSiteStatusText()
  74. {
  75.     Destroy(); // make sure we cleanup
  76. }
  77. HX_RESULT
  78. CHXSiteStatusText::Create(IHXSite* pSite)
  79. {
  80.     IHXSite* pChildSite = NULL;
  81.     HX_RESULT  hr = HXR_FAIL;
  82.     
  83.     HX_ASSERT(pSite);
  84.     HX_ASSERT(!m_pSite);
  85.     
  86.     // keep a ref while we use the parent site
  87.     pSite->AddRef();
  88.     
  89.     if (pSite->CreateChild(pChildSite) == HXR_OK)
  90.     {
  91.      if (pChildSite->AttachUser(this) == HXR_OK)
  92.      {
  93.          m_pParentSite = pSite;
  94.          HX_ASSERT(m_StatusText.IsEmpty());
  95.          
  96.          if (m_StatusText.IsEmpty())
  97.          {
  98.           Hide(); // keep hidden until we have status text
  99.          }
  100.          else
  101.          {
  102.           Show();
  103.          }
  104.          UpdatePosition();
  105.          hr = HXR_OK;
  106.      }
  107.      HX_RELEASE(pChildSite);
  108.     }
  109. // release if we failed
  110.     if (hr != HXR_OK)
  111.     {
  112.      HX_RELEASE(pSite);
  113.     }
  114.     return hr;
  115. }
  116. HX_RESULT
  117. CHXSiteStatusText::Destroy()
  118. {
  119.     if (m_pSite)
  120.     {
  121.      if (m_pParentSite)
  122.      {
  123.          m_pParentSite->DestroyChild(m_pSite);
  124.      }
  125.      // DetachUser will call DetachSite, which will release m_pSite
  126.      m_pSite->DetachUser();
  127.     
  128.     }
  129.     HX_RELEASE(m_pParentSite);
  130.     
  131.     HX_DELETE(m_pStatusImage);
  132.     
  133.     return HXR_OK;
  134. }
  135.     
  136. HX_RESULT
  137. CHXSiteStatusText::Show()
  138. {
  139.     IHXSite2* pSite2 = NULL;
  140.     
  141.     if (GetIHXSite2(pSite2) == HXR_OK)
  142.     {
  143.      pSite2->ShowSite(TRUE);
  144.      HX_RELEASE(pSite2);
  145.     }
  146.     
  147.     return HXR_OK;
  148. }
  149. HX_RESULT
  150. CHXSiteStatusText::Hide()
  151. {
  152.     IHXSite2* pSite2 = NULL;
  153.     
  154.     if (GetIHXSite2(pSite2) == HXR_OK)
  155.     {
  156.      pSite2->ShowSite(FALSE);
  157.      HX_RELEASE(pSite2);
  158.     }
  159.     
  160.     return HXR_OK;
  161. }
  162. HX_RESULT
  163. CHXSiteStatusText::ParentChangedSize()
  164. {
  165.     UpdatePosition();
  166.     return HXR_OK;
  167. }
  168. HX_RESULT
  169. CHXSiteStatusText::BringToTop()
  170. {
  171.     IHXSite2* pSite2 = NULL;
  172.     
  173.     if (GetIHXSite2(pSite2) == HXR_OK)
  174.     {
  175.      pSite2->MoveSiteToTop();
  176.      HX_RELEASE(pSite2);
  177.     }
  178.     
  179.     return HXR_OK;
  180. }
  181. HX_RESULT
  182. CHXSiteStatusText::UpdatePosition()
  183. {
  184.     HX_RESULT  hr = HXR_FAIL;
  185.     HXxPoint parentPos;
  186.     HXxSize parentSize;
  187.     
  188.     if (m_pParentSite && m_pSite)
  189.     {
  190.      if (m_pParentSite->GetSize(parentSize) == HXR_OK &&
  191.          m_pParentSite->GetPosition(parentPos) == HXR_OK)
  192.      {
  193.          // call platform-specific code to adjust the position & size
  194.          // of our site (since fonts may require different heights on
  195.          // different platforms
  196.     _AdjustPosition(&parentPos, &parentSize);
  197.          
  198.          m_pSite->SetPosition(m_statusPos);
  199.          m_pSite->SetSize(m_statusSize);
  200.      }
  201.     }
  202.     
  203.     return HXR_OK;
  204. }
  205. void
  206. CHXSiteStatusText::SetStatusText(const char* pText)
  207. {
  208.     CHXString oldStatusText = m_StatusText;
  209.     m_StatusText = pText;
  210.     
  211.     if (m_StatusText != oldStatusText)
  212.     {
  213. if (m_StatusText.IsEmpty())
  214. {
  215.     Hide();
  216. }
  217. else
  218. {
  219.     if (m_pSite)
  220.     {
  221. m_pSite->ForceRedraw();
  222.     }
  223.     if (oldStatusText.IsEmpty())
  224.     {
  225. BringToTop();
  226. Show();
  227.     }
  228. }
  229.     }
  230. }
  231.     
  232. STDMETHODIMP
  233. CHXSiteStatusText::QueryInterface(REFIID riid, void** ppvObj)
  234. {
  235.     if (riid == IID_IHXSiteUser)
  236.     {
  237.      *ppvObj = (IHXSiteUser*)this;
  238.      AddRef();
  239.      return HXR_OK;
  240.     }
  241.     if (riid == IID_IHXSiteWatcher)
  242.     {
  243.      *ppvObj = (IHXSiteWatcher*)this;
  244.      AddRef();
  245.      return HXR_OK;
  246.     }
  247.     else if (riid == IID_IUnknown)
  248.     {
  249.      *ppvObj = (IUnknown*)(IHXSiteUser*)this;
  250.      AddRef();
  251.      return HXR_OK;
  252.     }
  253.     
  254.     return HXR_FAIL;
  255. }
  256. STDMETHODIMP_(ULONG32)
  257. CHXSiteStatusText::AddRef()
  258. {
  259.     return InterlockedIncrement(&m_lRefCount);
  260. }
  261. STDMETHODIMP_(ULONG32)
  262. CHXSiteStatusText::Release()
  263. {
  264.     if (InterlockedDecrement(&m_lRefCount) > 0)
  265.     {
  266.      return m_lRefCount;
  267.     }
  268.     
  269.     delete this;
  270.     return 0;
  271. }
  272. STDMETHODIMP
  273. CHXSiteStatusText::AttachSite(IHXSite* /*IN*/ pSite)
  274. {
  275.     HX_RESULT hr = HXR_FAIL;
  276.     
  277.     if (!m_pSite)
  278.     {
  279.      m_pSite = pSite;
  280.      m_pSite->AddRef();
  281.      hr = HXR_OK;
  282.     }
  283.     
  284.     return hr;
  285. }
  286. STDMETHODIMP
  287. CHXSiteStatusText::DetachSite()
  288. {
  289.     HX_RESULT hr = HXR_FAIL;
  290.     
  291.     if (m_pSite)
  292.     {
  293.      HX_RELEASE(m_pSite);
  294.      hr = HXR_OK;
  295.     }
  296.     
  297.     return hr;
  298. }
  299. STDMETHODIMP
  300. CHXSiteStatusText::HandleEvent(HXxEvent* /*IN*/ pEvent)
  301. {
  302.     HX_RESULT hr = HXR_OK;
  303.     
  304.     if (pEvent->event == HX_SURFACE_UPDATE)
  305.     {
  306.      _DrawStatusText(pEvent);
  307.     }
  308.     
  309.     return hr;
  310. }
  311. STDMETHODIMP_(BOOL)
  312. CHXSiteStatusText::NeedsWindowedSites()
  313. {
  314.     return false;
  315. }
  316. HX_RESULT
  317. CHXSiteStatusText::GetIHXSite2(REF(IHXSite2*) pSite2)
  318. {
  319.     HX_RESULT hr = HXR_FAIL;
  320.     
  321.     if (m_pSite)
  322.     {
  323.      hr = m_pSite->QueryInterface(IID_IHXSite2, (void**)&pSite2);
  324.     }
  325.     
  326.     return hr;
  327. }
  328. void ConvertHXxColorToRGBColor(HXxColor& pnx, RGBColor& rgb)
  329. {
  330.     unsigned short red, blue, green;
  331.     red = ((unsigned char*)&pnx)[1];
  332.     green = ((unsigned char*)&pnx)[2];
  333.     blue = ((unsigned char*)&pnx)[3];
  334.     
  335.     rgb.red = red | (red << 8); 
  336.     rgb.green = green | (green << 8);  
  337.     rgb.blue = blue | (blue << 8); 
  338. }
  339. HX_RESULT
  340. CHXSiteStatusText::_DrawStatusText(HXxEvent* pEvent)
  341. {
  342.     // this function is called internally and this will never be null
  343.     HX_ASSERT(pEvent);
  344.     // XXXNH: the status text does not support drawing at interrupt time
  345.     if (!IsMacInCooperativeThread())
  346.     {
  347. return HXR_FAIL;
  348.     }
  349.     
  350.     pEvent->handled = TRUE;
  351.     pEvent->result = HXR_OK;
  352.     // The rect for our status message
  353.     HXxSize sz;
  354.     m_pSite->GetSize(sz);
  355.     Rect theRect;
  356.     ::SetRect(&theRect, 0, 0, sz.cx, sz.cy);
  357.     
  358.     if (!m_pStatusImage || (sizeof(m_pStatusImage) < m_statusSize.cy * m_statusSize.cx * 4))
  359.     {
  360. HX_DELETE(m_pStatusImage);
  361. m_pStatusImage = new BYTE[m_statusSize.cy * m_statusSize.cx * 4];
  362.     }
  363.     
  364.     // create offscreen graphics world
  365.     GWorldPtr offscreenGWorld;
  366.     PixMapHandle hPixMap = NULL;
  367.     long theRowBytes = sz.cx * 4;
  368.     
  369.     OSType thePixelFormat = k32BGRAPixelFormat;
  370.     OSErr err = noErr;
  371.     
  372.     err = NewGWorldFromPtr(
  373. &offscreenGWorld,
  374. thePixelFormat,
  375. &theRect,
  376. NULL, // color table
  377. NULL, // GDevice handle
  378. 0, // flags
  379. (Ptr)m_pStatusImage,
  380. theRowBytes);
  381.     HX_ASSERT(err == noErr);
  382.     
  383.     // set offscreen graphics world:
  384.     GDHandle hGDSave;
  385.     CGrafPtr pCGrafSave;
  386.     ::GetGWorld(&pCGrafSave, &hGDSave);
  387.     ::SetGWorld(offscreenGWorld, NULL);
  388.     
  389.     // update clip region to this site's bounds
  390.     RgnHandle theNewClipRgn = ::NewRgn();
  391.     ::RectRgn(theNewClipRgn, &theRect);
  392.     ::SetClip(theNewClipRgn);
  393.     ::DisposeRgn(theNewClipRgn);
  394.     
  395.     // convert our fg & bg colors
  396.     RGBColor bgColor;
  397.     ConvertHXxColorToRGBColor(m_rgbBkgndColor, bgColor);
  398.     RGBColor fgColor;
  399.     ConvertHXxColorToRGBColor(m_rgbTextColor, fgColor);
  400.     
  401.     // Draw the background rect
  402.     ::RGBBackColor(&bgColor);
  403.     ::RGBForeColor(&bgColor);
  404.     ::PaintRect(&theRect);
  405.     
  406.     ::RGBBackColor(&bgColor);
  407.     ::RGBForeColor(&fgColor);
  408.     
  409.     // pick the font, center it and draw it
  410.     short nFontId = 0;
  411.     GetFNum("pHelvetica", &nFontId);
  412.     TextFont(nFontId);
  413.     int nSize = DEF_TEXT_HEIGHT;
  414.     TextSize(nSize);
  415.     
  416.     // keep a local copy of status text in case we need to add an elipsis
  417.     CHXString statusText = m_StatusText;
  418.     int nStrLen = statusText.GetLength();
  419.     const char* pStr = statusText;
  420.     
  421.     int nElipsisLen = TextWidth(ELIPSIS, 0, ELIPSIS_LEN);
  422.     int nWidth = TextWidth(pStr, 0, nStrLen);
  423.     while (nWidth > m_statusSize.cx - DEF_HORZ_GUTTER && nStrLen > 0)
  424.     {
  425. nStrLen--;
  426.      nWidth = TextWidth(pStr, 0, nStrLen) + nElipsisLen;
  427.     }
  428.     if (nStrLen < statusText.GetLength())
  429.     {
  430.      statusText = statusText.Left(nStrLen);
  431.      statusText += ELIPSIS;
  432.      nStrLen += ELIPSIS_LEN;
  433.      pStr = statusText;
  434.     }
  435.     
  436.     int nHeight = (int)((double)nSize * POINTS_TO_PIXELS);
  437.     int nX = max(0, (m_statusSize.cx - nWidth) / 2);
  438.     int nY = (int)((double)m_statusSize.cy / 2 + (double)nSize / 2);
  439.     ::MoveTo(nX, nY);
  440.     
  441.     ::TextMode(srcCopy);
  442.     ::DrawText(pStr, 0, nStrLen);
  443.     
  444.     // switch port
  445.     ::SetGWorld(pCGrafSave, hGDSave);
  446.     ::DisposeGWorld(offscreenGWorld);
  447.     
  448.     IHXVideoSurface* pVideoSurface = (IHXVideoSurface*)pEvent->param1;
  449.     
  450.     if (!pVideoSurface)
  451.     {
  452. return HXR_FAIL;
  453.     }
  454.     
  455.     pVideoSurface->AddRef();
  456.     
  457.     HXxRect rDestRect;
  458.     rDestRect.left = 0;
  459.     rDestRect.top = 0;
  460.     rDestRect.right = sz.cx;
  461.     rDestRect.bottom = sz.cy;
  462.     
  463.     HXxRect rSrcRect = rDestRect;
  464.     
  465.     HXBitmapInfoHeader bitmapInfoHeader;
  466.     bitmapInfoHeader.biSize = sizeof(HXBitmapInfoHeader);
  467.     bitmapInfoHeader.biWidth = sz.cx;
  468.     bitmapInfoHeader.biHeight = sz.cy;
  469.     bitmapInfoHeader.biPlanes = 1;
  470.     bitmapInfoHeader.biBitCount = 32;
  471.     bitmapInfoHeader.biCompression = HX_RGB;
  472.     bitmapInfoHeader.biSizeImage = sz.cx * sz.cy * 4;
  473.     bitmapInfoHeader.biXPelsPerMeter = 0;
  474.     bitmapInfoHeader.biYPelsPerMeter = 0;
  475.     bitmapInfoHeader.biClrUsed = 0;
  476.     bitmapInfoHeader.biClrImportant = 0;
  477.     bitmapInfoHeader.rcolor = 0;
  478.     bitmapInfoHeader.gcolor = 0;
  479.     bitmapInfoHeader.bcolor = 0;
  480.     
  481.     pEvent->result = pVideoSurface->Blt(m_pStatusImage, &bitmapInfoHeader, rDestRect, rSrcRect);
  482.     
  483.     pVideoSurface->Release();
  484.     
  485.     return pEvent->result;
  486. }
  487. HX_RESULT
  488. CHXSiteStatusText::_AdjustPosition(HXxPoint* pParentPos, HXxSize* pParentSize)
  489. {
  490.     HX_RESULT hr = HXR_OK;
  491.     // this function is called internally and these will never be null
  492.     HX_ASSERT(pParentPos && pParentSize);
  493.     
  494.     // take the max width of the parent site
  495.     m_statusPos.x = 0;
  496.     m_statusSize.cx = pParentSize->cx;
  497.     
  498.     // take at most the bottom DEF_STAT_HEIGHT pixels of the parent site
  499.     m_statusPos.y = max(pParentSize->cy - DEF_STAT_HEIGHT, 0);
  500.     m_statusSize.cy = pParentSize->cy - m_statusPos.y;
  501.     
  502.     return hr;
  503. }