[OSX] Embedded plugins don't print - NPP_Print not called. b=191046 r=josh,kinetic
authorSteven Michaud <smichaud@pobox.com>
Mon, 20 Jul 2009 17:10:36 -0500
changeset 30472 860db9cc9e2bd58ad4b81aad2f7955ff615ff5d6
parent 30471 d347a454b3384885ff3844ba6f1b3c4ee0407b99
child 30473 02ff5f05a1a66d2b2bc015bf7fefd04790ec0a3e
push idunknown
push userunknown
push dateunknown
reviewersjosh, kinetic
bugs191046
milestone1.9.2a1pre
[OSX] Embedded plugins don't print - NPP_Print not called. b=191046 r=josh,kinetic
layout/generic/nsObjectFrame.cpp
modules/plugin/base/public/npapi.h
modules/plugin/base/public/nsplugindefs.h
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -1154,18 +1154,110 @@ nsObjectFrame::PrintPlugin(nsIRenderingC
   // we need to find out if we are windowless or not
   PRBool windowless = PR_FALSE;
   pi->GetValue(nsPluginInstanceVariable_WindowlessBool, (void *)&windowless);
   window.type  =  windowless ? nsPluginWindowType_Drawable : nsPluginWindowType_Window;
 
   window.clipRect.bottom = 0; window.clipRect.top = 0;
   window.clipRect.left = 0; window.clipRect.right = 0;
   
-// XXX platform specific printing code
-#if defined(XP_UNIX) && !defined(XP_MACOSX)
+// platform specific printing code
+#if defined(XP_MACOSX)
+  window.x = 0;
+  window.y = 0;
+  window.width = presContext->AppUnitsToDevPixels(mRect.width);
+  window.height = presContext->AppUnitsToDevPixels(mRect.height);
+
+  gfxContext *ctx = aRenderingContext.ThebesContext();
+  if (!ctx)
+    return;
+  gfxContextAutoSaveRestore save(ctx);
+
+  ctx->NewPath();
+
+  gfxRect rect(window.x, window.y, window.width, window.height);
+
+  ctx->Rectangle(rect);
+  ctx->Clip();
+
+  gfxQuartzNativeDrawing nativeDraw(ctx, rect);
+  CGContextRef cgContext = nativeDraw.BeginNativeDrawing();
+  if (!cgContext) {
+    nativeDraw.EndNativeDrawing();
+    return;
+  }
+
+  window.clipRect.right = window.width;
+  window.clipRect.bottom = window.height;
+  window.type = nsPluginWindowType_Drawable;
+
+  Rect gwBounds;
+  ::SetRect(&gwBounds, 0, 0, window.width, window.height);
+
+  nsTArray<char> buffer(window.width * window.height * 4);
+  CGColorSpaceRef cspace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+  if (!cspace) {
+    nativeDraw.EndNativeDrawing();
+    return;
+  }
+  CGContextRef cgBuffer =
+    ::CGBitmapContextCreate(buffer.Elements(), 
+                            window.width, window.height, 8, window.width * 4,
+                            cspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedFirst);
+  ::CGColorSpaceRelease(cspace);
+  if (!cgBuffer) {
+    nativeDraw.EndNativeDrawing();
+    return;
+  }
+  GWorldPtr gWorld;
+  if (::NewGWorldFromPtr(&gWorld, k32ARGBPixelFormat, &gwBounds, NULL, NULL, 0,
+                         buffer.Elements(), window.width * 4) != noErr) {
+    ::CGContextRelease(cgBuffer);
+    nativeDraw.EndNativeDrawing();
+    return;
+  }
+
+  window.clipRect.right = window.width;
+  window.clipRect.bottom = window.height;
+  window.type = nsPluginWindowType_Drawable;
+  // Setting nsPluginPrint/NPPrint.print.embedPrint.window.window to
+  // &GWorldPtr and nsPluginPrint/NPPrint.print.embedPrint.platformPrint to
+  // GWorldPtr isn't any kind of standard (it's not documented anywhere).
+  // But that's what WebKit does.  And it's what the Flash plugin (apparently
+  // the only NPAPI plugin on OS X to support printing) seems to expect.  So
+  // we do the same.  The Flash plugin uses the CoreGraphics drawing mode.
+  // But a GWorldPtr should be usable in either CoreGraphics or QuickDraw
+  // drawing mode.  See bug 191046.
+  window.window = reinterpret_cast<nsPluginPort *>(&gWorld);
+  npprint.print.embedPrint.platformPrint = gWorld;
+  npprint.print.embedPrint.window = window;
+  nsresult rv = pi->Print(&npprint);
+
+  ::CGContextSaveGState(cgContext);
+  ::CGContextTranslateCTM(cgContext, 0.0f, float(window.height));
+  ::CGContextScaleCTM(cgContext, 1.0f, -1.0f);
+  CGImageRef image = ::CGBitmapContextCreateImage(cgBuffer);
+  if (!image) {
+    ::CGContextRestoreGState(cgContext);
+    ::CGContextRelease(cgBuffer);
+    ::DisposeGWorld(gWorld);
+    nativeDraw.EndNativeDrawing();
+    return;
+  }
+  ::CGContextDrawImage(cgContext,
+                       ::CGRectMake(0, 0, window.width, window.height),
+                       image);
+  ::CGImageRelease(image);
+  ::CGContextRestoreGState(cgContext);
+  ::CGContextRelease(cgBuffer);
+
+  ::DisposeGWorld(gWorld);
+
+  nativeDraw.EndNativeDrawing();
+#elif defined(XP_UNIX)
 
   /* XXX this just flat-out doesn't work in a thebes world --
    * RenderEPS is a no-op.  So don't bother to do any work here.
    */
 #if 0
     /* UNIX does things completely differently:
    * We call the plugin and it sends generated PostScript data into a
    * file handle we provide. If the plugin returns with success we embed
--- a/modules/plugin/base/public/npapi.h
+++ b/modules/plugin/base/public/npapi.h
@@ -131,16 +131,22 @@ typedef unsigned char NPBool;
 typedef int16_t       NPError;
 typedef int16_t       NPReason;
 typedef char*         NPMIMEType;
 
 /*----------------------------------------------------------------------*/
 /*                       Structures and definitions                     */
 /*----------------------------------------------------------------------*/
 
+#if !defined(__LP64__)
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#pragma options align=mac68k
+#endif
+#endif /* __LP64__ */
+
 /*
  *  NPP is a plug-in's opaque instance handle
  */
 typedef struct _NPP
 {
   void* pdata;      /* plug-in private data */
   void* ndata;      /* netscape private data */
 } NPP_t;
@@ -505,16 +511,21 @@ enum NPEventType {
  */
 #define NP_NORMAL     1
 #define NP_SEEK       2
 #define NP_ASFILE     3
 #define NP_ASFILEONLY 4
 
 #define NP_MAXREADY (((unsigned)(~0)<<1)>>1)
 
+#if !defined(__LP64__)
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#pragma options align=reset
+#endif
+#endif /* __LP64__ */
 
 /*----------------------------------------------------------------------*/
 /*       Error and Reason Code definitions                              */
 /*----------------------------------------------------------------------*/
 
 /*
  * Values of type NPError:
  */
--- a/modules/plugin/base/public/nsplugindefs.h
+++ b/modules/plugin/base/public/nsplugindefs.h
@@ -109,16 +109,22 @@ RCDATA NS_INFO_ProductName       { "NPAV
 #define NS_INFO_LegalCopyright      10
 #define NS_INFO_OriginalFilename    11
 
 #ifndef RC_INVOKED
 
 ////////////////////////////////////////////////////////////////////////////////
 // Structures and definitions
 
+#if !defined(__LP64__)
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#pragma options align=mac68k
+#endif
+#endif /* __LP64__ */
+
 struct nsByteRange {
     PRInt32             offset; 	/* negative offset means from the end */
     PRUint32            length;
     struct nsByteRange* next;
 };
 
 struct nsPluginRect {
     PRUint16            top;
@@ -372,14 +378,20 @@ enum nsPluginReason {
 // Classes that must be implemented by the plugin DLL:
 class nsIPlugin;                        // plugin class (MIME-type handler)
 class nsIPluginInstance;                // plugin instance
 
 // Classes that are implemented by the browser:
 class nsIPluginTagInfo;                 // describes html tag
 ////////////////////////////////////////////////////////////////////////////////
 
+#if !defined(__LP64__)
+#if defined(XP_MAC) || defined(XP_MACOSX)
+#pragma options align=reset
+#endif
+#endif /* __LP64__ */
+
 #endif /* RC_INVOKED */
 #ifdef __OS2__
 #pragma pack()
 #endif
 
 #endif // nsplugindefs_h___