[OS/2] Bug 394412: fix scaling issues and add support for pagination, so that printing now works in principle. (OS/2 only, NPOTB)
authormozilla@weilbacher.org
Mon, 04 Feb 2008 01:31:05 -0800
changeset 11205 4363e9539cb58436344b86b725b20e7d4059f1d8
parent 11204 4baec3e1e49cd624e0bcae6b884766c7bfd27ef4
child 11206 264371cea63972c64329c43338ef7004674d3122
push idunknown
push userunknown
push dateunknown
bugs394412
milestone1.9b3pre
[OS/2] Bug 394412: fix scaling issues and add support for pagination, so that printing now works in principle. (OS/2 only, NPOTB)
gfx/src/thebes/nsThebesDeviceContext.cpp
widget/src/os2/nsDeviceContextSpecOS2.cpp
widget/src/os2/nsDeviceContextSpecOS2.h
--- a/gfx/src/thebes/nsThebesDeviceContext.cpp
+++ b/gfx/src/thebes/nsThebesDeviceContext.cpp
@@ -714,16 +714,19 @@ nsThebesDeviceContext::CalcPrintingSize(
 
 #ifdef XP_OS2
     case gfxASurface::SurfaceTypeOS2:
     {
         inPoints = PR_FALSE;
         // we already set the size in the surface constructor we set for
         // printing, so just get those values here
         size = reinterpret_cast<gfxOS2Surface*>(mPrintingSurface.get())->GetSize();
+        // as they are in pixels we need to scale them to app units
+        size.width = NSFloatPixelsToAppUnits(size.width, AppUnitsPerDevPixel());
+        size.height = NSFloatPixelsToAppUnits(size.height, AppUnitsPerDevPixel());
         // still need to get the depth from the device context
         HDC dc = GetPrintHDC();
         LONG value;
         if (DevQueryCaps(dc, CAPS_COLOR_BITCOUNT, 1, &value))
             mDepth = value;
         else
             mDepth = 8; // default to 8bpp, should be enough for printers
         break;
--- a/widget/src/os2/nsDeviceContextSpecOS2.cpp
+++ b/widget/src/os2/nsDeviceContextSpecOS2.cpp
@@ -94,17 +94,17 @@ protected:
 //---------------
 // static members
 GlobalPrinters GlobalPrinters::mGlobalPrinters;
 nsStringArray* GlobalPrinters::mGlobalPrinterList = nsnull;
 ULONG          GlobalPrinters::mGlobalNumPrinters = 0;
 //---------------
 
 nsDeviceContextSpecOS2::nsDeviceContextSpecOS2()
-  : mQueue(nsnull)
+  : mQueue(nsnull), mPrintDC(nsnull), mPrintingStarted(PR_FALSE)
 {
 }
 
 nsDeviceContextSpecOS2::~nsDeviceContextSpecOS2()
 {
   if (mQueue)
     PrnClosePrinter(mQueue);
 }
@@ -386,76 +386,121 @@ NS_IMETHODIMP nsDeviceContextSpecOS2::Ge
     int printerDest = 0;
     char *filename = nsnull;
 
     GetCopies(numCopies);
     GetDestination(printerDest);
     if (!printerDest) {
       GetPath(&filename);
     }
-    HDC printdc = PrnOpenDC(mQueue, "Mozilla", numCopies, printerDest, filename);
+    mPrintingStarted = PR_TRUE;
+    mPrintDC = PrnOpenDC(mQueue, "Mozilla", numCopies, printerDest, filename);
 
     double width, height;
     mPrintSettings->GetEffectivePageSize(&width, &height);
 #ifdef debug_thebes_print
     printf("nsDeviceContextSpecOS2::GetSurfaceForPrinter(): %fx%ftwips, copies=%d\n",
            width, height, numCopies);
 #endif
 
     // we need pixels, so scale from twips to the printer resolution
     // and take into account that CAPS_*_RESOLUTION are in px/m, default
     // to approx. 100dpi
     double hDPI = 3937., vDPI = 3937.;
     LONG value;
-    if (DevQueryCaps(printdc, CAPS_HORIZONTAL_RESOLUTION, 1, &value))
+    if (DevQueryCaps(mPrintDC, CAPS_HORIZONTAL_RESOLUTION, 1, &value))
       hDPI = value * 0.0254;
-    if (DevQueryCaps(printdc, CAPS_VERTICAL_RESOLUTION, 1, &value))
+    if (DevQueryCaps(mPrintDC, CAPS_VERTICAL_RESOLUTION, 1, &value))
       vDPI = value * 0.0254;
     width = width * hDPI / 1440;
     height = height * vDPI / 1440;
 #ifdef debug_thebes_print
-    printf("nsDeviceContextSpecOS2::GetSurfaceForPrinter(): %fx%fpx (res=%fx%f)\n",
-           width, height, hDPI, vDPI);
+    printf("nsDeviceContextSpecOS2::GetSurfaceForPrinter(): %fx%fpx (res=%fx%f)\n"
+           "  expected size: %7.2f MiB\n",
+           width, height, hDPI, vDPI, width*height*4./1024./1024.);
 #endif
 
     // Now pass the created DC into the thebes surface for printing.
     // It gets destroyed there.
     newSurface = new(std::nothrow)
-      gfxOS2Surface(printdc, gfxIntSize(int(ceil(width)), int(ceil(height))));
+      gfxOS2Surface(mPrintDC, gfxIntSize(int(ceil(width)), int(ceil(height))));
   }
   if (!newSurface) {
     *surface = nsnull;
     return NS_ERROR_FAILURE;
   }
   *surface = newSurface;
   NS_ADDREF(*surface);
   return NS_OK;
 }
 
