📄 sitetext.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 + -