913 lines
24 KiB
C++
913 lines
24 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||
*
|
||
* The contents of this file are subject to the Netscape Public
|
||
* License Version 1.1 (the "License"); you may not use this file
|
||
* except in compliance with the License. You may obtain a copy of
|
||
* the License at http://www.mozilla.org/NPL/
|
||
*
|
||
* Software distributed under the License is distributed on an "AS
|
||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||
* implied. See the License for the specific language governing
|
||
* rights and limitations under the License.
|
||
*
|
||
* The Original Code is mozilla.org code.
|
||
*
|
||
* The Initial Developer of the Original Code is Netscape
|
||
* Communications Corporation. Portions created by Netscape are
|
||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||
* Rights Reserved.
|
||
*
|
||
* Contributor(s):
|
||
*/
|
||
|
||
#include "nsDeviceContextMac.h"
|
||
#include "nsRenderingContextMac.h"
|
||
#include "nsDeviceContextSpecMac.h"
|
||
#include "nsString.h"
|
||
#include "nsHashtable.h"
|
||
#include <TextEncodingConverter.h>
|
||
#include <TextCommon.h>
|
||
#include <StringCompare.h>
|
||
#include <Fonts.h>
|
||
#include <Resources.h>
|
||
#include <MacWindows.h>
|
||
#include "il_util.h"
|
||
#include <FixMath.h>
|
||
#include "nsIPref.h"
|
||
#include "nsIServiceManager.h"
|
||
#include "nsQuickSort.h"
|
||
#include "nsUnicodeMappingUtil.h"
|
||
|
||
|
||
PRUint32 nsDeviceContextMac::mPixelsPerInch = 96;
|
||
PRBool nsDeviceContextMac::mDisplayVerySmallFonts = true;
|
||
|
||
|
||
static NS_DEFINE_IID(kDeviceContextIID, NS_IDEVICE_CONTEXT_IID);
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
nsDeviceContextMac :: nsDeviceContextMac()
|
||
{
|
||
|
||
NS_INIT_REFCNT();
|
||
mSpec = nsnull;
|
||
|
||
}
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
nsDeviceContextMac :: ~nsDeviceContextMac()
|
||
{
|
||
}
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
NS_IMPL_QUERY_INTERFACE(nsDeviceContextMac, kDeviceContextIID);
|
||
NS_IMPL_ADDREF(nsDeviceContextMac);
|
||
NS_IMPL_RELEASE(nsDeviceContextMac);
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac :: Init(nsNativeWidget aNativeWidget)
|
||
{
|
||
GDHandle thegd;
|
||
PixMapHandle thepix;
|
||
double pix_inch;
|
||
|
||
// this is a windowptr, or grafptr, native to macintosh only
|
||
mSurface = aNativeWidget;
|
||
|
||
// get depth and resolution
|
||
thegd = ::GetMainDevice();
|
||
thepix = (**thegd).gdPMap; // dereferenced handle: don't move memory below!
|
||
mDepth = (**thepix).pixelSize;
|
||
pix_inch = GetScreenResolution(); //Fix2X((**thepix).hRes);
|
||
mTwipsToPixels = pix_inch/(float)NSIntPointsToTwips(72);
|
||
mPixelsToTwips = 1.0f/mTwipsToPixels;
|
||
|
||
return DeviceContextImpl::Init(aNativeWidget);
|
||
}
|
||
|
||
|
||
/** ---------------------------------------------------
|
||
* See documentation in nsIDeviceContext.h
|
||
* @update 12/9/98 dwc
|
||
*/
|
||
NS_IMETHODIMP nsDeviceContextMac :: CreateRenderingContext(nsIRenderingContext *&aContext)
|
||
{
|
||
nsRenderingContextMac *pContext;
|
||
nsresult rv;
|
||
GrafPtr thePort;
|
||
|
||
pContext = new nsRenderingContextMac();
|
||
if (nsnull != pContext){
|
||
NS_ADDREF(pContext);
|
||
|
||
::GetPort(&thePort);
|
||
|
||
if (nsnull != thePort){
|
||
rv = pContext->Init(this,thePort);
|
||
}
|
||
else
|
||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||
}
|
||
else
|
||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||
|
||
if (NS_OK != rv){
|
||
NS_IF_RELEASE(pContext);
|
||
}
|
||
aContext = pContext;
|
||
return rv;
|
||
}
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac :: SupportsNativeWidgets(PRBool &aSupportsWidgets)
|
||
{
|
||
//XXX it is very critical that this not lie!! MMP
|
||
|
||
// <20><><EFBFBD> VERY IMPORTANT (pinkerton)
|
||
// This routine should return true if the widgets behave like Win32
|
||
// "windows", that is they paint themselves and the app never knows about
|
||
// them or has to send them update events. We were returning false which
|
||
// meant that raptor needed to make sure to redraw them. However, if we
|
||
// return false, the widgets never get created because the CreateWidget()
|
||
// call in nsView never creates the widget. If we return true (which makes
|
||
// things work), we are lying because the controls really need those
|
||
// precious update/repaint events.
|
||
//
|
||
// The situation we need is the following:
|
||
// - return false from SupportsNativeWidgets()
|
||
// - Create() is called on widgets when the above case is true.
|
||
//
|
||
// Raptor currently doesn't work this way and needs to be fixed.
|
||
// (please remove this comment when this situation is rectified)
|
||
|
||
//if (nsnull == mSurface)
|
||
aSupportsWidgets = PR_TRUE;
|
||
//else
|
||
//aSupportsWidgets = PR_FALSE;
|
||
|
||
return NS_OK;
|
||
}
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac :: GetScrollBarDimensions(float &aWidth, float &aHeight) const
|
||
{
|
||
// XXX Should we push this to widget library
|
||
aWidth = 16 * mDevUnitsToAppUnits;
|
||
aHeight = 16 * mDevUnitsToAppUnits;
|
||
return NS_OK;
|
||
}
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac :: GetSystemAttribute(nsSystemAttrID anID, SystemAttrStruct * aInfo) const
|
||
{
|
||
nsresult status = NS_OK;
|
||
|
||
switch (anID) {
|
||
//---------
|
||
// Colors
|
||
//---------
|
||
case eSystemAttr_Color_WindowBackground:
|
||
*aInfo->mColor = NS_RGB(0xdd,0xdd,0xdd);
|
||
break;
|
||
case eSystemAttr_Color_WindowForeground:
|
||
*aInfo->mColor = NS_RGB(0x00,0x00,0x00);
|
||
break;
|
||
case eSystemAttr_Color_WidgetBackground:
|
||
*aInfo->mColor = NS_RGB(0xdd,0xdd,0xdd);
|
||
break;
|
||
case eSystemAttr_Color_WidgetForeground:
|
||
*aInfo->mColor = NS_RGB(0x00,0x00,0x00);
|
||
break;
|
||
case eSystemAttr_Color_WidgetSelectBackground:
|
||
*aInfo->mColor = NS_RGB(0x80,0x80,0x80);
|
||
break;
|
||
case eSystemAttr_Color_WidgetSelectForeground:
|
||
*aInfo->mColor = NS_RGB(0x00,0x00,0x80);
|
||
break;
|
||
case eSystemAttr_Color_Widget3DHighlight:
|
||
*aInfo->mColor = NS_RGB(0xa0,0xa0,0xa0);
|
||
break;
|
||
case eSystemAttr_Color_Widget3DShadow:
|
||
*aInfo->mColor = NS_RGB(0x40,0x40,0x40);
|
||
break;
|
||
case eSystemAttr_Color_TextBackground:
|
||
*aInfo->mColor = NS_RGB(0xff,0xff,0xff);
|
||
break;
|
||
case eSystemAttr_Color_TextForeground:
|
||
*aInfo->mColor = NS_RGB(0x00,0x00,0x00);
|
||
break;
|
||
case eSystemAttr_Color_TextSelectBackground:
|
||
*aInfo->mColor = NS_RGB(0x00,0x00,0x80);
|
||
break;
|
||
case eSystemAttr_Color_TextSelectForeground:
|
||
*aInfo->mColor = NS_RGB(0xff,0xff,0xff);
|
||
break;
|
||
|
||
//---------
|
||
// Size
|
||
//---------
|
||
case eSystemAttr_Size_ScrollbarHeight :
|
||
aInfo->mSize = 16; //21;
|
||
break;
|
||
case eSystemAttr_Size_ScrollbarWidth :
|
||
aInfo->mSize = 16; //21;
|
||
break;
|
||
case eSystemAttr_Size_WindowTitleHeight:
|
||
aInfo->mSize = 0;
|
||
break;
|
||
case eSystemAttr_Size_WindowBorderWidth:
|
||
aInfo->mSize = 4;
|
||
break;
|
||
case eSystemAttr_Size_WindowBorderHeight:
|
||
aInfo->mSize = 4;
|
||
break;
|
||
case eSystemAttr_Size_Widget3DBorder:
|
||
aInfo->mSize = 4;
|
||
break;
|
||
|
||
//---------
|
||
// Fonts
|
||
//---------
|
||
case eSystemAttr_Font_Caption :
|
||
case eSystemAttr_Font_Icon :
|
||
case eSystemAttr_Font_Menu :
|
||
case eSystemAttr_Font_MessageBox :
|
||
case eSystemAttr_Font_SmallCaption :
|
||
case eSystemAttr_Font_StatusBar :
|
||
case eSystemAttr_Font_Tooltips :
|
||
status = NS_ERROR_FAILURE;
|
||
break;
|
||
|
||
} // switch
|
||
|
||
return NS_OK;
|
||
}
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac :: GetDrawingSurface(nsIRenderingContext &aContext, nsDrawingSurface &aSurface)
|
||
{
|
||
aContext.CreateDrawingSurface(nsnull, 0, aSurface);
|
||
return nsnull == aSurface ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
|
||
}
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac::GetDepth(PRUint32& aDepth)
|
||
{
|
||
aDepth = mDepth;
|
||
return NS_OK;
|
||
}
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac :: ConvertPixel(nscolor aColor, PRUint32 & aPixel)
|
||
{
|
||
aPixel = aColor;
|
||
return NS_OK;
|
||
}
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac::CreateILColorSpace(IL_ColorSpace*& aColorSpace)
|
||
{
|
||
nsresult result = NS_OK;
|
||
|
||
|
||
return result;
|
||
}
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac::GetILColorSpace(IL_ColorSpace*& aColorSpace)
|
||
{
|
||
|
||
if (nsnull == mColorSpace) {
|
||
IL_RGBBits colorRGBBits;
|
||
|
||
// Default is to create a 32-bit color space
|
||
colorRGBBits.red_shift = 16;
|
||
colorRGBBits.red_bits = 8;
|
||
colorRGBBits.green_shift = 8;
|
||
colorRGBBits.green_bits = 8;
|
||
colorRGBBits.blue_shift = 0;
|
||
colorRGBBits.blue_bits = 8;
|
||
|
||
mColorSpace = IL_CreateTrueColorSpace(&colorRGBBits, 32);
|
||
if (nsnull == mColorSpace) {
|
||
aColorSpace = nsnull;
|
||
return NS_ERROR_OUT_OF_MEMORY;
|
||
}
|
||
}
|
||
|
||
NS_POSTCONDITION(nsnull != mColorSpace, "null color space");
|
||
aColorSpace = mColorSpace;
|
||
IL_AddRefToColorSpace(aColorSpace);
|
||
return NS_OK;
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac :: CheckFontExistence(const nsString& aFontName)
|
||
{
|
||
short fontNum;
|
||
if (GetMacFontNumber(aFontName, fontNum))
|
||
return NS_OK;
|
||
else
|
||
return NS_ERROR_FAILURE;
|
||
}
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac::GetDeviceSurfaceDimensions(PRInt32 &aWidth, PRInt32 &aHeight)
|
||
{
|
||
// FIXME: could just union all of the GDevice rectangles together.
|
||
RgnHandle grayRgn = ::GetGrayRgn();
|
||
Rect bounds = (**grayRgn).rgnBBox;
|
||
//aWidth = bounds.right - bounds.left;
|
||
//aHeight = bounds.bottom - bounds.top;
|
||
|
||
aHeight = NSToIntRound((bounds.bottom - bounds.top)*mDevUnitsToAppUnits);
|
||
aWidth = NSToIntRound((bounds.right - bounds.left) * mDevUnitsToAppUnits);
|
||
|
||
return NS_OK;
|
||
}
|
||
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac::GetClientRect(nsRect &aRect)
|
||
{
|
||
// FIXME: equally as broken as GetDeviceSurfaceDimensions,
|
||
// this doesn't do what you want with multiple screens.
|
||
RgnHandle grayRgn = ::GetGrayRgn();
|
||
Rect bounds = (**grayRgn).rgnBBox;
|
||
|
||
aRect.x = NSToIntRound(bounds.left * mDevUnitsToAppUnits);
|
||
aRect.y = NSToIntRound(bounds.top * mDevUnitsToAppUnits);
|
||
aRect.width = NSToIntRound((bounds.right - bounds.left) * mDevUnitsToAppUnits);
|
||
aRect.height = NSToIntRound((bounds.bottom - bounds.top) * mDevUnitsToAppUnits);
|
||
|
||
return NS_OK;
|
||
}
|
||
|
||
#pragma mark -
|
||
//------------------------------------------------------------------------
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac::GetDeviceContextFor(nsIDeviceContextSpec *aDevice,nsIDeviceContext *&aContext)
|
||
{
|
||
GrafPtr curPort;
|
||
double pix_Inch;
|
||
THPrint thePrintRecord; // handle to print record
|
||
|
||
aContext = new nsDeviceContextMac();
|
||
((nsDeviceContextMac*)aContext)->mSpec = aDevice;
|
||
NS_ADDREF(aDevice);
|
||
|
||
::GetPort(&curPort);
|
||
|
||
thePrintRecord = ((nsDeviceContextSpecMac*)aDevice)->mPrtRec;
|
||
pix_Inch = (**thePrintRecord).prInfo.iHRes;
|
||
|
||
((nsDeviceContextMac*)aContext)->Init(curPort);
|
||
|
||
((nsDeviceContextMac*)aContext)->mPageRect = (**thePrintRecord).prInfo.rPage;
|
||
((nsDeviceContextMac*)aContext)->mTwipsToPixels = pix_Inch/(float)NSIntPointsToTwips(72);
|
||
((nsDeviceContextMac*)aContext)->mPixelsToTwips = 1.0f/mTwipsToPixels;
|
||
((nsDeviceContextMac*)aContext)->mAppUnitsToDevUnits = mTwipsToPixels;
|
||
((nsDeviceContextMac*)aContext)->mDevUnitsToAppUnits = 1.0f / mAppUnitsToDevUnits;
|
||
//((nsDeviceContextMac*)aContext)->Init(this);
|
||
return NS_OK;
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac::BeginDocument(void)
|
||
{
|
||
#if !TARGET_CARBON
|
||
GrafPtr thePort;
|
||
|
||
if(((nsDeviceContextSpecMac*)(this->mSpec))->mPrintManagerOpen) {
|
||
::GetPort(&mOldPort);
|
||
thePort = (GrafPtr)::PrOpenDoc(((nsDeviceContextSpecMac*)(this->mSpec))->mPrtRec,nsnull,nsnull);
|
||
((nsDeviceContextSpecMac*)(this->mSpec))->mPrinterPort = (TPrPort*)thePort;
|
||
SetDrawingSurface(((nsDeviceContextSpecMac*)(this->mSpec))->mPrtRec);
|
||
SetPort(thePort);
|
||
}
|
||
#endif
|
||
return NS_OK;
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac::EndDocument(void)
|
||
{
|
||
if(((nsDeviceContextSpecMac*)(this->mSpec))->mPrintManagerOpen){
|
||
::SetPort(mOldPort);
|
||
#if !TARGET_CARBON
|
||
::PrCloseDoc(((nsDeviceContextSpecMac*)(this->mSpec))->mPrinterPort);
|
||
#endif
|
||
}
|
||
return NS_OK;
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac::BeginPage(void)
|
||
{
|
||
#if !TARGET_CARBON
|
||
if(((nsDeviceContextSpecMac*)(this->mSpec))->mPrintManagerOpen)
|
||
::PrOpenPage(((nsDeviceContextSpecMac*)(this->mSpec))->mPrinterPort,nsnull);
|
||
#endif
|
||
return NS_OK;
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
NS_IMETHODIMP nsDeviceContextMac::EndPage(void)
|
||
{
|
||
#if !TARGET_CARBON
|
||
if(((nsDeviceContextSpecMac*)(this->mSpec))->mPrintManagerOpen) {
|
||
::SetPort((GrafPtr)(((nsDeviceContextSpecMac*)(this->mSpec))->mPrinterPort));
|
||
::PrClosePage(((nsDeviceContextSpecMac*)(this->mSpec))->mPrinterPort);
|
||
}
|
||
#endif
|
||
return NS_OK;
|
||
}
|
||
|
||
|
||
#pragma mark -
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
nsHashtable* nsDeviceContextMac :: gFontInfoList = nsnull;
|
||
|
||
class FontNameKey : public nsHashKey
|
||
{
|
||
public:
|
||
FontNameKey(const nsString& aString);
|
||
|
||
virtual PRUint32 HashValue(void) const;
|
||
virtual PRBool Equals(const nsHashKey *aKey) const;
|
||
virtual nsHashKey *Clone(void) const;
|
||
|
||
nsAutoString mString;
|
||
};
|
||
|
||
FontNameKey::FontNameKey(const nsString& aString)
|
||
{
|
||
mString = aString;
|
||
}
|
||
|
||
PRUint32 FontNameKey::HashValue(void) const
|
||
{
|
||
nsString str;
|
||
mString.ToLowerCase(str);
|
||
return nsCRT::HashValue(str.GetUnicode());
|
||
}
|
||
|
||
PRBool FontNameKey::Equals(const nsHashKey *aKey) const
|
||
{
|
||
return mString.EqualsIgnoreCase(((FontNameKey*)aKey)->mString);
|
||
}
|
||
|
||
nsHashKey* FontNameKey::Clone(void) const
|
||
{
|
||
return new FontNameKey(mString);
|
||
}
|
||
|
||
#pragma mark -
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
void nsDeviceContextMac :: InitFontInfoList()
|
||
{
|
||
|
||
OSStatus err;
|
||
if (!gFontInfoList)
|
||
{
|
||
gFontInfoList = new nsHashtable();
|
||
if (!gFontInfoList)
|
||
return;
|
||
|
||
short numFONDs = ::CountResources('FOND');
|
||
#if !TARGET_CARBON
|
||
TextEncoding unicodeEncoding = ::CreateTextEncoding(kTextEncodingUnicodeDefault,
|
||
kTextEncodingDefaultVariant,
|
||
kTextEncodingDefaultFormat);
|
||
#endif
|
||
TECObjectRef converter = nil;
|
||
ScriptCode lastscript = smUninterp;
|
||
for (short i = 1; i <= numFONDs ; i++)
|
||
{
|
||
Handle fond = ::GetIndResource('FOND', i);
|
||
if (fond)
|
||
{
|
||
short fondID;
|
||
OSType resType;
|
||
Str255 fontName;
|
||
::GetResInfo(fond, &fondID, &resType, fontName);
|
||
|
||
#if !TARGET_CARBON
|
||
ScriptCode script = ::FontToScript(fondID);
|
||
if (script != lastscript)
|
||
{
|
||
lastscript = script;
|
||
|
||
TextEncoding sourceEncoding;
|
||
err = ::UpgradeScriptInfoToTextEncoding(script, kTextLanguageDontCare,
|
||
kTextRegionDontCare, NULL, &sourceEncoding);
|
||
|
||
if (converter)
|
||
err = ::TECDisposeConverter(converter);
|
||
|
||
err = ::TECCreateConverter(&converter, sourceEncoding, unicodeEncoding);
|
||
if (err != noErr)
|
||
converter = nil;
|
||
}
|
||
|
||
if (converter)
|
||
{
|
||
PRUnichar unicodeFontName[sizeof(fontName)];
|
||
ByteCount actualInputLength, actualOutputLength;
|
||
err = ::TECConvertText(converter, &fontName[1], fontName[0], &actualInputLength,
|
||
(TextPtr)unicodeFontName , sizeof(unicodeFontName), &actualOutputLength);
|
||
unicodeFontName[actualOutputLength / sizeof(PRUnichar)] = '\0';
|
||
|
||
FontNameKey key(unicodeFontName);
|
||
gFontInfoList->Put(&key, (void*)fondID);
|
||
}
|
||
#else
|
||
// pinkerton - CreateTextEncoding() makes a carbon app exit. this is a smarmy hack
|
||
char buffer[500];
|
||
::BlockMoveData ( &fontName[1], buffer, *fontName );
|
||
buffer[*fontName] = NULL;
|
||
printf("font buffer is %s\n", buffer);
|
||
FontNameKey key(buffer);
|
||
gFontInfoList->Put(&key, (void*)fondID);
|
||
#endif
|
||
::ReleaseResource(fond);
|
||
}
|
||
}
|
||
if (converter)
|
||
err = ::TECDisposeConverter(converter);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
//------------------------------------------------------------------------
|
||
|
||
bool nsDeviceContextMac :: GetMacFontNumber(const nsString& aFontName, short &aFontNum)
|
||
{
|
||
//<2F>TODO?: Maybe we shouldn't call that function so often. If nsFont could store the
|
||
// fontNum, nsFontMetricsMac::SetFont() wouldn't need to call this at all.
|
||
InitFontInfoList();
|
||
#if TARGET_CARBON
|
||
char* fontNameC = aFontName.ToNewCString();
|
||
Str255 fontNamePascal;
|
||
fontNamePascal[0] = strlen(fontNameC);
|
||
::BlockMoveData ( fontNameC, &fontNamePascal[1], fontNamePascal[0] );
|
||
::GetFNum ( fontNamePascal, &aFontNum );
|
||
delete[] fontNameC;
|
||
#else
|
||
FontNameKey key(aFontName);
|
||
aFontNum = (short)gFontInfoList->Get(&key);
|
||
#endif
|
||
return (aFontNum != 0);
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------
|
||
// Override to tweak font settings
|
||
nsresult nsDeviceContextMac::CreateFontAliasTable()
|
||
{
|
||
nsresult result = NS_OK;
|
||
|
||
if (nsnull == mFontAliasTable) {
|
||
mFontAliasTable = new nsHashtable();
|
||
if (nsnull != mFontAliasTable)
|
||
{
|
||
nsAutoString fontTimes("Times");
|
||
nsAutoString fontTimesNewRoman("Times New Roman");
|
||
nsAutoString fontTimesRoman("Times Roman");
|
||
nsAutoString fontArial("Arial");
|
||
nsAutoString fontHelvetica("Helvetica");
|
||
nsAutoString fontCourier("Courier");
|
||
nsAutoString fontCourierNew("Courier New");
|
||
nsAutoString fontUnicode("Unicode");
|
||
nsAutoString fontBitstreamCyberbit("Bitstream Cyberbit");
|
||
nsAutoString fontNullStr;
|
||
|
||
AliasFont(fontTimes, fontTimesNewRoman, fontTimesRoman, PR_FALSE);
|
||
AliasFont(fontTimesRoman, fontTimesNewRoman, fontTimes, PR_FALSE);
|
||
AliasFont(fontTimesNewRoman, fontTimesRoman, fontTimes, PR_FALSE);
|
||
AliasFont(fontArial, fontHelvetica, fontNullStr, PR_FALSE);
|
||
AliasFont(fontHelvetica, fontArial, fontNullStr, PR_FALSE);
|
||
AliasFont(fontCourier, fontCourierNew, fontNullStr, PR_FALSE); // changed from DeviceContextImpl
|
||
AliasFont(fontCourierNew, fontCourier, fontNullStr, PR_FALSE);
|
||
AliasFont(fontUnicode, fontBitstreamCyberbit, fontNullStr, PR_FALSE); // XXX ????
|
||
}
|
||
else {
|
||
result = NS_ERROR_OUT_OF_MEMORY;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
#pragma mark -
|
||
|
||
//------------------------------------------------------------------------
|
||
//
|
||
static NS_DEFINE_IID(kIPrefIID, NS_IPREF_IID);
|
||
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
|
||
|
||
PRUint32 nsDeviceContextMac::GetScreenResolution()
|
||
{
|
||
static PRBool initialized = PR_FALSE;
|
||
if (initialized)
|
||
return mPixelsPerInch;
|
||
initialized = PR_TRUE;
|
||
|
||
nsIPref* prefs;
|
||
nsresult rv = nsServiceManager::GetService(kPrefCID, kIPrefIID, (nsISupports**)&prefs);
|
||
if (NS_SUCCEEDED(rv) && prefs) {
|
||
PRInt32 intVal;
|
||
if (NS_SUCCEEDED(prefs->GetIntPref("browser.screen_resolution", &intVal))) {
|
||
mPixelsPerInch = intVal;
|
||
}
|
||
#if 0
|
||
else {
|
||
short hppi, vppi;
|
||
::ScreenRes(&hppi, &vppi);
|
||
mPixelsPerInch = hppi * 1.17f;
|
||
}
|
||
#endif
|
||
nsServiceManager::ReleaseService(kPrefCID, prefs);
|
||
}
|
||
|
||
return mPixelsPerInch;
|
||
}
|
||
|
||
PRBool nsDeviceContextMac::DisplayVerySmallFonts()
|
||
{
|
||
static PRBool initialized = PR_FALSE;
|
||
if (initialized)
|
||
return mDisplayVerySmallFonts;
|
||
initialized = PR_TRUE;
|
||
|
||
nsIPref* prefs;
|
||
nsresult rv = nsServiceManager::GetService(kPrefCID, kIPrefIID, (nsISupports**)&prefs);
|
||
if (NS_SUCCEEDED(rv) && prefs) {
|
||
PRBool boolVal;
|
||
if (NS_SUCCEEDED(prefs->GetBoolPref("browser.display_very_small_fonts", &boolVal))) {
|
||
mDisplayVerySmallFonts = boolVal;
|
||
}
|
||
nsServiceManager::ReleaseService(kPrefCID, prefs);
|
||
}
|
||
|
||
return mDisplayVerySmallFonts;
|
||
}
|
||
|
||
|
||
#pragma mark -
|
||
//------------------------------------------------------------------------
|
||
nsFontEnumeratorMac::nsFontEnumeratorMac()
|
||
{
|
||
NS_INIT_REFCNT();
|
||
}
|
||
|
||
NS_IMPL_ISUPPORTS(nsFontEnumeratorMac,
|
||
nsCOMTypeInfo<nsIFontEnumerator>::GetIID());
|
||
typedef struct EnumerateFamilyInfo
|
||
{
|
||
PRUnichar** mArray;
|
||
int mIndex;
|
||
} EnumerateFamilyInfo;
|
||
|
||
typedef struct EnumerateFontInfo
|
||
{
|
||
PRUnichar** mArray;
|
||
int mIndex;
|
||
int mCount;
|
||
ScriptCode mScript;
|
||
nsGenericFontNameType mType;
|
||
} EnumerateFontInfo;
|
||
|
||
|
||
|
||
static ScriptCode MapLangGroupToScriptCode(const char* aLangGroup)
|
||
{
|
||
if(0==nsCRT::strcmp(aLangGroup, "x-western")) {
|
||
return smRoman;
|
||
} else
|
||
if(0==nsCRT::strcmp(aLangGroup, "x-central-euro")) {
|
||
return smCentralEuroRoman;
|
||
} else
|
||
if(0==nsCRT::strcmp(aLangGroup, "x-cyrillic")) {
|
||
return smCyrillic;
|
||
} else
|
||
if(0==nsCRT::strcmp(aLangGroup, "el")) {
|
||
return smGreek;
|
||
} else
|
||
if(0==nsCRT::strcmp(aLangGroup, "tr")) {
|
||
return smRoman;
|
||
} else
|
||
if(0==nsCRT::strcmp(aLangGroup, "he")) {
|
||
return smHebrew;
|
||
} else
|
||
if(0==nsCRT::strcmp(aLangGroup, "ar")) {
|
||
return smArabic;
|
||
} else
|
||
if(0==nsCRT::strcmp(aLangGroup, "x-baltic")) {
|
||
return smRoman;
|
||
} else
|
||
if(0==nsCRT::strcmp(aLangGroup, "th")) {
|
||
return smThai;
|
||
} else
|
||
if(0==nsCRT::strcmp(aLangGroup, "ja")) {
|
||
return smJapanese;
|
||
} else
|
||
if(0==nsCRT::strcmp(aLangGroup, "zh-CN")) {
|
||
return smSimpChinese;
|
||
} else
|
||
if(0==nsCRT::strcmp(aLangGroup, "ko")) {
|
||
return smKorean;
|
||
} else
|
||
if(0==nsCRT::strcmp(aLangGroup, "zh-TW")) {
|
||
return smTradChinese;
|
||
} else
|
||
{
|
||
return smRoman;
|
||
}
|
||
}
|
||
static int
|
||
CompareFontNames(const void* aArg1, const void* aArg2, void* aClosure)
|
||
{
|
||
const PRUnichar* str1 = *((const PRUnichar**) aArg1);
|
||
const PRUnichar* str2 = *((const PRUnichar**) aArg2);
|
||
|
||
// XXX add nsICollation stuff
|
||
|
||
return nsCRT::strcmp(str1, str2);
|
||
}
|
||
static PRBool
|
||
EnumerateFamily(nsHashKey *aKey, void *aData, void* closure)
|
||
|
||
{
|
||
EnumerateFamilyInfo* info = (EnumerateFamilyInfo*) closure;
|
||
PRUnichar** array = info->mArray;
|
||
int j = info->mIndex;
|
||
|
||
|
||
PRUnichar* str = (((FontNameKey*)aKey)->mString).ToNewUnicode();
|
||
if (!str) {
|
||
for (j = j - 1; j >= 0; j--) {
|
||
nsAllocator::Free(array[j]);
|
||
}
|
||
info->mIndex = 0;
|
||
return PR_FALSE;
|
||
}
|
||
array[j] = str;
|
||
info->mIndex++;
|
||
|
||
return PR_TRUE;
|
||
}
|
||
|
||
NS_IMETHODIMP
|
||
nsFontEnumeratorMac::EnumerateAllFonts(PRUint32* aCount, PRUnichar*** aResult)
|
||
{
|
||
if (aCount) {
|
||
*aCount = 0;
|
||
}
|
||
else {
|
||
return NS_ERROR_NULL_POINTER;
|
||
}
|
||
if (aResult) {
|
||
*aResult = nsnull;
|
||
}
|
||
else {
|
||
return NS_ERROR_NULL_POINTER;
|
||
}
|
||
|
||
nsDeviceContextMac::InitFontInfoList();
|
||
nsHashtable* list = nsDeviceContextMac::gFontInfoList;
|
||
if(!list) {
|
||
return NS_ERROR_FAILURE;
|
||
}
|
||
PRInt32 items = list->Count();
|
||
PRUnichar** array = (PRUnichar**)
|
||
nsAllocator::Alloc(items * sizeof(PRUnichar*));
|
||
if (!array) {
|
||
return NS_ERROR_OUT_OF_MEMORY;
|
||
}
|
||
EnumerateFamilyInfo info = { array, 0 };
|
||
list->Enumerate ( EnumerateFamily, &info);
|
||
NS_ASSERTION( items == info.mIndex, "didn't get all the fonts");
|
||
if (!info.mIndex) {
|
||
nsAllocator::Free(array);
|
||
return NS_ERROR_OUT_OF_MEMORY;
|
||
}
|
||
|
||
NS_QuickSort(array, info.mIndex, sizeof(PRUnichar*),
|
||
CompareFontNames, nsnull);
|
||
|
||
*aCount = info.mIndex;
|
||
*aResult = array;
|
||
|
||
return NS_OK;
|
||
}
|
||
|
||
static PRBool
|
||
EnumerateFont(nsHashKey *aKey, void *aData, void* closure)
|
||
|
||
{
|
||
EnumerateFontInfo* info = (EnumerateFontInfo*) closure;
|
||
PRUnichar** array = info->mArray;
|
||
int j = info->mCount;
|
||
|
||
short fondID = (short) aData;
|
||
ScriptCode script = ::FontToScript(fondID);
|
||
if(script == info->mScript) {
|
||
PRUnichar* str = (((FontNameKey*)aKey)->mString).ToNewUnicode();
|
||
if (!str) {
|
||
for (j = j - 1; j >= 0; j--) {
|
||
nsAllocator::Free(array[j]);
|
||
}
|
||
info->mIndex = 0;
|
||
return PR_FALSE;
|
||
}
|
||
array[j] = str;
|
||
info->mCount++;
|
||
}
|
||
info->mIndex++;
|
||
return PR_TRUE;
|
||
}
|
||
NS_IMETHODIMP
|
||
nsFontEnumeratorMac::EnumerateFonts(const char* aLangGroup,
|
||
const char* aGeneric, PRUint32* aCount, PRUnichar*** aResult)
|
||
{
|
||
if ((! aLangGroup) ||( !aGeneric ))
|
||
return NS_ERROR_NULL_POINTER;
|
||
|
||
if (aCount) {
|
||
*aCount = 0;
|
||
}
|
||
else {
|
||
return NS_ERROR_NULL_POINTER;
|
||
}
|
||
if (aResult) {
|
||
*aResult = nsnull;
|
||
}
|
||
else {
|
||
return NS_ERROR_NULL_POINTER;
|
||
}
|
||
|
||
if ((!strcmp(aLangGroup, "x-unicode")) ||
|
||
(!strcmp(aLangGroup, "x-user-def"))) {
|
||
return EnumerateAllFonts(aCount, aResult);
|
||
}
|
||
|
||
nsDeviceContextMac::InitFontInfoList();
|
||
nsHashtable* list = nsDeviceContextMac::gFontInfoList;
|
||
if(!list) {
|
||
return NS_ERROR_FAILURE;
|
||
}
|
||
PRInt32 items = list->Count();
|
||
PRUnichar** array = (PRUnichar**)
|
||
nsAllocator::Alloc(items * sizeof(PRUnichar*));
|
||
if (!array) {
|
||
return NS_ERROR_OUT_OF_MEMORY;
|
||
}
|
||
nsUnicodeMappingUtil* gUtil = nsUnicodeMappingUtil::GetSingleton();
|
||
if(!gUtil) {
|
||
return NS_ERROR_FAILURE;
|
||
}
|
||
|
||
nsAutoString GenName(aGeneric);
|
||
EnumerateFontInfo info = { array, 0 , 0, MapLangGroupToScriptCode(aLangGroup) ,gUtil->MapGenericFontNameType(GenName) };
|
||
list->Enumerate ( EnumerateFont, &info);
|
||
if (!info.mIndex) {
|
||
nsAllocator::Free(array);
|
||
return NS_ERROR_OUT_OF_MEMORY;
|
||
}
|
||
|
||
NS_QuickSort(array, info.mCount, sizeof(PRUnichar*),
|
||
CompareFontNames, nsnull);
|
||
|
||
*aCount = info.mCount;
|
||
*aResult = array;
|
||
|
||
return NS_OK;
|
||
}
|
||
|