michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #define SET_PRINTER_FEATURES_VIA_PREFS 1 michael@0: #define PRINTERFEATURES_PREF "print.tmp.printerfeatures" michael@0: michael@0: #ifdef MOZ_LOGGING michael@0: #define FORCE_PR_LOG 1 /* Allow logging in the release build */ michael@0: #endif /* MOZ_LOGGING */ michael@0: #include "prlog.h" michael@0: michael@0: #include "plstr.h" michael@0: michael@0: #include "nsDeviceContextSpecQt.h" michael@0: michael@0: #include "prenv.h" /* for PR_GetEnv */ michael@0: michael@0: #include "nsReadableUtils.h" michael@0: #include "nsStringEnumerator.h" michael@0: #include "nsIServiceManager.h" michael@0: #include "nsPrintSettingsQt.h" michael@0: #include "nsIFileStreams.h" michael@0: #include "nsIFile.h" michael@0: #include "nsTArray.h" michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include "gfxPDFSurface.h" michael@0: michael@0: #ifdef PR_LOGGING michael@0: static PRLogModuleInfo* DeviceContextSpecQtLM = michael@0: PR_NewLogModule("DeviceContextSpecQt"); michael@0: #endif /* PR_LOGGING */ michael@0: /* Macro to make lines shorter */ michael@0: #define DO_PR_DEBUG_LOG(x) PR_LOG(DeviceContextSpecQtLM, PR_LOG_DEBUG, x) michael@0: michael@0: nsDeviceContextSpecQt::nsDeviceContextSpecQt() michael@0: { michael@0: DO_PR_DEBUG_LOG(("nsDeviceContextSpecQt::nsDeviceContextSpecQt()\n")); michael@0: } michael@0: michael@0: nsDeviceContextSpecQt::~nsDeviceContextSpecQt() michael@0: { michael@0: DO_PR_DEBUG_LOG(("nsDeviceContextSpecQt::~nsDeviceContextSpecQt()\n")); michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsDeviceContextSpecQt, michael@0: nsIDeviceContextSpec) michael@0: michael@0: NS_IMETHODIMP nsDeviceContextSpecQt::GetSurfaceForPrinter( michael@0: gfxASurface** aSurface) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aSurface); michael@0: *aSurface = nullptr; michael@0: michael@0: double width, height; michael@0: mPrintSettings->GetEffectivePageSize(&width, &height); michael@0: michael@0: // If we're in landscape mode, we'll be rotating the output -- michael@0: // need to swap width & height. michael@0: int32_t orientation; michael@0: mPrintSettings->GetOrientation(&orientation); michael@0: if (nsIPrintSettings::kLandscapeOrientation == orientation) { michael@0: double tmp = width; michael@0: width = height; michael@0: height = tmp; michael@0: } michael@0: michael@0: // convert twips to points michael@0: width /= TWIPS_PER_POINT_FLOAT; michael@0: height /= TWIPS_PER_POINT_FLOAT; michael@0: michael@0: DO_PR_DEBUG_LOG(("\"%s\", %f, %f\n", mPath, width, height)); michael@0: michael@0: QTemporaryFile file; michael@0: if(!file.open()) { michael@0: return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE; michael@0: } michael@0: file.setAutoRemove(false); michael@0: michael@0: nsresult rv = NS_NewNativeLocalFile( michael@0: nsDependentCString(file.fileName().toUtf8().constData()), michael@0: false, michael@0: getter_AddRefs(mSpoolFile)); michael@0: if (NS_FAILED(rv)) { michael@0: file.remove(); michael@0: return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE; michael@0: } michael@0: michael@0: mSpoolName = file.fileName().toUtf8().constData(); michael@0: michael@0: mSpoolFile->SetPermissions(0600); michael@0: michael@0: nsCOMPtr stream = michael@0: do_CreateInstance("@mozilla.org/network/file-output-stream;1"); michael@0: michael@0: rv = stream->Init(mSpoolFile, -1, -1, 0); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: int16_t format; michael@0: mPrintSettings->GetOutputFormat(&format); michael@0: michael@0: nsRefPtr surface; michael@0: gfxSize surfaceSize(width, height); michael@0: michael@0: if (format == nsIPrintSettings::kOutputFormatNative) { michael@0: if (mIsPPreview) { michael@0: // There is nothing to detect on Print Preview, use PS. michael@0: // TODO: implement for Qt? michael@0: //format = nsIPrintSettings::kOutputFormatPS; michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: format = nsIPrintSettings::kOutputFormatPDF; michael@0: } michael@0: if (format == nsIPrintSettings::kOutputFormatPDF) { michael@0: surface = new gfxPDFSurface(stream, surfaceSize); michael@0: } else { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: NS_ABORT_IF_FALSE(surface, "valid address expected"); michael@0: michael@0: surface.swap(*aSurface); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsDeviceContextSpecQt::Init(nsIWidget* aWidget, michael@0: nsIPrintSettings* aPS, michael@0: bool aIsPrintPreview) michael@0: { michael@0: DO_PR_DEBUG_LOG(("nsDeviceContextSpecQt::Init(aPS=%p)\n", aPS)); michael@0: michael@0: mPrintSettings = aPS; michael@0: mIsPPreview = aIsPrintPreview; michael@0: michael@0: // This is only set by embedders michael@0: bool toFile; michael@0: aPS->GetPrintToFile(&toFile); michael@0: michael@0: mToPrinter = !toFile && !aIsPrintPreview; michael@0: michael@0: nsCOMPtr printSettingsQt(do_QueryInterface(aPS)); michael@0: if (!printSettingsQt) michael@0: return NS_ERROR_NO_INTERFACE; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsDeviceContextSpecQt::GetPath(const char** aPath) michael@0: { michael@0: *aPath = mPath; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsDeviceContextSpecQt::BeginDocument( michael@0: const nsAString& aTitle, michael@0: char16_t* aPrintToFileName, michael@0: int32_t aStartPage, michael@0: int32_t aEndPage) michael@0: { michael@0: if (mToPrinter) { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsDeviceContextSpecQt::EndDocument() michael@0: { michael@0: if (mToPrinter) { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: // Handle print-to-file ourselves for the benefit of embedders michael@0: nsXPIDLString targetPath; michael@0: nsCOMPtr destFile; michael@0: mPrintSettings->GetToFileName(getter_Copies(targetPath)); michael@0: michael@0: nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(targetPath), michael@0: false, getter_AddRefs(destFile)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsAutoString destLeafName; michael@0: rv = destFile->GetLeafName(destLeafName); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsCOMPtr destDir; michael@0: rv = destFile->GetParent(getter_AddRefs(destDir)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: rv = mSpoolFile->MoveTo(destDir, destLeafName); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: // This is the standard way to get the UNIX umask. Ugh. michael@0: mode_t mask = umask(0); michael@0: umask(mask); michael@0: // If you're not familiar with umasks, they contain the bits of what NOT michael@0: // to set in the permissions michael@0: // (thats because files and directories have different numbers of bits michael@0: // for their permissions) michael@0: destFile->SetPermissions(0666 & ~(mask)); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: // Printer Enumerator michael@0: nsPrinterEnumeratorQt::nsPrinterEnumeratorQt() michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsPrinterEnumeratorQt, nsIPrinterEnumerator) michael@0: michael@0: NS_IMETHODIMP nsPrinterEnumeratorQt::GetPrinterNameList( michael@0: nsIStringEnumerator** aPrinterNameList) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aPrinterNameList); michael@0: *aPrinterNameList = nullptr; michael@0: michael@0: QList qprinters = QPrinterInfo::availablePrinters(); michael@0: if (qprinters.size() == 0) michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: michael@0: nsTArray* printers = michael@0: new nsTArray(qprinters.size()); michael@0: michael@0: for (int32_t i = 0; i < qprinters.size(); ++i) { michael@0: printers->AppendElement( michael@0: nsDependentString( michael@0: (const char16_t*)qprinters[i].printerName().constData())); michael@0: } michael@0: michael@0: return NS_NewAdoptingStringEnumerator(aPrinterNameList, printers); michael@0: } michael@0: michael@0: NS_IMETHODIMP nsPrinterEnumeratorQt::GetDefaultPrinterName( michael@0: char16_t** aDefaultPrinterName) michael@0: { michael@0: DO_PR_DEBUG_LOG(("nsPrinterEnumeratorQt::GetDefaultPrinterName()\n")); michael@0: NS_ENSURE_ARG_POINTER(aDefaultPrinterName); michael@0: michael@0: QString defprinter = QPrinterInfo::defaultPrinter().printerName(); michael@0: *aDefaultPrinterName = ToNewUnicode(nsDependentString( michael@0: (const char16_t*)defprinter.constData())); michael@0: michael@0: DO_PR_DEBUG_LOG(("GetDefaultPrinterName(): default printer='%s'.\n", michael@0: NS_ConvertUTF16toUTF8(*aDefaultPrinterName).get())); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsPrinterEnumeratorQt::InitPrintSettingsFromPrinter( michael@0: const char16_t* aPrinterName, michael@0: nsIPrintSettings* aPrintSettings) michael@0: { michael@0: DO_PR_DEBUG_LOG(("nsPrinterEnumeratorQt::InitPrintSettingsFromPrinter()")); michael@0: // XXX Leave NS_OK for now michael@0: // Probably should use NS_ERROR_NOT_IMPLEMENTED michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsPrinterEnumeratorQt::DisplayPropertiesDlg( michael@0: const char16_t* aPrinter, michael@0: nsIPrintSettings* aPrintSettings) michael@0: { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: