⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sitetext.cpp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CPP
字号:
/* ***** BEGIN LICENSE BLOCK ***** 
 * Version: RCSL 1.0/RPSL 1.0 
 *  
 * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
 *      
 * The contents of this file, and the files included with this file, are 
 * subject to the current version of the RealNetworks Public Source License 
 * Version 1.0 (the "RPSL") available at 
 * http://www.helixcommunity.org/content/rpsl unless you have licensed 
 * the file under the RealNetworks Community Source License Version 1.0 
 * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
 * in which case the RCSL will apply. You may also obtain the license terms 
 * directly from RealNetworks.  You may not use this file except in 
 * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
 * applicable to this file, the RCSL.  Please see the applicable RPSL or 
 * RCSL for the rights, obligations and limitations governing use of the 
 * contents of the file.  
 *  
 * This file is part of the Helix DNA Technology. RealNetworks is the 
 * developer of the Original Code and owns the copyrights in the portions 
 * it created. 
 *  
 * This file, and the files included with this file, is distributed and made 
 * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
 * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
 * 
 * Technology Compatibility Kit Test Suite(s) Location: 
 *    http://www.helixcommunity.org/content/tck 
 * 
 * Contributor(s): 
 *  
 * ***** END LICENSE BLOCK ***** */ 

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Intrinsic.h>

#include "hxcom.h"
#include "hxtypes.h"
#include "hxwintyp.h"
#include "hxmap.h"
#include "hxslist.h"

#include "ihxpckts.h"
#include "hxwin.h"
#include "hxengin.h"

#include "hxsite2.h"
#include "chxxtype.h"

#include "hxvctrl.h"
#include "hxvsurf.h"
#include "hxcodec.h"
#include "surface.h"
#include "vidosurf.h"
#include "chxpckts.h"
#include "hxevent.h"

#include "sitemgr.h"
#include "sitetext.h"

//#include "pnmm.h" ??

#define DEF_TEXT_HEIGHT		12
#define POINTS_TO_PIXELS	1.5
#define DEF_TEXT_GUTTER		1.2
#define DEF_STAT_HEIGHT		(int)((double)DEF_TEXT_HEIGHT * POINTS_TO_PIXELS * DEF_TEXT_GUTTER)
#define DEF_HORZ_GUTTER		4
#define ELIPSIS			"..."
#define ELIPSIS_LEN		3


// fwd declares 
typedef ULONG32 COLORTYPE;



CHXSiteStatusText::CHXSiteStatusText()
   : m_lRefCount(0)
   , m_pSite(NULL)
   , m_pParentSite(NULL)
   , m_rgbBkgndColor(0x00008000)
   , m_rgbTextColor(0x0000FF00)
   , m_colormap(0)
   , m_display(0)
   , m_window(0)
   , m_statusfont(NULL)
{
   memset(&m_statusPos, 0, sizeof(HXxPoint));
   memset(&m_statusSize, 0, sizeof(HXxSize));
}
    
CHXSiteStatusText::~CHXSiteStatusText()
{
   Destroy(); // make sure we cleanup
}

HX_RESULT CHXSiteStatusText::Create(IHXSite* pSite)
{
   IHXSite*	pChildSite	= NULL;
   HX_RESULT 	hr		= HXR_FAIL;
    
   HX_ASSERT(pSite);
   HX_ASSERT(!m_pSite);
    
   // keep a ref while we use the parent site
   pSite->AddRef();
    
   if (pSite->CreateChild(pChildSite) == HXR_OK)
   {
      if (pChildSite->AttachUser(this) == HXR_OK)
      {
         m_pParentSite = pSite;
         if (m_StatusText.IsEmpty())
         {
            Hide(); // keep hidden until we have status text
         }
         else
         {
            Show();
         }
         UpdatePosition();
         hr = HXR_OK;
      }
      HX_RELEASE(pChildSite);
   }

   // release if we failed
   if (hr != HXR_OK)
   {
      HX_RELEASE(pSite);
   }

   return hr;
}


HX_RESULT CHXSiteStatusText::Destroy()
{
   if (m_pSite)
   {
      if (m_pParentSite)
      {
         m_pParentSite->DestroyChild(m_pSite);
      }
      // DetachUser will call DetachSite, which will release m_pSite
      m_pSite->DetachUser();
      m_pSite == NULL;
   }

   HX_RELEASE(m_pParentSite);
    
   return HXR_OK;
}
 
HX_RESULT CHXSiteStatusText::Show()
{
   IHXSite2* pSite2 = NULL;
    
   if (GetIHXSite2(pSite2) == HXR_OK)
   {
      pSite2->ShowSite(TRUE);
      HX_RELEASE(pSite2);
   }
   
   BringToTop();
   
   return HXR_OK;
}


HX_RESULT CHXSiteStatusText::Hide()
{
   IHXSite2* pSite2 = NULL;
    
   if (GetIHXSite2(pSite2) == HXR_OK)
   {
      pSite2->ShowSite(FALSE);
      HX_RELEASE(pSite2);
   }
    
   return HXR_OK;
}


