RetroZilla/gfx/src/windows/nsDeviceContextWin.cpp

906 lines
24 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsDeviceContextWin.h"
#include "nsRenderingContextWin.h"
#include "nsDeviceContextSpecWin.h"
#include "nsIServiceManager.h"
#include "nsCOMPtr.h"
#include "nsIScreenManager.h"
#include "nsIScreen.h"
#include "nsGfxCIID.h"
#include "nsReadableUtils.h"
#include "nsString.h"
#if defined(DEBUG_rods) && defined(MOZ_LAYOUTDEBUG)
#include "nsIDebugObject.h"
#endif
#define DOC_TITLE_LENGTH 64
#include "prlog.h"
#ifdef PR_LOGGING
PRLogModuleInfo * kGfxPrintingLogMod = PR_NewLogModule("printing-gfx");
#define PR_PL(_p1) PR_LOG(kGfxPrintingLogMod, PR_LOG_DEBUG, _p1)
#else
#define PR_PL(_p1)
#endif
nsDeviceContextWin :: nsDeviceContextWin()
: DeviceContextImpl()
{
mSurface = NULL;
mPaletteInfo.isPaletteDevice = PR_FALSE;
mPaletteInfo.sizePalette = 0;
mPaletteInfo.numReserved = 0;
mPaletteInfo.palette = NULL;
mDC = NULL;
mPixelScale = 1.0f;
mWidth = -1;
mHeight = -1;
mSpec = nsnull;
mCachedClientRect = PR_FALSE;
mCachedFullRect = PR_FALSE;
}
nsDeviceContextWin :: ~nsDeviceContextWin()
{
nsDrawingSurfaceWin *surf = (nsDrawingSurfaceWin *)mSurface;
NS_IF_RELEASE(surf); //this clears the surf pointer...
mSurface = nsnull;
if (NULL != mPaletteInfo.palette)
::DeleteObject((HPALETTE)mPaletteInfo.palette);
if (NULL != mDC)
{
::DeleteDC(mDC);
mDC = NULL;
}
NS_IF_RELEASE(mSpec);
}
NS_IMETHODIMP nsDeviceContextWin :: Init(nsNativeWidget aWidget)
{
mWidget = aWidget;
HWND hwnd = (HWND)aWidget;
HDC hdc = ::GetDC(hwnd);
CommonInit(hdc);
::ReleaseDC(hwnd, hdc);
return NS_OK;
}
//local method...
nsresult nsDeviceContextWin :: Init(nsNativeDeviceContext aContext, nsIDeviceContext *aOrigContext)
{
float origscale, newscale;
float t2d, a2d;
mDC = (HDC)aContext;
CommonInit(mDC);
newscale = TwipsToDevUnits();
origscale = aOrigContext->TwipsToDevUnits();
mPixelScale = newscale / origscale;
t2d = aOrigContext->TwipsToDevUnits();
a2d = aOrigContext->AppUnitsToDevUnits();
mAppUnitsToDevUnits = (a2d / t2d) * mTwipsToPixels;
mDevUnitsToAppUnits = 1.0f / mAppUnitsToDevUnits;
return NS_OK;
}
void nsDeviceContextWin :: CommonInit(HDC aDC)
{
int rasterCaps = ::GetDeviceCaps(aDC, RASTERCAPS);
mDepth = (PRUint32)::GetDeviceCaps(aDC, BITSPIXEL);
mPaletteInfo.isPaletteDevice = RC_PALETTE == (rasterCaps & RC_PALETTE);
mPaletteInfo.sizePalette = (PRUint16)::GetDeviceCaps(aDC, SIZEPALETTE);
mPaletteInfo.numReserved = (PRUint16)::GetDeviceCaps(aDC, NUMRESERVED);
mWidth = ::GetDeviceCaps(aDC, HORZRES);
mHeight = ::GetDeviceCaps(aDC, VERTRES);
mPixelsToTwips = (float)NSIntPointsToTwips(72) / ((float)::GetDeviceCaps(aDC, LOGPIXELSY));
if (::GetDeviceCaps(aDC, TECHNOLOGY) == DT_RASDISPLAY)
{
// Ensure that, for screens, pixels-to-twips is an integer
mPixelsToTwips = NSToIntRound(mPixelsToTwips);
// init the screen manager and compute our client rect based on the
// screen objects. We'll save the result
nsresult ignore;
mScreenManager = do_GetService("@mozilla.org/gfx/screenmanager;1", &ignore);
} // if this dc is not a print device
mTwipsToPixels = 1.0 / mPixelsToTwips;
DeviceContextImpl::CommonInit();
}
void
nsDeviceContextWin :: ComputeClientRectUsingScreen ( nsRect* outRect )
{
// we always need to recompute the clientRect
// because the window may have moved onto a different screen. In the single
// monitor case, we only need to do the computation if we haven't done it
// once already, and remember that we have because we're assured it won't change.
nsCOMPtr<nsIScreen> screen;
FindScreen ( getter_AddRefs(screen) );
if ( screen ) {
PRInt32 x, y, width, height;
screen->GetAvailRect ( &x, &y, &width, &height );
// convert to device units
outRect->y = NSToIntRound(y * mDevUnitsToAppUnits);
outRect->x = NSToIntRound(x * mDevUnitsToAppUnits);
outRect->width = NSToIntRound(width * mDevUnitsToAppUnits);
outRect->height = NSToIntRound(height * mDevUnitsToAppUnits);
mCachedClientRect = PR_TRUE;
mClientRect = *outRect;
}
} // ComputeClientRectUsingScreen
void
nsDeviceContextWin :: ComputeFullAreaUsingScreen ( nsRect* outRect )
{
// if we have more than one screen, we always need to recompute the clientRect
// because the window may have moved onto a different screen. In the single
// monitor case, we only need to do the computation if we haven't done it
// once already, and remember that we have because we're assured it won't change.
nsCOMPtr<nsIScreen> screen;
FindScreen ( getter_AddRefs(screen) );
if ( screen ) {
PRInt32 x, y, width, height;
screen->GetRect ( &x, &y, &width, &height );
// convert to device units
outRect->y = NSToIntRound(y * mDevUnitsToAppUnits);
outRect->x = NSToIntRound(x * mDevUnitsToAppUnits);
outRect->width = NSToIntRound(width * mDevUnitsToAppUnits);
outRect->height = NSToIntRound(height * mDevUnitsToAppUnits);
mWidth = width;
mHeight = height;
mCachedFullRect = PR_TRUE;
}
} // ComputeFullRectUsingScreen
//
// FindScreen
//
// Determines which screen intersects the largest area of the given surface.
//
void
nsDeviceContextWin :: FindScreen ( nsIScreen** outScreen )
{
// now then, if we have more than one screen, we need to find which screen this
// window is on.
HWND window = NS_REINTERPRET_CAST(HWND, mWidget);
if ( window ) {
RECT globalPosition;
::GetWindowRect ( window, &globalPosition );
if ( mScreenManager )
mScreenManager->ScreenForRect ( globalPosition.left, globalPosition.top,
globalPosition.right - globalPosition.left,
globalPosition.bottom - globalPosition.top, outScreen );
}
} // FindScreen
static NS_DEFINE_CID(kRCCID,NS_RENDERING_CONTEXT_CID);
NS_IMETHODIMP nsDeviceContextWin :: CreateRenderingContext(nsIRenderingContext *&aContext)
{
#ifdef NS_PRINT_PREVIEW
// Defer to Alt when there is one
if (mAltDC && ((mUseAltDC & kUseAltDCFor_CREATERC_PAINT) || (mUseAltDC & kUseAltDCFor_CREATERC_REFLOW))) {
return mAltDC->CreateRenderingContext(aContext);
}
#endif
nsIRenderingContext *pContext;
nsresult rv;
nsDrawingSurfaceWin *surf;
rv = CallCreateInstance(kRCCID, &pContext);
if ( (NS_SUCCEEDED(rv)) && (nsnull != pContext))
{
surf = new nsDrawingSurfaceWin();
if (nsnull != surf)
{
rv = surf->Init(mDC);
if (NS_OK == rv)
rv = pContext->Init(this, surf);
}
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 nsDeviceContextWin :: SupportsNativeWidgets(PRBool &aSupportsWidgets)
{
if (nsnull == mDC)
aSupportsWidgets = PR_TRUE;
else
aSupportsWidgets = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP nsDeviceContextWin :: GetCanonicalPixelScale(float &aScale) const
{
aScale = mPixelScale;
return NS_OK;
}
NS_IMETHODIMP nsDeviceContextWin :: SetCanonicalPixelScale(float aScale)
{
DeviceContextImpl::SetCanonicalPixelScale(aScale);
mPixelScale = aScale;
return NS_OK;
}
NS_IMETHODIMP nsDeviceContextWin :: GetScrollBarDimensions(float &aWidth, float &aHeight) const
{
float scale;
GetCanonicalPixelScale(scale);
aWidth = ::GetSystemMetrics(SM_CXVSCROLL) * mDevUnitsToAppUnits * scale;
aHeight = ::GetSystemMetrics(SM_CXHSCROLL) * mDevUnitsToAppUnits * scale;
return NS_OK;
}
nsresult nsDeviceContextWin::CopyLogFontToNSFont(HDC* aHDC, const LOGFONT* ptrLogFont,
nsFont* aFont, PRBool aIsWide) const
{
PRUnichar name[LF_FACESIZE];
name[0] = 0;
if (aIsWide)
memcpy(name, ptrLogFont->lfFaceName, LF_FACESIZE*2);
else {
MultiByteToWideChar(CP_ACP, 0, ptrLogFont->lfFaceName,
strlen(ptrLogFont->lfFaceName) + 1, name, sizeof(name)/sizeof(name[0]));
}
aFont->name = name;
// Do Style
aFont->style = NS_FONT_STYLE_NORMAL;
if (ptrLogFont->lfItalic)
{
aFont->style = NS_FONT_STYLE_ITALIC;
}
// XXX What about oblique?
aFont->variant = NS_FONT_VARIANT_NORMAL;
// Do Weight
aFont->weight = (ptrLogFont->lfWeight == FW_BOLD ?
NS_FONT_WEIGHT_BOLD : NS_FONT_WEIGHT_NORMAL);
// Do decorations
aFont->decorations = NS_FONT_DECORATION_NONE;
if (ptrLogFont->lfUnderline)
{
aFont->decorations |= NS_FONT_DECORATION_UNDERLINE;
}
if (ptrLogFont->lfStrikeOut)
{
aFont->decorations |= NS_FONT_DECORATION_LINE_THROUGH;
}
// Do Point Size
//
// The lfHeight is in pixel and it needs to be adjusted for the
// device it will be "displayed" on
// Screens and Printers will differe in DPI
//
// So this accounts for the difference in the DeviceContexts
// The mPixelScale will be a "1" for the screen and could be
// any value when going to a printer, for example mPixleScale is
// 6.25 when going to a 600dpi printer.
// round, but take into account whether it is negative
float pixelHeight = -ptrLogFont->lfHeight;
if (pixelHeight < 0) {
HFONT hFont = ::CreateFontIndirect(ptrLogFont);
if (!hFont)
return NS_ERROR_OUT_OF_MEMORY;
HGDIOBJ hObject = ::SelectObject(*aHDC, hFont);
TEXTMETRIC tm;
::GetTextMetrics(*aHDC, &tm);
::SelectObject(*aHDC, hObject);
::DeleteObject(hFont);
pixelHeight = tm.tmAscent;
}
float pointSize = pixelHeight * mPixelScale * 72 / ::GetDeviceCaps(*aHDC, LOGPIXELSY);
// we have problem on Simplified Chinese system because the system report
// the default font size is 8. but if we use 8, the text display very
// Ugly. force it to be at 9 on that system (cp936), but leave other sizes alone.
if ((pointSize < 9) &&
(936 == ::GetACP()))
pointSize = 9;
aFont->size = NSFloatPointsToTwips(pointSize);
return NS_OK;
}
nsresult nsDeviceContextWin :: GetSysFontInfo(HDC aHDC, nsSystemFontID anID, nsFont* aFont) const
{
HGDIOBJ hGDI;
LOGFONT logFont;
LOGFONT* ptrLogFont = NULL;
#ifdef WINCE
hGDI = ::GetStockObject(SYSTEM_FONT);
if (hGDI == NULL)
return NS_ERROR_UNEXPECTED;
if (::GetObject(hGDI, sizeof(logFont), &logFont) > 0)
ptrLogFont = &logFont;
#else
NONCLIENTMETRICS ncm;
BOOL status;
if (anID == eSystemFont_Icon)
{
status = ::SystemParametersInfo(SPI_GETICONTITLELOGFONT,
sizeof(logFont),
(PVOID)&logFont,
0);
}
else
{
ncm.cbSize = sizeof(NONCLIENTMETRICS);
status = ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
sizeof(ncm),
(PVOID)&ncm,
0);
}
if (!status)
{
return NS_ERROR_FAILURE;
}
switch (anID)
{
// Caption in CSS is NOT the same as Caption on Windows
//case eSystemFont_Caption:
// ptrLogFont = &ncm.lfCaptionFont;
// break;
case eSystemFont_Icon:
ptrLogFont = &logFont;
break;
case eSystemFont_Menu:
ptrLogFont = &ncm.lfMenuFont;
break;
case eSystemFont_MessageBox:
ptrLogFont = &ncm.lfMessageFont;
break;
case eSystemFont_SmallCaption:
ptrLogFont = &ncm.lfSmCaptionFont;
break;
case eSystemFont_StatusBar:
case eSystemFont_Tooltips:
ptrLogFont = &ncm.lfStatusFont;
break;
case eSystemFont_Widget:
case eSystemFont_Window: // css3
case eSystemFont_Document:
case eSystemFont_Workspace:
case eSystemFont_Desktop:
case eSystemFont_Info:
case eSystemFont_Dialog:
case eSystemFont_Button:
case eSystemFont_PullDownMenu:
case eSystemFont_List:
case eSystemFont_Field:
case eSystemFont_Caption:
hGDI = ::GetStockObject(DEFAULT_GUI_FONT);
if (hGDI != NULL)
{
if (::GetObject(hGDI, sizeof(logFont), &logFont) > 0)
{
ptrLogFont = &logFont;
}
}
break;
} // switch
#endif // WINCE
if (nsnull == ptrLogFont)
{
return NS_ERROR_FAILURE;
}
aFont->systemFont = PR_TRUE;
return CopyLogFontToNSFont(&aHDC, ptrLogFont, aFont);
}
NS_IMETHODIMP nsDeviceContextWin :: GetSystemFont(nsSystemFontID anID, nsFont *aFont) const
{
nsresult status = NS_OK;
switch (anID) {
case eSystemFont_Caption:
case eSystemFont_Icon:
case eSystemFont_Menu:
case eSystemFont_MessageBox:
case eSystemFont_SmallCaption:
case eSystemFont_StatusBar:
case eSystemFont_Tooltips:
case eSystemFont_Widget:
case eSystemFont_Window: // css3
case eSystemFont_Document:
case eSystemFont_Workspace:
case eSystemFont_Desktop:
case eSystemFont_Info:
case eSystemFont_Dialog:
case eSystemFont_Button:
case eSystemFont_PullDownMenu:
case eSystemFont_List:
case eSystemFont_Field:
{
HWND hwnd;
HDC tdc;
if (nsnull == mDC)
{
hwnd = (HWND)mWidget;
tdc = ::GetDC(hwnd);
}
else
tdc = mDC;
status = GetSysFontInfo(tdc, anID, aFont);
if (nsnull == mDC)
::ReleaseDC(hwnd, tdc);
break;
}
}
return status;
}
NS_IMETHODIMP nsDeviceContextWin :: GetDrawingSurface(nsIRenderingContext &aContext, nsIDrawingSurface* &aSurface)
{
if (NULL == mSurface) {
nsRect empty(0,0,0,0); // CreateDrawingSurface(null,...) used width=0,height=0
aContext.CreateDrawingSurface(empty, 0, mSurface);
}
aSurface = mSurface;
return NS_OK;
}
int CALLBACK fontcallback(ENUMLOGFONT FAR *lpelf, NEWTEXTMETRIC FAR *lpntm,
int FontType, LPARAM lParam)
{
if (NULL != lpelf)
*((PRBool *)lParam) = PR_TRUE;
return 0;
}
NS_IMETHODIMP nsDeviceContextWin :: CheckFontExistence(const nsString& aFontName)
{
HWND hwnd = (HWND)mWidget;
HDC hdc = ::GetDC(hwnd);
PRBool isthere = PR_FALSE;
LOGFONT logFont;
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfPitchAndFamily = 0;
int outlen = WideCharToMultiByte(CP_ACP, 0, aFontName.get(), aFontName.Length() + 1,
logFont.lfFaceName, sizeof(logFont.lfFaceName), nsnull, nsnull);
// somehow the WideCharToMultiByte failed, let's try the old code
if(0 == outlen)
aFontName.ToCString(logFont.lfFaceName, LF_FACESIZE);
::EnumFontFamiliesEx(hdc, &logFont, (FONTENUMPROC)fontcallback, (LPARAM)&isthere, 0);
if (!isthere)
::EnumFontFamilies(hdc, logFont.lfFaceName, (FONTENUMPROC)fontcallback, (LPARAM)&isthere);
::ReleaseDC(hwnd, hdc);
if (PR_TRUE == isthere)
return NS_OK;
else
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsDeviceContextWin::GetDepth(PRUint32& aDepth)
{
aDepth = mDepth;
return NS_OK;
}
NS_IMETHODIMP nsDeviceContextWin::GetPaletteInfo(nsPaletteInfo& aPaletteInfo)
{
aPaletteInfo.isPaletteDevice = mPaletteInfo.isPaletteDevice;
aPaletteInfo.sizePalette = mPaletteInfo.sizePalette;
aPaletteInfo.numReserved = mPaletteInfo.numReserved;
if (NULL == mPaletteInfo.palette) {
#ifndef WINCE
HWND hwnd = (HWND)mWidget;
HDC hdc = ::GetDC(hwnd);
mPaletteInfo.palette = ::CreateHalftonePalette(hdc);
::ReleaseDC(hwnd, hdc);
#else
mPaletteInfo.palette = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
#endif
}
aPaletteInfo.palette = mPaletteInfo.palette;
return NS_OK;
}
NS_IMETHODIMP nsDeviceContextWin :: GetDeviceSurfaceDimensions(PRInt32 &aWidth, PRInt32 &aHeight)
{
#ifdef NS_PRINT_PREVIEW
// Defer to Alt when there is one
if (mAltDC && (mUseAltDC & kUseAltDCFor_SURFACE_DIM)) {
return mAltDC->GetDeviceSurfaceDimensions(aWidth, aHeight);
}
#endif
if ( mSpec )
{
// we have a printer device
aWidth = NSToIntRound(mWidth * mDevUnitsToAppUnits);
aHeight = NSToIntRound(mHeight * mDevUnitsToAppUnits);
}
else
{
nsRect area;
ComputeFullAreaUsingScreen ( &area );
aWidth = area.width;
aHeight = area.height;
}
return NS_OK;
}
NS_IMETHODIMP nsDeviceContextWin :: GetRect(nsRect &aRect)
{
if ( mSpec )
{
// we have a printer device
aRect.x = 0;
aRect.y = 0;
aRect.width = NSToIntRound(mWidth * mDevUnitsToAppUnits);
aRect.height = NSToIntRound(mHeight * mDevUnitsToAppUnits);
}
else
ComputeFullAreaUsingScreen ( &aRect );
return NS_OK;
}
NS_IMETHODIMP nsDeviceContextWin :: GetClientRect(nsRect &aRect)
{
if ( mSpec )
{
// we have a printer device
aRect.x = 0;
aRect.y = 0;
aRect.width = NSToIntRound(mWidth * mDevUnitsToAppUnits);
aRect.height = NSToIntRound(mHeight * mDevUnitsToAppUnits);
}
else
ComputeClientRectUsingScreen ( &aRect );
return NS_OK;
}
BOOL CALLBACK abortproc( HDC hdc, int iError )
{
return TRUE;
}
NS_IMETHODIMP nsDeviceContextWin :: GetDeviceContextFor(nsIDeviceContextSpec *aDevice,
nsIDeviceContext *&aContext)
{
nsDeviceContextWin* devConWin = new nsDeviceContextWin(); //ref count 0
if (devConWin != nsnull) {
// this will ref count it
nsresult rv = devConWin->QueryInterface(NS_GET_IID(nsIDeviceContext), (void**)&aContext);
NS_ASSERTION(NS_SUCCEEDED(rv), "This has to support nsIDeviceContext");
} else {
return NS_ERROR_OUT_OF_MEMORY;
}
devConWin->mSpec = aDevice;
NS_ADDREF(aDevice);
char* devicename;
char* drivername;
nsDeviceContextSpecWin* devSpecWin = NS_STATIC_CAST(nsDeviceContextSpecWin*, aDevice);
devSpecWin->GetDeviceName(devicename); // sets pointer do not free
devSpecWin->GetDriverName(drivername); // sets pointer do not free
HDC dc = NULL;
LPDEVMODE devmode;
devSpecWin->GetDevMode(devmode);
NS_ASSERTION(devmode, "DevMode can't be NULL here");
if (devmode) {
dc = ::CreateDC(drivername, devicename, NULL, devmode);
}
return devConWin->Init(dc, this); // take ownership of the DC
}
#if defined(DEBUG_rods) || defined(DEBUG_dcone)
static void DisplayLastError()
{
LPVOID lpMsgBuf;
DWORD errCode = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Display the string.
MessageBox( NULL, (const char *)lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
}
#define DISPLAY_LAST_ERROR DisplayLastError();
#else
#define DISPLAY_LAST_ERROR
#endif
NS_IMETHODIMP nsDeviceContextWin :: BeginDocument(PRUnichar * aTitle, PRUnichar* aPrintToFileName, PRInt32 aStartPage, PRInt32 aEndPage)
{
nsresult rv = NS_ERROR_GFX_PRINTER_STARTDOC;
if (NULL != mDC) {
DOCINFO docinfo;
nsString titleStr;
titleStr = aTitle;
if (titleStr.Length() > DOC_TITLE_LENGTH) {
titleStr.SetLength(DOC_TITLE_LENGTH-3);
titleStr.AppendLiteral("...");
}
char *title = GetACPString(titleStr);
char* docName = nsnull;
nsAutoString str(aPrintToFileName);
if (!str.IsEmpty()) {
docName = ToNewCString(str);
}
docinfo.cbSize = sizeof(docinfo);
docinfo.lpszDocName = title != nsnull?title:"Mozilla Document";
#ifdef DEBUG_rods
docinfo.lpszOutput = "\\p.ps";
#ifdef MOZ_LAYOUTDEBUG
// This is for overriding the above when doing the runtime checking
char * tempFileName = nsnull;
nsCOMPtr<nsIDebugObject>debugObj = do_GetService("@mozilla.org/debug/debugobject;1");
if (debugObj) {
PRBool isDoingTests;
if (NS_SUCCEEDED(debugObj->GetDoRuntimeTests(&isDoingTests)) && isDoingTests) {
PRUnichar * name;
debugObj->GetPrintFileName(&name);
if (name) {
if (*name) {
nsCString cStrName;
cStrName.AssignWithConversion(name);
tempFileName = ToNewCString(cStrName);
}
nsMemory::Free(name);
}
docinfo.lpszOutput = tempFileName;
}
}
#endif
#else
docinfo.lpszOutput = docName;
#endif
docinfo.lpszDatatype = NULL;
docinfo.fwType = 0;
if (::StartDoc(mDC, &docinfo) > 0) {
rv = NS_OK;
} else {
DISPLAY_LAST_ERROR
rv = NS_ERROR_GFX_PRINTER_STARTDOC;
PR_PL(("nsDeviceContextWin::BeginDocument - StartDoc Error!\n"));
}
if (title != nsnull) delete [] title;
if (docName != nsnull) nsMemory::Free(docName);
#if defined(DEBUG_rods) && defined(MOZ_LAYOUTDEBUG)
if (tempFileName) {
nsMemory::Free(tempFileName);
}
#endif
}
return rv;
}
NS_IMETHODIMP nsDeviceContextWin :: EndDocument(void)
{
if (NULL != mDC)
{
if (::EndDoc(mDC) > 0) {
return NS_OK;
} else {
DISPLAY_LAST_ERROR
PR_PL(("nsDeviceContextWin::EndDocument - EndDoc Error!\n"));
return NS_ERROR_GFX_PRINTER_ENDDOC;
}
}
return NS_OK;
}
NS_IMETHODIMP nsDeviceContextWin :: AbortDocument(void)
{
if (NULL != mDC)
{
if (::AbortDoc(mDC) > 0) {
return NS_OK;
} else {
DISPLAY_LAST_ERROR
PR_PL(("nsDeviceContextWin::AbortDocument - AbortDoc Error!\n"));
return NS_ERROR_ABORT;
}
}
return NS_OK;
}
NS_IMETHODIMP nsDeviceContextWin :: BeginPage(void)
{
if (NULL != mDC)
{
if (::StartPage(mDC) > 0)
return NS_OK;
else {
DISPLAY_LAST_ERROR
PR_PL(("nsDeviceContextWin::BeginPage - StartPage Error!\n"));
return NS_ERROR_GFX_PRINTER_STARTPAGE;
}
}
return NS_OK;
}
NS_IMETHODIMP nsDeviceContextWin :: EndPage(void)
{
if (NULL != mDC)
{
if (::EndPage(mDC) > 0) {
return NS_OK;
} else {
DISPLAY_LAST_ERROR
PR_PL(("nsDeviceContextWin::EndPage - EndPage Error!\n"));
return NS_ERROR_GFX_PRINTER_ENDPAGE;
}
}
return NS_OK;
}
char*
nsDeviceContextWin :: GetACPString(const nsAString& aStr)
{
int acplen = aStr.Length() * 2 + 1;
char * acp = new char[acplen];
if(acp)
{
int outlen = ::WideCharToMultiByte( CP_ACP, 0,
PromiseFlatString(aStr).get(), aStr.Length(),
acp, acplen, NULL, NULL);
if ( outlen > 0)
acp[outlen] = '\0'; // null terminate
}
return acp;
}