From: Wolfgang Rosenauer , Arne John Glenstrup Subject: get paper sizes from CUPS References: https://bugzilla.novell.com/show_bug.cgi?id=65482 https://bugzilla.mozilla.org/show_bug.cgi?id=324060 ================================================================================ --- gfx/src/gtk/nsDeviceContextSpecG.cpp +++ gfx/src/gtk/nsDeviceContextSpecG.cpp @@ -66,6 +66,7 @@ #ifdef USE_POSTSCRIPT #include "nsPSPrinters.h" #include "nsPaperPS.h" /* Paper size list */ +#include "nsPaperFactoryPS.h" /* Paper size list factory */ #endif /* USE_POSTSCRIPT */ /* Ensure that the result is always equal to either PR_TRUE or PR_FALSE */ @@ -1210,34 +1211,38 @@ #ifdef SET_PRINTER_FEATURES_VIA_PREFS printerFeatures.SetCanChangePaperSize(PR_TRUE); #endif /* SET_PRINTER_FEATURES_VIA_PREFS */ - nsXPIDLCString papername; - if (NS_SUCCEEDED(CopyPrinterCharPref(pPrefs, "postscript", printerName, "paper_size", getter_Copies(papername)))) { - nsPaperSizePS paper; - - if (paper.Find(papername)) { - DO_PR_DEBUG_LOG(("setting default paper size to '%s' (%g mm/%g mm)\n", - paper.Name(), paper.Width_mm(), paper.Height_mm())); - aPrintSettings->SetPaperSizeUnit(paper.IsMetric() ? - (int)nsIPrintSettings::kPaperSizeMillimeters : - (int)nsIPrintSettings::kPaperSizeInches); - aPrintSettings->SetPaperWidth(paper.Width_mm()); - aPrintSettings->SetPaperHeight(paper.Height_mm()); - aPrintSettings->SetPaperName(NS_ConvertASCIItoUCS2(paper.Name()).get()); - } - else { - DO_PR_DEBUG_LOG(("Unknown paper size '%s' given.\n", papername.get())); + { + nsIPaperSizePS* paper; + nsresult rv; + rv = nsPaperFactoryPS::CreatePaper + (fullPrinterName.get(), printerName.get(), paper); + if (NS_FAILED(rv)) return rv; + paper->FindDefault(); + + nsXPIDLCString papername; + if (NS_SUCCEEDED(CopyPrinterCharPref(pPrefs, "postscript", fullPrinterName, "print_paper_name", getter_Copies(papername)))) { + if (!paper->Find(papername)) { + DO_PR_DEBUG_LOG(("Unknown paper size '%s' given.\n", papername.get())); + } } + DO_PR_DEBUG_LOG(("setting default paper size to '%s' (%g mm/%g mm)\n", + paper->Name(), paper->Width_mm(), paper->Height_mm())); + aPrintSettings->SetPaperSizeUnit(nsIPrintSettings::kPaperSizeMillimeters); + aPrintSettings->SetPaperWidth(paper->Width_mm()); + aPrintSettings->SetPaperHeight(paper->Height_mm()); + aPrintSettings->SetPaperName(NS_ConvertASCIItoUTF16(paper->Name()).get()); #ifdef SET_PRINTER_FEATURES_VIA_PREFS - paper.First(); + paper->First(); int count = 0; - while (!paper.AtEnd()) + while (!paper->AtEnd()) { - printerFeatures.SetPaperRecord(count++, paper.Name(), - (int)paper.Width_mm(), (int)paper.Height_mm(), !paper.IsMetric()); - paper.Next(); + printerFeatures.SetPaperRecord(count++, paper->Name(), + (int)paper->Width_mm(), (int)paper->Height_mm(), !paper->IsMetric()); + paper->Next(); } printerFeatures.SetNumPaperSizeRecords(count); #endif /* SET_PRINTER_FEATURES_VIA_PREFS */ + delete(paper); } PRBool hasSpoolerCmd = (nsPSPrinterList::kTypePS == --- gfx/src/ps/nsPrintJobPS.cpp +++ gfx/src/ps/nsPrintJobPS.cpp @@ -364,6 +364,10 @@ const char *slash = strchr(printerName, '/'); mPrinterName = slash ? slash + 1 : printerName; mJobTitle.SetIsVoid(PR_TRUE); + /* Paper name */ + const char* paperName = nsnull; + aSpec->GetPaperName(&paperName); + mPaperName = paperName; return NS_OK; } @@ -445,6 +449,11 @@ mNumCopies.get(), dest->num_options, &dest->options); + if (!mPaperName.IsEmpty()) + dest->num_options = (mCups.mCupsAddOption)("media", + mPaperName.get(), + dest->num_options, + &dest->options); const char *title = mJobTitle.IsVoid() ? "Untitled Document" : mJobTitle.get(); result = (mCups.mCupsPrintFile)(printer.CStringAt(0)->get(), --- gfx/src/ps/nsPrintJobPS.h +++ gfx/src/ps/nsPrintJobPS.h @@ -179,6 +179,7 @@ nsCUPSShim mCups; nsCString mPrinterName; nsCString mNumCopies; + nsCString mPaperName; nsCString mJobTitle; // IsVoid() if no title }; #endif /* VMS */ --- gfx/src/psshared/Makefile.in +++ gfx/src/psshared/Makefile.in @@ -57,13 +57,16 @@ EXPORTS = nsCUPSShim.h \ nsPaperPS.h \ + nsIPaperPS.h \ nsPSPrinters.h\ psSharedCore.h \ + nsPaperFactoryPS.h \ $(NULL) CPPSRCS = nsCUPSShim.cpp \ nsPaperPS.cpp \ nsPSPrinters.cpp \ + nsPaperFactoryPS.cpp \ $(NULL) EXTRA_DSO_LDOPTS = \ --- gfx/src/psshared/nsCUPSShim.cpp +++ gfx/src/psshared/nsCUPSShim.cpp @@ -45,13 +45,18 @@ // List of symbols to find in libcups. Must match symAddr[] defined in Init(). // Making this an array of arrays instead of pointers allows storing the // whole thing in read-only memory. -static const char gSymName[][sizeof("cupsPrintFile")] = { +static const char gSymName[][sizeof("ppdMarkDefaults")] = { { "cupsAddOption" }, { "cupsFreeDests" }, { "cupsGetDest" }, { "cupsGetDests" }, { "cupsPrintFile" }, { "cupsTempFd" }, + { "cupsGetPPD" }, + { "ppdOpenFile" }, + { "ppdClose" }, + { "ppdMarkDefaults" }, + { "ppdIsMarked" }, }; static const int gSymNameCt = sizeof(gSymName) / sizeof(gSymName[0]); @@ -71,6 +76,11 @@ (void **)&mCupsGetDests, (void **)&mCupsPrintFile, (void **)&mCupsTempFd, + (void **)&mCupsGetPPD, + (void **)&mPpdOpenFile, + (void **)&mPpdClose, + (void **)&mPpdMarkDefaults, + (void **)&mPpdIsMarked, }; for (int i = gSymNameCt; i--; ) { --- gfx/src/psshared/nsCUPSShim.h +++ gfx/src/psshared/nsCUPSShim.h @@ -62,6 +62,82 @@ cups_option_t *options; /* Options */ } cups_dest_t; +typedef enum /**** Colorspaces ****/ +{ + PPD_CS_CMYK = -4, /* CMYK colorspace */ + PPD_CS_CMY, /* CMY colorspace */ + PPD_CS_GRAY = 1, /* Grayscale colorspace */ + PPD_CS_RGB = 3, /* RGB colorspace */ + PPD_CS_RGBK, /* RGBK (K = gray) colorspace */ + PPD_CS_N /* DeviceN colorspace */ +} ppd_cs_t; + +typedef struct /**** Page Sizes ****/ +{ + int marked; /* Page size selected? */ + char name[41]; + /* Media size option */ + float width, /* Width of media in points */ + length, /* Length of media in points */ + left, /* Left printable margin in points */ + bottom, /* Bottom printable margin in points */ + right, /* Right printable margin in points */ + top; /* Top printable margin in points */ +} ppd_size_t; + +typedef struct /**** Files ****/ +{ + int language_level, /* Language level of device */ + color_device, /* 1 = color device, 0 = grayscale */ + variable_sizes, /* 1 = supports variable sizes, 0 = doesn't */ + accurate_screens, /* 1 = supports accurate screens, 0 = not */ + contone_only, /* 1 = continuous tone only, 0 = not */ + landscape, /* -90 or 90 */ + model_number, /* Device-specific model number */ + manual_copies, /* 1 = Copies done manually, 0 = hardware */ + throughput; /* Pages per minute */ + ppd_cs_t colorspace; /* Default colorspace */ + char *patches; /* Patch commands to be sent to printer */ + int num_emulations; /* Number of emulations supported */ + void *emulations; /* Emulations and the code to invoke them */ + char *jcl_begin, /* Start JCL commands */ + *jcl_ps, /* Enter PostScript interpreter */ + *jcl_end, /* End JCL commands */ + *lang_encoding, /* Language encoding */ + *lang_version, /* Language version (English, Spanish, etc.) */ + *modelname, /* Model name (general) */ + *ttrasterizer, /* Truetype rasterizer */ + *manufacturer, /* Manufacturer name */ + *product, /* Product name (from PS RIP/interpreter) */ + *nickname, /* Nickname (specific) */ + *shortnickname; /* Short version of nickname */ + int num_groups; /* Number of UI groups */ + void *groups; /* UI groups */ + int num_sizes; /* Number of page sizes */ + ppd_size_t *sizes; /* Page sizes */ + float custom_min[2], /* Minimum variable page size */ + custom_max[2], /* Maximum variable page size */ + custom_margins[4];/* Margins around page */ + int num_consts; /* Number of UI/Non-UI constraints */ + void *consts; /* UI/Non-UI constraints */ + int num_fonts; /* Number of pre-loaded fonts */ + char **fonts; /* Pre-loaded fonts */ + int num_profiles; /* Number of sRGB color profiles */ + void *profiles; /* sRGB color profiles */ + int num_filters; /* Number of filters */ + char **filters; /* Filter strings... */ + + /**** New in CUPS 1.1 ****/ + int flip_duplex; /* 1 = Flip page for back sides */ + + /**** New in CUPS 1.1.19 ****/ + char *protocols, /* Protocols (BCP, TBCP) string */ + *pcfilename; /* PCFileName string */ + int num_attrs, /* Number of attributes */ + cur_attr; /* Current attribute */ + void **attrs; /* Attributes */ +} ppd_file_t; + typedef cups_dest_t* (PR_CALLBACK *CupsGetDestType)(const char *printer, const char *instance, int num_dests, @@ -80,6 +156,11 @@ const char *value, int num_options, cups_option_t **options); +typedef const char* (PR_CALLBACK *CupsGetPPDType) (const char* name); +typedef ppd_file_t* (PR_CALLBACK *PPDOpenFileType) (const char* filename); +typedef void (PR_CALLBACK *PPDCloseType) (ppd_file_t* ppd); +typedef void (PR_CALLBACK *PPDMarkDefaultsType) (ppd_file_t* ppd); +typedef int (PR_CALLBACK *PPDIsMarkedType) (ppd_file_t* ppd, const char* pname, const char* pname_clear); struct PRLibrary; @@ -113,6 +194,11 @@ CupsGetDestsType mCupsGetDests; CupsPrintFileType mCupsPrintFile; CupsTempFdType mCupsTempFd; + CupsGetPPDType mCupsGetPPD; + PPDOpenFileType mPpdOpenFile; + PPDCloseType mPpdClose; + PPDMarkDefaultsType mPpdMarkDefaults; + PPDIsMarkedType mPpdIsMarked; private: PRLibrary *mCupsLib; --- gfx/src/psshared/nsIPaperPS.h +++ gfx/src/psshared/nsIPaperPS.h @@ -0,0 +1,102 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */ +/* ***** 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. + * + * Contributor(s): + * Arne John Glenstrup + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 ***** */ + + +#ifndef _NSIPAPERPS_H_ +#define _NSIPAPERPS_H_ + +#include "prtypes.h" +#include "psSharedCore.h" + +class nsIPaperSizePS { + public: + /** --------------------------------------------------- + * Virtual destructor. + */ + virtual ~nsIPaperSizePS(); + + /* Allow the paper factory to create instances */ + friend class nsPaperFactoryPS; + + /** --------------------------------------------------- + * @return PR_TRUE if the cursor points past the last item. + */ + virtual PRBool AtEnd() = 0; + + /** --------------------------------------------------- + * Position the cursor at the beginning of the paper size list. + * @return VOID + */ + virtual void First() = 0; + + /** --------------------------------------------------- + * Advance the cursor to the next item. + * @return VOID + */ + virtual void Next() = 0; + + /** --------------------------------------------------- + * Point the cursor to the entry with the given paper name. + * @return PR_TRUE if pointing to a valid entry. + */ + virtual PRBool Find(const char *aName) = 0; + + /** --------------------------------------------------- + * Point the cursor to a default entry if available. + * Otherwise it's equivalent to First(). + * @return PR_TRUE if pointing to a valid entry. + */ + virtual PRBool FindDefault() = 0; + + /** --------------------------------------------------- + * @return a pointer to the name of the current paper size + */ + virtual const char *Name() = 0; + + /** --------------------------------------------------- + * @return the width of the page in millimeters + */ + virtual float Width_mm() = 0; + + /** --------------------------------------------------- + * @return the height of the page in millimeters + */ + virtual float Height_mm() = 0; + + /** --------------------------------------------------- + * @return PR_TRUE if the paper should be presented to + * the user in metric units. + */ + virtual PRBool IsMetric() { return PR_TRUE; }; +}; + +#endif /* _NSIPAPERPS_H_ */ --- gfx/src/psshared/nsPSPrinters.h +++ gfx/src/psshared/nsPSPrinters.h @@ -44,6 +44,7 @@ #include "prtypes.h" #include "nsCUPSShim.h" #include "psSharedCore.h" +#include "nsCOMPtr.h" class nsIPrefService; class nsIPrefBranch; --- gfx/src/psshared/nsPaperFactoryPS.cpp +++ gfx/src/psshared/nsPaperFactoryPS.cpp @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */ +/* ***** 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 + * Kenneth Herron . + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Arne John Glenstrup + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 "nsDebug.h" +#include "nsPaperFactoryPS.h" +#include "nsIPaperPS.h" +#include "nsPaperPS.h" +#include "nsPSPrinters.h" + +nsresult +nsPaperFactoryPS::CreatePaper(const char* fullPrinterName, + const char* printerName, + nsIPaperSizePS* &aPaper) +{ + nsIPaperSizePS *newPZ; + + if (nsPSPrinterList::kTypeCUPS == nsPSPrinterList::GetPrinterType + (nsDependentCString(fullPrinterName))) + newPZ = new nsPaperSizeCUPS(fullPrinterName, printerName); + else + newPZ = new nsPaperSizePS(); + + if (!newPZ) + return NS_ERROR_OUT_OF_MEMORY; + + aPaper = newPZ; + return NS_OK; +} --- gfx/src/psshared/nsPaperFactoryPS.h +++ gfx/src/psshared/nsPaperFactoryPS.h @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */ +/* ***** 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. + * + * Contributor(s): + * Arne John Glenstrup + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 ***** */ + +#ifndef nsPaperFactoryPS_h__ +#define nsPaperFactoryPS_h__ + +#include "nscore.h" +#include "nsIPaperPS.h" + +/* Factory class for the paper sizes. This class determines + * which paper size class should handle a request, and constructs + * an object of the appropriate class. + */ + +class NS_PSSHARED nsPaperFactoryPS +{ +public: + /** + * Construct a paper size object for the given device context spec. + * On success, the paper size object is owned by the caller and should + * be destroyed when no longer needed. + * + * @param fullPrinterName Fully qualified name, e.g., "CUPS/myprinter" + * @param printerName Stripped name, e.g., "myprinter" + * @param aPaper If NS_OK is returned, this will be filled + * in with a pointer to a paper size object. + * @return NS_OK or a suitable error value. + */ + static nsresult CreatePaper(const char* fullPrinterName, + const char* printerName, + nsIPaperSizePS* &aPaper); +}; + + +#endif /* nsPaperFactoryPS_h__ */ --- gfx/src/psshared/nsPaperPS.cpp +++ gfx/src/psshared/nsPaperPS.cpp @@ -22,6 +22,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Arne John Glenstrup * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -37,9 +38,25 @@ * * ***** END LICENSE BLOCK ***** */ - +#ifdef MOZ_LOGGING +#define FORCE_PR_LOG 1 /* Allow logging in the release build */ +#endif /* MOZ_LOGGING */ +#include "prlog.h" + #include "nsPaperPS.h" #include "plstr.h" +#include "nsPSPrinters.h" +#include + +#ifdef PR_LOGGING +static PRLogModuleInfo *PaperSizePSLM = PR_NewLogModule("PaperSizePS"); +#endif /* PR_LOGGING */ +/* Macro to make lines shorter */ +#define DO_PR_DEBUG_LOG(x) PR_LOG(PaperSizePSLM, PR_LOG_DEBUG, x) + +#define MM_PER_PT (25.4 / 72.0) +#define HALF_INCH_PT 36.0 +#define EPSILON 0.125 #define COUNTOF(x) (sizeof(x) / sizeof((x)[0])) @@ -57,7 +74,15 @@ #undef SIZE_MM }; -const unsigned int nsPaperSizePS::mCount = COUNTOF(mList); +nsCUPSShim nsPaperSizeCUPS::mCups; + +/* ~nsIPaperSizePS() is virtual, so must implement a destructor. */ +nsIPaperSizePS::~nsIPaperSizePS () { } + +nsPaperSizePS::nsPaperSizePS() { + mCount = COUNTOF(mList); + mCurrent = 0; +} PRBool nsPaperSizePS::Find(const char *aName) @@ -70,3 +95,125 @@ } return PR_FALSE; } + +nsPaperSizeCUPS::nsPaperSizeCUPS(const char* fullPrinterName, + const char* printerName) { + DO_PR_DEBUG_LOG(("nsPaperSizeCUPS::nsPaperSizeCUPS('%s', '%s')\n", + fullPrinterName, printerName)); + /* Don't use CUPS before we are sure we have access to the PPD */ + mUsingCups = false; + mPPD = nsnull; + mCount = COUNTOF(mList); + mCurrent = 0; + if (!fullPrinterName || !printerName || + nsPSPrinterList::kTypeCUPS != + nsPSPrinterList::GetPrinterType(nsDependentCString(fullPrinterName))) + return; + if (!mCups.IsInitialized()) { mCups.Init(); } + if (!mCups.IsInitialized()) { + DO_PR_DEBUG_LOG(("nsPaperSizeCUPS::nsPaperSizeCUPS: CUPS unavailable\n")); + return; + } + const char* ppdFileName = mCups.mCupsGetPPD(printerName); + if (!ppdFileName) { + DO_PR_DEBUG_LOG(("nsPaperSizeCUPS::nsPaperSizeCUPS: " + "cannot get PPD file name for printer '%s'\n", + printerName)); + return; + } + mPPD = mCups.mPpdOpenFile(ppdFileName); + if (!mPPD) { + DO_PR_DEBUG_LOG(("nsPaperSizeCUPS::nsPaperSizeCUPS: " + "cannot open PPD file '%s'\n", + ppdFileName)); + return; + } + mCount = mPPD->num_sizes; + mUsingCups = true; +} + +nsPaperSizeCUPS::~nsPaperSizeCUPS() { + if (mPPD) mCups.mPpdClose(mPPD); +} + +void +nsPaperSizeCUPS::SkipZeroSizes() { + if (!mUsingCups) return; + while (mCurrent < mCount + && (mPPD->sizes[mCurrent].width == 0.0f || + mPPD->sizes[mCurrent].length == 0.0f)) { + mCurrent++; + } +} + +PRBool +nsPaperSizeCUPS::Find(const char* aName) { + DO_PR_DEBUG_LOG(("nsPaperSizeCUPS::Find ('%s') ", aName)); + if (!mUsingCups) return nsPaperSizePS::Find(aName); + for (int i = mCount; i--; ) { + if (!PL_strcasecmp(aName, mPPD->sizes[i].name)) { + DO_PR_DEBUG_LOG + (("found paper '%s' (%gx%gmm)\n", + aName, + round(mPPD->sizes[i].width * MM_PER_PT), + round(mPPD->sizes[i].length * MM_PER_PT))); + mCurrent = i; + return PR_TRUE; + } + } + DO_PR_DEBUG_LOG(("did not find paper '%s'\n", aName)); + return PR_FALSE; +} + +PRBool +nsPaperSizeCUPS::FindDefault() { + DO_PR_DEBUG_LOG(("nsPaperSizeCUPS::FindDefault")); + if (!mUsingCups) return nsPaperSizePS::FindDefault(); + mCups.mPpdMarkDefaults(mPPD); + for (int i = mCount; i--; ) { + if (mCups.mPpdIsMarked(mPPD, "PageSize", mPPD->sizes[i].name )) { + DO_PR_DEBUG_LOG + (("found default paper '%s' (%gx%gmm)\n", + mPPD->sizes[i].name, + round(mPPD->sizes[i].width * MM_PER_PT), + round(mPPD->sizes[i].length * MM_PER_PT))); + mCurrent = i; + return PR_TRUE; + } + } + mCurrent = 0; + DO_PR_DEBUG_LOG(("no default paper found, therefore set the first\n")); + return PR_TRUE; +} + +const char* +nsPaperSizeCUPS::Name() { + if (!mUsingCups) return nsPaperSizePS::Name(); + NS_PRECONDITION(!AtEnd(), "Invalid current item"); + return mPPD->sizes[mCurrent].name; +} + +float +nsPaperSizeCUPS::Width_mm() { + if (!mUsingCups) return nsPaperSizePS::Width_mm(); + NS_PRECONDITION(!AtEnd(), "Invalid current item"); + return round(mPPD->sizes[mCurrent].width * MM_PER_PT); +} + +float +nsPaperSizeCUPS::Height_mm() { + if (!mUsingCups) return nsPaperSizePS::Height_mm(); + NS_PRECONDITION(!AtEnd(), "Invalid current item"); + return round(mPPD->sizes[mCurrent].length * MM_PER_PT); +} + +PRBool +nsPaperSizeCUPS::IsMetric() { + if (!mUsingCups) return nsPaperSizePS::IsMetric(); + NS_PRECONDITION(!AtEnd(), "Invalid current item"); + /* Educated guess: unless sizes are integral number */ + /* of half inches, present them to the user in metric. */ + return + fabs(fmod(mPPD->sizes[mCurrent].width, HALF_INCH_PT)) > EPSILON || + fabs(fmod(mPPD->sizes[mCurrent].length, HALF_INCH_PT)) > EPSILON; +} --- gfx/src/psshared/nsPaperPS.h +++ gfx/src/psshared/nsPaperPS.h @@ -40,9 +40,9 @@ #ifndef _PAPERPS_H_ #define _PAPERPS_H_ -#include "prtypes.h" +#include "nsIPaperPS.h" #include "nsDebug.h" -#include "psSharedCore.h" +#include "nsCUPSShim.h" struct nsPaperSizePS_ { const char *name; @@ -51,13 +51,13 @@ PRBool isMetric; // Present to the user in metric, if possible }; -class NS_PSSHARED nsPaperSizePS { +class NS_PSSHARED nsPaperSizePS : public nsIPaperSizePS { public: /** --------------------------------------------------- * Constructor */ - nsPaperSizePS() { mCurrent = 0; } - + nsPaperSizePS(); + /** --------------------------------------------------- * @return PR_TRUE if the cursor points past the last item. */ @@ -85,6 +85,12 @@ PRBool Find(const char *aName); /** --------------------------------------------------- + * Position the cursor at the beginning of the paper size list. + * @return PR_TRUE + */ + PRBool FindDefault() { mCurrent = 0; return PR_TRUE; } + + /** --------------------------------------------------- * @return a pointer to the name of the current paper size */ const char *Name() { @@ -117,11 +123,83 @@ return mList[mCurrent].isMetric; } - private: + protected: unsigned int mCurrent; // the class visibility should export these, but it doesn't static NS_PSSHARED_STATIC_MEMBER_(const nsPaperSizePS_) mList[]; - static NS_PSSHARED_STATIC_MEMBER_(const unsigned int) mCount; + unsigned int mCount; +}; + +class NS_PSSHARED nsPaperSizeCUPS : public nsPaperSizePS { + public: + /** --------------------------------------------------- + * Constructor for a specific CUPS printer. + * @param fullPrinterName Fully qualified name, e.g., "CUPS/myprinter" + * @param printerName Stripped name, e.g., "myprinter" + */ + nsPaperSizeCUPS(const char* fullPrinterName, const char* printerName); + + /** --------------------------------------------------- + * Destructor. + */ + ~nsPaperSizeCUPS(); + + /** --------------------------------------------------- + * Position the cursor at the beginning of the paper size list. + * @return VOID + */ + void First() { + nsPaperSizePS::First(); + SkipZeroSizes(); + } + + /** --------------------------------------------------- + * Advance the cursor to the next item. + * @return VOID + */ + void Next() { + nsPaperSizePS::Next(); + SkipZeroSizes(); + } + + /** --------------------------------------------------- + * Point the cursor to the entry with the given paper name. + * @return PR_TRUE if pointing to a valid entry. + */ + PRBool Find(const char *aName); + + /** --------------------------------------------------- + * Point the cursor to the CUPS default entry for paper size. + * @return PR_TRUE if pointing to a valid entry. + */ + PRBool FindDefault(); + + /** --------------------------------------------------- + * @return a pointer to the name of the current paper size + */ + const char *Name(); + + /** --------------------------------------------------- + * @return the width of the page in millimeters + */ + float Width_mm(); + + /** --------------------------------------------------- + * @return the height of the page in millimeters + */ + float Height_mm(); + + /** --------------------------------------------------- + * @return PR_TRUE if the paper should be presented to + * the user in metric units. + */ + PRBool IsMetric(); + + private: + void SkipZeroSizes(); + PRBool mUsingCups; + static NS_PSSHARED_STATIC_MEMBER_(nsCUPSShim) mCups; + ppd_file_t* mPPD; }; #endif --- gfx/src/xlib/nsDeviceContextSpecXlib.cpp +++ gfx/src/xlib/nsDeviceContextSpecXlib.cpp @@ -1212,7 +1212,11 @@ #endif /* SET_PRINTER_FEATURES_VIA_PREFS */ nsXPIDLCString papername; if (NS_SUCCEEDED(CopyPrinterCharPref(pPrefs, "postscript", printerName, "paper_size", getter_Copies(papername)))) { - nsPaperSizePS paper; + nsIPaperSizePS* paper; + nsresult rv; + rv = nsPaperFactoryPS::CreatePaper + (fullPrinterName.get(), printerName.get(), paper); + if (NS_FAILED(rv)) return rv; if (paper.Find(papername)) { DO_PR_DEBUG_LOG(("setting default paper size to '%s' (%g mm/%g mm)\n", @@ -1238,6 +1242,7 @@ } printerFeatures.SetNumPaperSizeRecords(count); #endif /* SET_PRINTER_FEATURES_VIA_PREFS */ + delete(paper); } PRBool hasSpoolerCmd = (nsPSPrinterList::kTypePS ==