HX_RESULT CHXSiteStatusText::ParentChangedSize()
{
   UpdatePosition();
   return HXR_OK;
}


HX_RESULT CHXSiteStatusText::BringToTop()
{
   IHXSite2* pSite2 = NULL;
    
   if (GetIHXSite2(pSite2) == HXR_OK)
   {
      pSite2->MoveSiteToTop();
      HX_RELEASE(pSite2);
   }
    
   return HXR_OK;
}


HX_RESULT CHXSiteStatusText::UpdatePosition()
{
   HXxPoint	parentPos;
   HXxSize	parentSize;
   HX_RESULT    res = HXR_FAIL;
    
   if (m_pParentSite && m_pSite)
   {
      if (m_pParentSite->GetSize(parentSize) == HXR_OK &&
          m_pParentSite->GetPosition(parentPos) == HXR_OK)
      {
         // call platform-specific code to adjust the position & size
         // of our site (since fonts may require different heights on
         // different platforms
         _AdjustPosition(&parentPos, &parentSize);

         m_pSite->SetPosition(m_statusPos);
         m_pSite->SetSize(m_statusSize);
    	    
         if (!m_StatusText.IsEmpty())
         {
            BringToTop();
         }
         res = HXR_OK;
      }
   }
    
   return res;
}


void CHXSiteStatusText::SetStatusText(const char* pText)
{
   m_StatusText = pText;
   if (m_StatusText.IsEmpty())
   {
      Hide();
   }
   else
   {
      Show();
   }
}

    
STDMETHODIMP CHXSiteStatusText::QueryInterface(REFIID riid, void** ppvObj)
{
   if (riid == IID_IHXSiteUser)
   {
      *ppvObj = (IHXSiteUser*)this;
      AddRef();
      return HXR_OK;
   }
   if (riid == IID_IHXSiteWatcher)
   {
      *ppvObj = (IHXSiteWatcher*)this;
      AddRef();
      return HXR_OK;
   }
   else if (riid == IID_IUnknown)
   {
      *ppvObj = (IUnknown*)(IHXSiteUser*)this;
      AddRef();
      return HXR_OK;
   }
    
   return HXR_FAIL;
}


STDMETHODIMP_(ULONG32) CHXSiteStatusText::AddRef()
{
   return InterlockedIncrement(&m_lRefCount);
}


STDMETHODIMP_(ULONG32) CHXSiteStatusText::Release()
{
   if (InterlockedDecrement(&m_lRefCount) > 0)
   {
      return m_lRefCount;
   }
    
   delete this;
   return 0;
}

STDMETHODIMP CHXSiteStatusText::AttachSite(IHXSite*	/*IN*/ pSite)
{
   HX_RESULT hr = HXR_FAIL;
    
   if (!m_pSite)
   {
      m_pSite = pSite;
      m_pSite->AddRef();
      hr = HXR_OK;
   }
    
   return hr;
}


STDMETHODIMP CHXSiteStatusText::DetachSite()
{
   HX_RESULT hr = HXR_FAIL;
    
   if (m_pSite)
   {
      HX_RELEASE(m_pSite);
      hr = HXR_OK;
   }
    
   return hr;
}


STDMETHODIMP CHXSiteStatusText::HandleEvent(HXxEvent*	/*IN*/ pEvent)
{
   HX_RESULT hr = HXR_OK;
    
   if (pEvent->event == HX_SURFACE_UPDATE)
   {
      _DrawStatusText(pEvent);
   }
    
   return hr;
}


STDMETHODIMP_(BOOL) CHXSiteStatusText::NeedsWindowedSites()
{
   return false;
}


HX_RESULT CHXSiteStatusText::GetIHXSite2(REF(IHXSite2*) pSite2)
{
   HX_RESULT hr = HXR_FAIL;
    
   if (m_pSite)
   {
      hr = m_pSite->QueryInterface(IID_IHXSite2, (void**)&pSite2);
   }
    
   return hr;
}


