[OS/2] Bug 369791: adapt plugin code to compile with cairo-os2, this in principle allows plugin content to be printed and windowless plugins to display, r=mkaply, a1.9+=damons
authormozilla@weilbacher.org
Mon, 10 Mar 2008 17:10:55 -0700
changeset 12859 eaabea9f8465b5589d4cf6689a9fe364b8997a2b
parent 12858 0663898c295eee4694efe9ab056a08d9a9db49ea
child 12860 efc6c7ab3f328668914c0c669ee5e83e1ecf621d
push idunknown
push userunknown
push dateunknown
reviewersmkaply, a1.9
bugs369791
milestone1.9b5pre
[OS/2] Bug 369791: adapt plugin code to compile with cairo-os2, this in principle allows plugin content to be printed and windowless plugins to display, r=mkaply, a1.9+=damons
gfx/public/nsIRenderingContext.h
gfx/src/thebes/nsThebesRenderingContext.cpp
layout/generic/nsObjectFrame.cpp
--- a/gfx/public/nsIRenderingContext.h
+++ b/gfx/public/nsIRenderingContext.h
@@ -536,17 +536,18 @@ public:
                         PRInt32 aFontID = -1,
                         const nscoord* aSpacing = nsnull) = 0;
 
   enum GraphicDataType {
     NATIVE_CAIRO_CONTEXT = 1,
     NATIVE_GDK_DRAWABLE = 2,
     NATIVE_WINDOWS_DC = 3,
     NATIVE_MAC_THING = 4,
-    NATIVE_THEBES_CONTEXT = 5
+    NATIVE_THEBES_CONTEXT = 5,
+    NATIVE_OS2_PS = 6
   };
   /**
    * Retrieve the native graphic data given by aType. Return
    * nsnull if not available.
    */
   virtual void* GetNativeGraphicData(GraphicDataType aType) = 0;
 
 #ifdef MOZ_MATHML
--- a/gfx/src/thebes/nsThebesRenderingContext.cpp
+++ b/gfx/src/thebes/nsThebesRenderingContext.cpp
@@ -715,16 +715,24 @@ nsThebesRenderingContext::GetNativeGraph
 #ifdef XP_WIN
     if (aType == NATIVE_WINDOWS_DC) {
         nsRefPtr<gfxASurface> surf(mThebes->CurrentSurface());
         if (!surf || surf->CairoStatus())
             return nsnull;
         return static_cast<gfxWindowsSurface*>(static_cast<gfxASurface*>(surf.get()))->GetDC();
     }
 #endif
+#ifdef XP_OS2
+    if (aType == NATIVE_OS2_PS) {
+        nsRefPtr<gfxASurface> surf(mThebes->CurrentSurface());
+        if (!surf || surf->CairoStatus())
+            return nsnull;
+        return (void*)(static_cast<gfxOS2Surface*>(static_cast<gfxASurface*>(surf.get()))->GetPS());
+    }
+#endif
 
     return nsnull;
 }
 
 NS_IMETHODIMP
 nsThebesRenderingContext::PushFilter(const nsRect& twRect, PRBool aAreaIsOpaque, float aOpacity)
 {
     PR_LOG(gThebesGFXLog, PR_LOG_DEBUG,
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -356,16 +356,18 @@ public:
   
 #ifdef XP_WIN
   void Paint(const nsRect& aDirtyRect, HDC ndc);
 #elif defined(XP_MACOSX)
   void Paint(const nsRect& aDirtyRect);  
 #elif defined(MOZ_X11)
   void Paint(nsIRenderingContext& aRenderingContext,
              const nsRect& aDirtyRect);
+#elif defined(XP_OS2)
+  void Paint(const nsRect& aDirtyRect, HPS aHPS);
 #endif
 
   // nsITimerCallback interface
   NS_DECL_NSITIMERCALLBACK
   
   void CancelTimer();
   void StartTimer(unsigned int aDelay);
 
@@ -440,17 +442,17 @@ private:
     nsPluginWindow* mWindow;
     nsIPluginInstance* mInstance;
     const nsIntRect& mDirtyRect;
   };
 #endif
 
 };
 
-#if defined(XP_WIN) || (defined(DO_DIRTY_INTERSECT) && defined(XP_MACOSX)) || defined(MOZ_X11)
+#if defined(XP_WIN) || (defined(DO_DIRTY_INTERSECT) && defined(XP_MACOSX)) || defined(MOZ_X11) || defined(XP_OS2)
 static void ConvertAppUnitsToPixels(const nsPresContext& aPresContext, const nsRect& aTwipsRect, nsIntRect& aPixelRect);
 #endif
 
   // Mac specific code to fix up port position and clip during paint
 #ifdef XP_MACOSX
 
 #ifdef DO_DIRTY_INTERSECT
   // convert relative coordinates to absolute
@@ -1178,16 +1180,25 @@ nsObjectFrame::PrintPlugin(nsIRenderingC
   /* Send data to printer */
   rv = aRenderingContext.RenderEPS(aDirtyRect, plugintmpfile);
 
   fclose(plugintmpfile);
 
   PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, ("plugin printing done, return code is %lx\n", (long)rv));
 #endif
 
+#elif defined(XP_OS2)
+  void *hps = aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_OS2_PS);
+  if (!hps)
+    return;
+
+  npprint.print.embedPrint.platformPrint = hps;
+  npprint.print.embedPrint.window = window;
+  // send off print info to plugin
+  rv = pi->Print(&npprint);
 #elif defined(XP_WIN)
 
   /* On Windows, we use the win32 printing surface to print.  This, in
    * turn, uses the Cairo paginated surface, which in turn uses the
    * meta surface to record all operations and then play them back.
    * This doesn't work too well for plugins, because if plugins render
    * directly into the DC, the meta surface won't have any knowledge
    * of them, and so at the end when it actually does the replay step,
@@ -1337,19 +1348,17 @@ nsObjectFrame::PaintPlugin(nsIRenderingC
   if (mInstanceOwner)
     {
       nsPluginWindow * window;
       mInstanceOwner->GetWindow(window);
 
       if (window->type == nsPluginWindowType_Drawable)
         mInstanceOwner->Paint(aRenderingContext, aDirtyRect);
     }
-#elif defined (XP_WIN) // || defined(XP_OS2)
-  // XXX for OS/2 we need to overhaul this for Cairo builds
-  //     for now just ignore plugin stuff
+#elif defined (XP_WIN) || defined(XP_OS2)
   nsCOMPtr<nsIPluginInstance> inst;
   GetPluginInstance(*getter_AddRefs(inst));
   if (inst) {
     // Look if it's windowless
     nsPluginWindow * window;
     mInstanceOwner->GetWindow(window);
 
     if (window->type == nsPluginWindowType_Drawable) {
@@ -1390,29 +1399,49 @@ nsObjectFrame::PaintPlugin(nsIRenderingC
       gfxFloat xoff, yoff;
       nsRefPtr<gfxASurface> surf = ctx->CurrentSurface(&xoff, &yoff);
 
       if (surf->CairoStatus() != 0) {
         NS_WARNING("Plugin is being asked to render to a surface that's in error!");
         return;
       }
 
+#ifdef XP_WIN
       // check if we need to update hdc
       HDC hdc = (HDC)aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC);
 
       if (reinterpret_cast<HDC>(window->window) != hdc) {
         window->window = reinterpret_cast<nsPluginPort*>(hdc);
         doupdatewindow = PR_TRUE;
       }
 
       SaveDC(hdc);
 
       POINT origViewportOrigin;
       GetViewportOrgEx(hdc, &origViewportOrigin);
       SetViewportOrgEx(hdc, origViewportOrigin.x + (int) xoff, origViewportOrigin.y + (int) yoff, NULL);
+#else // do something similar on OS/2
+      // check if we need to update the PS
+      HPS hps = (HPS)aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_OS2_PS);
+      if (reinterpret_cast<HPS>(window->window) != hps) {
+        window->window = reinterpret_cast<nsPluginPort*>(hps);
+        doupdatewindow = PR_TRUE;
+      }
+      LONG lPSid = GpiSavePS(hps);
+      RECTL rclViewport;
+      if (GpiQueryDevice(hps) != NULLHANDLE) { // ensure that we have an associated HDC
+        if (GpiQueryPageViewport(hps, &rclViewport)) {
+          rclViewport.xLeft += (LONG)xoff;
+          rclViewport.xRight += (LONG)xoff;
+          rclViewport.yBottom += (LONG)yoff;
+          rclViewport.yTop += (LONG)yoff;
+          GpiSetPageViewport(hps, &rclViewport);
+        }
+      }
+#endif
 
       if ((window->x != origin.x) || (window->y != origin.y)) {
         window->x = origin.x;
         window->y = origin.y;
         doupdatewindow = PR_TRUE;
       }
 
       // if our location or visible area has changed, we need to tell the plugin
@@ -1455,23 +1484,30 @@ nsObjectFrame::PaintPlugin(nsIRenderingC
 
                 inst->HandleEvent(&pluginEvent, &eventHandled);
               }
 #endif
 
         inst->SetWindow(window);        
       }
 
+#ifdef XP_WIN
       // FIXME - Bug 385435:
       // This expects a dirty rect relative to the plugin's rect
       // XXX I wonder if this breaks if we give the frame a border so the
       // frame origin and plugin origin are not the same
       mInstanceOwner->Paint(aDirtyRect, hdc);
 
       RestoreDC(hdc, -1);
+#else // do something similar on OS/2
+      mInstanceOwner->Paint(aDirtyRect, hps);
+      if (lPSid >= 1) {
+        GpiRestorePS(hps, lPSid);
+      }
+#endif
       surf->MarkDirty();
     }
   }
 #endif
 }
 
 NS_IMETHODIMP
 nsObjectFrame::HandleEvent(nsPresContext* aPresContext,
@@ -3821,16 +3857,46 @@ void nsPluginInstanceOwner::Paint(const 
   pluginEvent.event = WM_PAINT;
   pluginEvent.wParam = (uint32)ndc;
   pluginEvent.lParam = (uint32)&drc;
   PRBool eventHandled = PR_FALSE;
   mInstance->HandleEvent(&pluginEvent, &eventHandled);
 }
 #endif
 
+#ifdef XP_OS2
+void nsPluginInstanceOwner::Paint(const nsRect& aDirtyRect, HPS aHPS)
+{
+  if (!mInstance || !mOwner)
+    return;
+
+  nsPluginWindow * window;
+  GetWindow(window);
+  nsRect relDirtyRect = nsRect(aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
+  nsIntRect relDirtyRectInPixels;
+  ConvertAppUnitsToPixels(*mOwner->PresContext(), relDirtyRect,
+                          relDirtyRectInPixels);
+
+  // we got dirty rectangle in relative window coordinates, but we
+  // need it in absolute units and in the (left, top, right, bottom) form
+  RECTL rectl;
+  rectl.xLeft   = relDirtyRectInPixels.x + window->x;
+  rectl.yBottom = relDirtyRectInPixels.y + window->y;
+  rectl.xRight  = rectl.xLeft + relDirtyRectInPixels.width;
+  rectl.yTop    = rectl.yBottom + relDirtyRectInPixels.height;
+
+  nsPluginEvent pluginEvent;
+  pluginEvent.event = WM_PAINT;
+  pluginEvent.wParam = (uint32)aHPS;
+  pluginEvent.lParam = (uint32)&rectl;
+  PRBool eventHandled = PR_FALSE;
+  mInstance->HandleEvent(&pluginEvent, &eventHandled);
+}
+#endif
+
 #ifdef MOZ_X11
 void nsPluginInstanceOwner::Paint(nsIRenderingContext& aRenderingContext,
                                   const nsRect& aDirtyRect)
 {
   if (!mInstance || !mOwner)
     return;
  
   nsPluginWindow* window;
@@ -4179,17 +4245,17 @@ NS_IMETHODIMP nsPluginInstanceOwner::Cre
   return rv;
 }
 
 void nsPluginInstanceOwner::SetPluginHost(nsIPluginHost* aHost)
 {
   mPluginHost = aHost;
 }
 
-#if defined(XP_WIN) || (defined(DO_DIRTY_INTERSECT) && defined(XP_MACOSX)) || defined(MOZ_X11)
+#if defined(XP_WIN) || (defined(DO_DIRTY_INTERSECT) && defined(XP_MACOSX)) || defined(MOZ_X11) || defined(XP_OS2)
 // convert frame coordinates from twips to pixels
 static void ConvertAppUnitsToPixels(const nsPresContext& aPresContext, const nsRect& aTwipsRect, nsIntRect& aPixelRect)
 {
   aPixelRect.x = aPresContext.AppUnitsToDevPixels(aTwipsRect.x);
   aPixelRect.y = aPresContext.AppUnitsToDevPixels(aTwipsRect.y);
   aPixelRect.width = aPresContext.AppUnitsToDevPixels(aTwipsRect.width);
   aPixelRect.height = aPresContext.AppUnitsToDevPixels(aTwipsRect.height);
 }