sitetext.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:13k
源码类别:

Symbian

开发平台:

Visual C++

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