HX_RESULT CHXSiteStatusText::_DrawStatusText(HXxEvent* pEvent)
{
   HX_RESULT hr = HXR_OK;
   HX_ASSERT(pEvent); 

   int         direction;
   int         ascent;
   int         descent;
   XCharStruct overall;

   if (!m_pSite || m_statusSize.cx == 0)
   {
      return HXR_UNEXPECTED;
   }


   // if this is the first time in we should populate our data now
   if (m_display == NULL)
   {
      // first get the site's window
      IHXSiteWindowed* pSiteW = NULL;
      HX_VERIFY(HXR_OK == m_pSite->QueryInterface(IID_IHXSiteWindowed, (void**)&pSiteW));
	
      HXxWindow* pWindow  = pSiteW->GetWindow();
      m_window = (Window) pWindow->window;
      m_display = (Display*) pWindow->display;

      int screenNumber = DefaultScreen(m_display);
      m_colormap = DefaultColormap(m_display, screenNumber);

      m_statusfont = XLoadQueryFont(m_display, "-adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*");

      HX_RELEASE(pSiteW);
   }

   // create the GC 
   GC gc = XCreateGC(m_display, m_window, 0, 0);

   // get the GC values we will need 
   unsigned long mask = GCForeground | GCBackground | GCClipXOrigin | GCClipYOrigin;
   XGCValues gcValues;
   memset(&gcValues, 0, sizeof(XGCValues));
   int r = XGetGCValues(m_display, gc, mask, &gcValues);

   // save off the color pixel values
   Pixel saveBG = gcValues.background;
   Pixel saveFG = gcValues.foreground;

   // convert color to Pixel values
   XColor bgXColor, fgXColor;
   ConvertRGBToXColor(m_rgbBkgndColor, bgXColor);
   ConvertRGBToXColor(m_rgbTextColor, fgXColor);

   // get color
   if (!XAllocColor(m_display, m_colormap, &bgXColor))
   {
      // default to first color (is this really enough?)
      bgXColor.pixel = 1;
   }

   if (!XAllocColor(m_display, m_colormap, &fgXColor))
   {
      // default to first color (is this really enough?)
      fgXColor.pixel = 1;
   }

   // get the size of our region
   HXxSize sz;
   m_pSite->GetSize(sz);

   // keep a local copy of status text in case we need to add an elipsis
   CHXString statusText = m_StatusText;
   int nStrLen = statusText.GetLength();
   char* pStr = statusText.GetBuffer(statusText.GetLength()+1);

   // get size of elipsis
   XTextExtents(m_statusfont, ELIPSIS, strlen(ELIPSIS), &direction, &ascent, &descent, &overall);
   int nElipsisLen = (overall.lbearing + overall.rbearing);

   XTextExtents(m_statusfont, pStr, nStrLen, &direction, &ascent, &descent, &overall);
   int nWidth = (overall.lbearing + overall.rbearing);

   while (nWidth > m_statusSize.cx - DEF_HORZ_GUTTER && nStrLen > 0)
   {
      nStrLen--;
      XTextExtents(m_statusfont, pStr, nStrLen, &direction, &ascent, &descent, &overall);
      nWidth = (overall.lbearing + overall.rbearing);
   }

   if (nStrLen < statusText.GetLength())
   {
      statusText = statusText.Left(nStrLen);
      statusText += ELIPSIS;
      nStrLen += ELIPSIS_LEN;
   }
    
   int nHeight = (int)((double)DEF_TEXT_HEIGHT * POINTS_TO_PIXELS);
   int nX = max(0, (m_statusSize.cx - nWidth) / 2);
   int nY = ((int)((double)m_statusSize.cy / 2 + (double)DEF_TEXT_HEIGHT/ 2)) + m_statusPos.y;

   // set our colors into the gc
   XSetBackground(m_display, gc, fgXColor.pixel);
   XSetForeground(m_display, gc, bgXColor.pixel);

   // fill first then draw text
   XFillRectangle(m_display, m_window, gc, 
                  m_statusPos.x, 
                  m_statusPos.y,
                  m_statusSize.cx,
                  m_statusSize.cy);

   XSetBackground(m_display, gc, bgXColor.pixel);
   XSetForeground(m_display, gc, fgXColor.pixel);

   // draw string
   XDrawImageString(m_display, m_window, gc, nX, nY, (const char*) statusText, statusText.GetLength());

   // reset orig. colors
   XSetBackground(m_display, gc, saveBG);
   XSetForeground(m_display, gc, saveFG);

   // clean up colors
   unsigned long pixels[2];
   pixels[0] = bgXColor.pixel;
   pixels[1] = fgXColor.pixel;
   XFreeColors(m_display, m_colormap, pixels, 2, 0);

   // release GC
   XFreeGC(m_display, gc);

   return hr;
}

BOOL CHXSiteStatusText::ConvertRGBToXColor(HXxColor& hxxColor, XColor& xcolor)
{
   // assume starting with a new XColor
   memset(&xcolor, 0, sizeof(XColor));
    
    // separate r,g and b
   UINT16 t;
   t = (hxxColor & 0x00ff0000) >> 16;
   xcolor.blue   = t << 8;
    
   t = (hxxColor & 0x0000ff00) >> 8;
   xcolor.green = t << 8;
    
   t = (hxxColor & 0x000000ff);
   xcolor.red  = t << 8;
    
   //color.pixel = n;
   xcolor.flags = DoRed | DoGreen | DoBlue;

   return TRUE;
}

HX_RESULT CHXSiteStatusText::_AdjustPosition(HXxPoint* pParentPos, HXxSize* pParentSize)
{
   HX_RESULT hr = HXR_OK;
   
   // this function is called internally and these will never be null
   HX_ASSERT(pParentPos && pParentSize);

   // take the max width of the parent site
   m_statusPos.x = 0;
   m_statusSize.cx = pParentSize->cx;
    
   // take at most the bottom DEF_STAT_HEIGHT pixels of the parent site
   m_statusPos.y = max(pParentSize->cy - DEF_STAT_HEIGHT, 0);
   m_statusSize.cy = pParentSize->cy - m_statusPos.y;
    
   return hr;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -