Back to index

lightning-sunbird  0.9+nobinonly
nsRenderingContextXp.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
00024  *   Julien Lafon <julien.lafon@gmail.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039  
00040 #include "nsRenderingContextXp.h"
00041 #include "nsFontMetricsXlib.h"
00042 #include "nsDeviceContextXP.h"
00043 #include "nsCompressedCharMap.h"
00044 #include "xlibrgb.h"
00045 #include "prprf.h"
00046 #include "prmem.h"
00047 #include "prlog.h"
00048 #include "nsGCCache.h"
00049 #include "imgIContainer.h"
00050 #include "gfxIImageFrame.h"
00051 #include "nsIInterfaceRequestor.h"
00052 #include "nsIInterfaceRequestorUtils.h"
00053 #include "nsLocalFile.h"
00054 #include <sys/mman.h>
00055 #include <errno.h>
00056 
00057 #ifdef PR_LOGGING 
00058 static PRLogModuleInfo *RenderingContextXpLM = PR_NewLogModule("RenderingContextXp");
00059 #endif /* PR_LOGGING */ 
00060 
00061 nsRenderingContextXp::nsRenderingContextXp()
00062   : nsRenderingContextXlib(),
00063   mPrintContext(nsnull)
00064 {
00065 }
00066 
00067 nsRenderingContextXp::~nsRenderingContextXp()
00068 {
00069 }
00070 
00071 NS_IMETHODIMP
00072 nsRenderingContextXp::Init(nsIDeviceContext* aContext)
00073 {
00074   PR_LOG(RenderingContextXpLM, PR_LOG_DEBUG, ("nsRenderingContextXp::Init(nsIDeviceContext *)\n"));
00075 
00076   NS_ENSURE_TRUE(nsnull != aContext, NS_ERROR_NULL_POINTER);
00077   mContext = aContext;
00078   if (mContext) {
00079      nsIDeviceContext *dc = mContext;     
00080      NS_STATIC_CAST(nsDeviceContextXp *,dc)->GetPrintContext(mPrintContext);
00081   }
00082   NS_ENSURE_TRUE(nsnull != mPrintContext, NS_ERROR_NULL_POINTER);
00083 
00084   mPrintContext->GetXlibRgbHandle(mXlibRgbHandle);
00085   mDisplay = xxlib_rgb_get_display(mXlibRgbHandle);
00086 
00087   /* A printer usually does not support things like multiple drawing surfaces
00088    * (nor "offscreen" drawing surfaces... would be quite difficult to 
00089    * implement) - however the Xprint API supports offscreen surfaces for
00090    * all DDX implementations.
00091    */
00092   mOffscreenSurface = mSurface = mPrintContext; 
00093   UpdateGC(); /* Fill |mGC| */
00094   mPrintContext->SetGC(mGC);
00095 
00096   return CommonInit();
00097 }
00098 
00099 NS_IMETHODIMP nsRenderingContextXp::Init(nsIDeviceContext* aContext, nsIWidget *aWidget) 
00100 { 
00101   PR_LOG(RenderingContextXpLM, PR_LOG_DEBUG, ("nsRenderingContextXp::Init(nsIDeviceContext* aContext, nsIWidget *aWidget)\n"));
00102   return NS_ERROR_NOT_IMPLEMENTED;
00103 }
00104 
00105 NS_IMETHODIMP nsRenderingContextXp::Init(nsIDeviceContext* aContext, nsIDrawingSurface* aSurface)
00106 {
00107   PR_LOG(RenderingContextXpLM, PR_LOG_DEBUG, ("nsRenderingContextXp::Init(nsIDeviceContext* aContext, nsIDrawingSurface* aSurface)\n"));
00108   return NS_ERROR_NOT_IMPLEMENTED;
00109 }
00110 
00111 NS_IMETHODIMP
00112 nsRenderingContextXp::LockDrawingSurface(PRInt32 aX, PRInt32 aY,
00113                                          PRUint32 aWidth, PRUint32 aHeight,
00114                                          void **aBits,
00115                                          PRInt32 *aStride,
00116                                          PRInt32 *aWidthBytes,
00117                                          PRUint32 aFlags)
00118 {
00119   PR_LOG(RenderingContextXpLM, PR_LOG_DEBUG, ("nsRenderingContextXp::LockDrawingSurface()\n"));
00120   PushState();
00121   return NS_OK;
00122 }
00123 
00124 NS_IMETHODIMP
00125 nsRenderingContextXp::UnlockDrawingSurface(void)
00126 {
00127   PR_LOG(RenderingContextXpLM, PR_LOG_DEBUG, ("nsRenderingContextXp::UnlockDrawingSurface()\n"));
00128   PopState();
00129   return NS_OK;
00130 }
00131 
00132 NS_IMETHODIMP nsRenderingContextXp::DrawImage(imgIContainer *aImage, const nsRect & aSrcRect, const nsRect & aDestRect)
00133 {
00134   PR_LOG(RenderingContextXpLM, PR_LOG_DEBUG, ("nsRenderingContextXp::DrawImage()\n"));
00135 
00136   nsRect dr = aDestRect;
00137   mTranMatrix->TransformCoord(&dr.x, &dr.y, &dr.width, &dr.height);
00138 
00139   nsCOMPtr<gfxIImageFrame> iframe;
00140   aImage->GetCurrentFrame(getter_AddRefs(iframe));
00141   if (!iframe) 
00142     return NS_ERROR_FAILURE;
00143 
00144   nsCOMPtr<nsIImage> img(do_GetInterface(iframe));
00145   if (!img) 
00146     return NS_ERROR_FAILURE;
00147 
00148   // doesn't it seem like we should use more of the params here?
00149   // img->Draw(*this, surface, sr.x, sr.y, sr.width, sr.height, dr.x, dr.y, dr.width, dr.height);
00150 
00151   nsRect sr = aSrcRect;
00152   mTranMatrix->TransformCoord(&sr.x, &sr.y, &sr.width, &sr.height);
00153   sr.x = aSrcRect.x;
00154   sr.y = aSrcRect.y;
00155   mTranMatrix->TransformNoXLateCoord(&sr.x, &sr.y);
00156 
00157   UpdateGC();
00158   return mPrintContext->DrawImage(mSurface->GetDrawable(),
00159                                   mGC, img,
00160                                   sr.x, sr.y,
00161                                   sr.width, sr.height,
00162                                   dr.x, dr.y,
00163                                   dr.width, dr.height);
00164 }
00165 
00166 #ifdef JULIEN_NOTNOW
00167 static
00168 void TilePixmap(Display *dpy, Pixmap src, Pixmap dest, PRInt32 aSXOffset,
00169                 PRInt32 aSYOffset, const nsRect &destRect,
00170                 const nsRect &clipRect, PRBool useClip)
00171 {
00172   GC gc;
00173   XGCValues values;
00174   unsigned long valuesMask;
00175   memset(&values, 0, sizeof(XGCValues));
00176   values.fill_style = FillTiled;
00177   values.tile = src;
00178   values.ts_x_origin = destRect.x - aSXOffset;
00179   values.ts_y_origin = destRect.y - aSYOffset;
00180   valuesMask = GCTile | GCTileStipXOrigin | GCTileStipYOrigin | GCFillStyle;
00181   gc = XCreateGC(dpy, src, valuesMask, &values);
00182 
00183   if (useClip) {
00184     XRectangle xrectangle;
00185     xrectangle.x      = clipRect.x;
00186     xrectangle.y      = clipRect.y;
00187     xrectangle.width  = clipRect.width;
00188     xrectangle.height = clipRect.height;
00189     XSetClipRectangles(dpy, gc, 0, 0, &xrectangle, 1, Unsorted);
00190   }
00191 
00192   XFillRectangle(dpy, dest, gc, destRect.x, destRect.y,
00193                  destRect.width, destRect.height);
00194 
00195   XFreeGC(dpy, gc);
00196 }
00197 #endif /* JULIEN_NOTNOW */
00198 
00199 NS_IMETHODIMP
00200 nsRenderingContextXp::DrawTile(imgIContainer *aImage,
00201                                nscoord aSXOffset,
00202                                nscoord aSYOffset,
00203                                const nsRect *aTileRect)
00204 {
00205   PR_LOG(RenderingContextXpLM, PR_LOG_DEBUG,
00206          ("nsRenderingContextXp::DrawTile(imgIContainer *aImage, nscoord aXImageStart, nscoord aYImageStart, const nsRect *aTargetRect)\n"));
00207 
00208 /* xxx_julien: Either this code or the PDF DDX needs a fix */
00209 #ifdef JULIEN_NOTNOW    
00210   nsCOMPtr<gfxIImageFrame> iframe;
00211   aImage->GetCurrentFrame(getter_AddRefs(iframe));
00212   if (!iframe) 
00213     return NS_ERROR_FAILURE;
00214 
00215   nsCOMPtr<nsIImage> img(do_GetInterface(iframe));
00216   if (!img) 
00217     return NS_ERROR_FAILURE;
00218 
00219   PushState();
00220 
00221   nscoord imgwidth, imgheight;
00222   aImage->GetWidth(&imgwidth);
00223   aImage->GetHeight(&imgheight);
00224 
00225   imgwidth  = NSToCoordRound(imgwidth*mP2T);
00226   imgheight = NSToCoordRound(imgheight*mP2T);
00227   
00228   Drawable srcdrawable;
00229   Drawable destdrawable;
00230   mSurface->GetDrawable(destdrawable);
00231 
00232   UpdateGC(); 
00233   srcdrawable = XCreatePixmap(mDisplay, destdrawable,
00234                               imgwidth, imgheight,
00235                               xxlib_rgb_get_depth(mXlibRgbHandle));
00236 
00237   XGCValues     values;
00238   unsigned long valuesMask = 0;
00239   nsRenderingContextXlibContext *rcContext;
00240   nsIDeviceContext *dc = mContext;
00241   NS_STATIC_CAST(nsDeviceContextX *, dc)->GetRCContext(rcContext);
00242   xGC *xgc = rcContext->mGcCache.GetGC(mDisplay, srcdrawable, valuesMask, &values, NULL);
00243 
00244   mPrintContext->DrawImage(srcdrawable,
00245                            xgc, img,
00246                            0, 0,
00247                            img->GetWidth(), img->GetHeight(),
00248                            0, 0,
00249                            imgwidth, imgheight);
00250 
00251   /* Xlib API can tile for us */
00252   nsRect clipRect;
00253   PRBool isValid;
00254 
00255   GetClipRect(clipRect, isValid);
00256   TilePixmap(mDisplay, srcdrawable, destdrawable, aSXOffset, aSYOffset,
00257              *aTileRect, clipRect, PR_FALSE);
00258 
00259   xgc->Release();
00260   XFreePixmap(mDisplay, srcdrawable);
00261   
00262   PopState();
00263 #endif /* JULIEN_NOTNOW */
00264   return NS_OK;
00265 }
00266 
00267 NS_IMETHODIMP
00268 nsRenderingContextXp::RenderEPS(const nsRect& aRect, FILE *aDataFile)
00269 {
00270   nsresult             rv;
00271   int                  fd;
00272   const unsigned char *data;
00273   size_t               datalen;
00274 
00275   PR_LOG(RenderingContextXpLM, PR_LOG_DEBUG, ("nsRenderingContextXp::RenderPostScriptDataFragment()\n"));
00276 
00277   /* Get file size */
00278   fseek(aDataFile, 0, SEEK_END);
00279   datalen = ftell(aDataFile);
00280 
00281   PR_LOG(RenderingContextXpLM, PR_LOG_DEBUG, ("file size=%ld\n", (long)datalen));  
00282 
00283   /* Safeguard against bogus values
00284    * (make sure we clamp the size to a reasonable value (say... 128 MB)) */
00285   if (datalen <= 0 || datalen > (128 * 1024 * 1024)) {
00286     PR_LOG(RenderingContextXpLM, PR_LOG_DEBUG, ("error: file size %ld too large\n", (long)datalen));
00287     return NS_ERROR_FAILURE;
00288   }
00289   
00290   fflush(aDataFile);
00291   fd = fileno(aDataFile);
00292   PR_LOG(RenderingContextXpLM, PR_LOG_DEBUG, ("fileno=%d\n", fd));  
00293   data = (const unsigned char *)mmap(0, datalen, PROT_READ, MAP_SHARED, fd, 0); 
00294   if (MAP_FAILED == data) {
00295     int saved_errno = errno;
00296     PR_LOG(RenderingContextXpLM, PR_LOG_DEBUG, ("mmap() failure, errno=%s/%d\n",
00297            strerror(saved_errno), saved_errno));  
00298     return nsresultForErrno(saved_errno);
00299   }
00300 
00301   PushState();
00302 
00303   nsRect trect = aRect;
00304   mTranMatrix->TransformCoord(&trect.x, &trect.y, &trect.width, &trect.height);
00305   UpdateGC();
00306   rv = mPrintContext->RenderEPS(mSurface->GetDrawable(), trect, data, datalen);
00307 
00308   PopState();
00309   
00310   munmap((char *)data, datalen);
00311 
00312   return rv;
00313 }
00314 
00315 
00316