+// Helper function to convert the string to the native codepage,
+// similar to UnicodeToCodepage() in nsDragService.cpp.
+char *GetACPString(const PRUnichar* aStr)
+{
+   nsString str(aStr);
+   if (str.Length() == 0) {
+      return nsnull;
+   }
+
+   nsAutoCharBuffer buffer;
+   PRInt32 bufLength;
+   WideCharToMultiByte(0, PromiseFlatString(str).get(), str.Length(),
+                       buffer, bufLength);
+   return ToNewCString(nsDependentCString(buffer.Elements()));
+}
+
 NS_IMETHODIMP nsDeviceContextSpecOS2::BeginDocument(PRUnichar* aTitle,
                                                     PRUnichar* aPrintToFileName,
                                                     PRInt32 aStartPage,
                                                     PRInt32 aEndPage)
 {
-  return NS_ERROR_NOT_IMPLEMENTED;
+#ifdef debug_thebes_print
+  printf("nsDeviceContextSpecOS2[%#x]::BeginPrinting(%s, %s)\n", (unsigned)this,
+         NS_LossyConvertUTF16toASCII(nsString(aTitle)).get(),
+         NS_LossyConvertUTF16toASCII(nsString(aPrintToFileName)).get());
+#endif
+  char *title = GetACPString(aTitle);
+  const PSZ pszGenericDocName = "Mozilla Document";
+  PSZ pszDocName = title ? title : pszGenericDocName;
+  LONG lResult = DevEscape(mPrintDC, DEVESC_STARTDOC,
+                           strlen(pszDocName) + 1, pszDocName,
+                           (PLONG)NULL, (PBYTE)NULL);
+  mPrintingStarted = PR_TRUE;
+  if (title) {
+    nsMemory::Free(title);
+  }
+
+  return lResult == DEV_OK ? NS_OK : NS_ERROR_GFX_PRINTER_STARTDOC;
 }
 
 NS_IMETHODIMP nsDeviceContextSpecOS2::EndDocument()
 {
-  return NS_ERROR_NOT_IMPLEMENTED;
+  LONG lOutCount = 2;
+  USHORT usJobID = 0;
+  LONG lResult = DevEscape(mPrintDC, DEVESC_ENDDOC, 0L, (PBYTE)NULL,
+                           &lOutCount, (PBYTE)&usJobID);
+  return lResult == DEV_OK ? NS_OK : NS_ERROR_GFX_PRINTER_ENDDOC;
 }
 
 NS_IMETHODIMP nsDeviceContextSpecOS2::BeginPage()
 {
-  return NS_ERROR_NOT_IMPLEMENTED;
+  if (mPrintingStarted) {
+    // we don't want an extra page break at the start of the document
+    mPrintingStarted = PR_FALSE;
+    return NS_OK;
+  }
+  LONG lResult = DevEscape(mPrintDC, DEVESC_NEWFRAME, 0L, (PBYTE)NULL,
+                           (PLONG)NULL, (PBYTE)NULL);
+  return lResult == DEV_OK ? NS_OK : NS_ERROR_GFX_PRINTER_STARTPAGE;
 }
 
 NS_IMETHODIMP nsDeviceContextSpecOS2::EndPage()
 {
-  return NS_ERROR_NOT_IMPLEMENTED;
+  return NS_OK;
 }
 
 //  Printer Enumerator
 nsPrinterEnumeratorOS2::nsPrinterEnumeratorOS2()
 {
 }
 
 NS_IMPL_ISUPPORTS1(nsPrinterEnumeratorOS2, nsIPrinterEnumerator)
--- a/widget/src/os2/nsDeviceContextSpecOS2.h
+++ b/widget/src/os2/nsDeviceContextSpecOS2.h
@@ -108,20 +108,21 @@ public:
  * @update  dc 2/16/98
  */
   virtual ~nsDeviceContextSpecOS2();
 
   static PRINTDLG PrnDlg;
   static nsresult SetPrintSettingsFromDevMode(nsIPrintSettings* aPrintSettings, ULONG printer);
 
 protected:
-
   OS2PrData mPrData;
   PRTQUEUE *mQueue;
   nsCOMPtr<nsIPrintSettings> mPrintSettings;
+  HDC mPrintDC;
+  PRPackedBool mPrintingStarted;
 };
 
 //-------------------------------------------------------------------------
 // Printer Enumerator
 //-------------------------------------------------------------------------
 class nsPrinterEnumeratorOS2 : public nsIPrinterEnumerator
 {
 public: