LCOV - app.info - gfx/thebes/gfxDrawable.cpp

LCOV - code coverage report
| Current view: | directory - gfx/thebes - gfxDrawable.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 96 | 0 | 0.0 %
| Date: | 2012-06-02 | Functions: | 14 | 0 | 0.0 %

           1                 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  * ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozilla.org code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is Markus Stange.
          18                 :  * Portions created by the Initial Developer are Copyright (C) 2010
          19                 :  * the Initial Developer. All Rights Reserved.
          20                 :  *
          21                 :  * Contributor(s):
          22                 :  *
          23                 :  * Alternatively, the contents of this file may be used under the terms of
          24                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          25                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          26                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          27                 :  * of those above. If you wish to allow use of your version of this file only
          28                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          29                 :  * use your version of this file under the terms of the MPL, indicate your
          30                 :  * decision by deleting the provisions above and replace them with the notice
          31                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          32                 :  * the provisions above, a recipient may use your version of this file under
          33                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          34                 :  *
          35                 :  * ***** END LICENSE BLOCK ***** */
          36                 :
          37                 : #include "gfxDrawable.h"
          38                 : #include "gfxASurface.h"
          39                 : #include "gfxContext.h"
          40                 : #include "gfxPlatform.h"
          41                 : #include "mozilla/arm.h"
          42                 : #ifdef MOZ_X11
          43                 : #include "cairo.h"
          44                 : #include "gfxXlibSurface.h"
          45                 : #endif
          46                 :
          47               0 : gfxSurfaceDrawable::gfxSurfaceDrawable(gfxASurface* aSurface,
          48                 :                                        const gfxIntSize aSize,
          49                 :                                        const gfxMatrix aTransform)
          50                 :  : gfxDrawable(aSize)
          51                 :  , mSurface(aSurface)
          52               0 :  , mTransform(aTransform)
          53                 : {
          54               0 : }
          55                 :
          56                 : static gfxMatrix
          57               0 : DeviceToImageTransform(gfxContext* aContext,
          58                 :                        const gfxMatrix& aUserSpaceToImageSpace)
          59                 : {
          60                 :     gfxFloat deviceX, deviceY;
          61                 :     nsRefPtr<gfxASurface> currentTarget =
          62               0 :         aContext->CurrentSurface(&deviceX, &deviceY);
          63               0 :     gfxMatrix currentMatrix = aContext->CurrentMatrix();
          64               0 :     gfxMatrix deviceToUser = gfxMatrix(currentMatrix).Invert();
          65               0 :     deviceToUser.Translate(-gfxPoint(-deviceX, -deviceY));
          66               0 :     return gfxMatrix(deviceToUser).Multiply(aUserSpaceToImageSpace);
          67                 : }
          68                 :
          69                 : static void
          70               0 : PreparePatternForUntiledDrawing(gfxPattern* aPattern,
          71                 :                                 const gfxMatrix& aDeviceToImage,
          72                 :                                 gfxASurface *currentTarget,
          73                 :                                 const gfxPattern::GraphicsFilter aDefaultFilter)
          74                 : {
          75               0 :     if (!currentTarget) {
          76                 :         // This happens if we're dealing with an Azure target.
          77               0 :         aPattern->SetExtend(gfxPattern::EXTEND_PAD);
          78               0 :         aPattern->SetFilter(aDefaultFilter);
          79               0 :         return;
          80                 :     }
          81                 :
          82                 :     // In theory we can handle this using cairo's EXTEND_PAD,
          83                 :     // but implementation limitations mean we have to consult
          84                 :     // the surface type.
          85               0 :     switch (currentTarget->GetType()) {
          86                 :
          87                 :         // The printing surfaces don't natively support or need
          88                 :         // EXTEND_PAD for padding the edges. Using EXTEND_PAD this way
          89                 :         // is suboptimal as it will result in the printing surface
          90                 :         // creating a new image for each fill operation. The pattern
          91                 :         // will be painted to the image to pad out the pattern, then
          92                 :         // the new image will be used as the source. This increases
          93                 :         // printing time and memory use, and prevents the use of mime
          94                 :         // data from cairo_surface_set_mime_data(). Bug 691061.
          95                 :         case gfxASurface::SurfaceTypePDF:
          96                 :         case gfxASurface::SurfaceTypePS:
          97                 :         case gfxASurface::SurfaceTypeWin32Printing:
          98               0 :             aPattern->SetExtend(gfxPattern::EXTEND_NONE);
          99               0 :             aPattern->SetFilter(aDefaultFilter);
         100               0 :             break;
         101                 :
         102                 : #ifdef MOZ_X11
         103                 :         case gfxASurface::SurfaceTypeXlib:
         104                 :         {
         105                 :             // See bugs 324698, 422179, and 468496.  This is a workaround for
         106                 :             // XRender's RepeatPad not being implemented correctly on old X
         107                 :             // servers.
         108                 :             //
         109                 :             // In this situation, cairo avoids XRender and instead reads back
         110                 :             // to perform EXTEND_PAD with pixman.  This is too slow so we
         111                 :             // avoid EXTEND_PAD and set the filter to CAIRO_FILTER_FAST ---
         112                 :             // otherwise, pixman's sampling will sample transparency for the
         113                 :             // outside edges and we'll get blurry edges.
         114                 :             //
         115                 :             // But don't do this for simple downscales because it's horrible.
         116                 :             // Downscaling means that device-space coordinates are
         117                 :             // scaled *up* to find the image pixel coordinates.
         118                 :             //
         119                 :             // Cairo, and hence Gecko, can use RepeatPad on Xorg 1.7. We
         120                 :             // enable EXTEND_PAD provided that we're running on a recent
         121                 :             // enough X server.
         122                 :
         123                 :             gfxXlibSurface *xlibSurface =
         124               0 :                 static_cast<gfxXlibSurface *>(currentTarget);
         125               0 :             Display *dpy = xlibSurface->XDisplay();
         126                 :             // This is the exact condition for cairo to avoid XRender for
         127                 :             // EXTEND_PAD
         128               0 :             if (VendorRelease(dpy) >= 60700000 ||
         129                 :                 VendorRelease(dpy) < 10699000) {
         130                 :
         131                 :                 bool isDownscale =
         132                 :                     aDeviceToImage.xx >= 1.0 && aDeviceToImage.yy >= 1.0 &&
         133               0 :                     aDeviceToImage.xy == 0.0 && aDeviceToImage.yx == 0.0;
         134                 :
         135                 :                 gfxPattern::GraphicsFilter filter =
         136               0 :                     isDownscale ? aDefaultFilter : gfxPattern::FILTER_FAST;
         137               0 :                 aPattern->SetFilter(filter);
         138                 :
         139                 :                 // Use the default EXTEND_NONE
         140               0 :                 break;
         141                 :             }
         142                 :             // else fall through to EXTEND_PAD and the default filter.
         143                 :         }
         144                 : #endif
         145                 :
         146                 :         default:
         147                 :             // turn on EXTEND_PAD.
         148                 :             // This is what we really want for all surface types, if the
         149                 :             // implementation was universally good.
         150               0 :             aPattern->SetExtend(gfxPattern::EXTEND_PAD);
         151               0 :             aPattern->SetFilter(aDefaultFilter);
         152               0 :             break;
         153                 :     }
         154                 : }
         155                 :
         156                 : bool
         157               0 : gfxSurfaceDrawable::Draw(gfxContext* aContext,
         158                 :                          const gfxRect& aFillRect,
         159                 :                          bool aRepeat,
         160                 :                          const gfxPattern::GraphicsFilter& aFilter,
         161                 :                          const gfxMatrix& aTransform)
         162                 : {
         163               0 :     nsRefPtr<gfxPattern> pattern = new gfxPattern(mSurface);
         164               0 :     if (aRepeat) {
         165               0 :         pattern->SetExtend(gfxPattern::EXTEND_REPEAT);
         166               0 :         pattern->SetFilter(aFilter);
         167                 :     } else {
         168               0 :         gfxPattern::GraphicsFilter filter = aFilter;
         169               0 :         if (aContext->CurrentMatrix().HasOnlyIntegerTranslation() &&
         170               0 :             aTransform.HasOnlyIntegerTranslation())
         171                 :         {
         172                 :           // If we only have integer translation, no special filtering needs to
         173                 :           // happen and we explicitly use FILTER_FAST. This is fast for some
         174                 :           // backends.
         175               0 :           filter = gfxPattern::FILTER_FAST;
         176                 :         }
         177               0 :         nsRefPtr<gfxASurface> currentTarget = aContext->CurrentSurface();
         178                 :         gfxMatrix deviceSpaceToImageSpace =
         179               0 :             DeviceToImageTransform(aContext, aTransform);
         180                 :         PreparePatternForUntiledDrawing(pattern, deviceSpaceToImageSpace,
         181               0 :                                         currentTarget, filter);
         182                 :     }
         183               0 :     pattern->SetMatrix(gfxMatrix(aTransform).Multiply(mTransform));
         184               0 :     aContext->NewPath();
         185               0 :     aContext->SetPattern(pattern);
         186               0 :     aContext->Rectangle(aFillRect);
         187               0 :     aContext->Fill();
         188               0 :     return true;
         189                 : }
         190                 :
         191               0 : gfxCallbackDrawable::gfxCallbackDrawable(gfxDrawingCallback* aCallback,
         192                 :                                          const gfxIntSize aSize)
         193                 :  : gfxDrawable(aSize)
         194               0 :  , mCallback(aCallback)
         195                 : {
         196               0 : }
         197                 :
         198                 : already_AddRefed<gfxSurfaceDrawable>
         199               0 : gfxCallbackDrawable::MakeSurfaceDrawable(const gfxPattern::GraphicsFilter aFilter)
         200                 : {
         201                 :     nsRefPtr<gfxASurface> surface =
         202               0 :         gfxPlatform::GetPlatform()->CreateOffscreenSurface(mSize, gfxASurface::CONTENT_COLOR_ALPHA);
         203               0 :     if (!surface || surface->CairoStatus() != 0)
         204               0 :         return nsnull;
         205                 :
         206               0 :     nsRefPtr<gfxContext> ctx = new gfxContext(surface);
         207               0 :     Draw(ctx, gfxRect(0, 0, mSize.width, mSize.height), false, aFilter);
         208               0 :     nsRefPtr<gfxSurfaceDrawable> drawable = new gfxSurfaceDrawable(surface, mSize);
         209               0 :     return drawable.forget();
         210                 : }
         211                 :
         212                 : bool
         213               0 : gfxCallbackDrawable::Draw(gfxContext* aContext,
         214                 :                           const gfxRect& aFillRect,
         215                 :                           bool aRepeat,
         216                 :                           const gfxPattern::GraphicsFilter& aFilter,
         217                 :                           const gfxMatrix& aTransform)
         218                 : {
         219               0 :     if (aRepeat && !mSurfaceDrawable) {
         220               0 :         mSurfaceDrawable = MakeSurfaceDrawable(aFilter);
         221                 :     }
         222                 :
         223               0 :     if (mSurfaceDrawable)
         224               0 :         return mSurfaceDrawable->Draw(aContext, aFillRect, aRepeat, aFilter,
         225               0 :                                       aTransform);
         226                 :
         227               0 :     if (mCallback)
         228               0 :         return (*mCallback)(aContext, aFillRect, aFilter, aTransform);
         229                 :
         230               0 :     return false;
         231                 : }
         232                 :
         233               0 : gfxPatternDrawable::gfxPatternDrawable(gfxPattern* aPattern,
         234                 :                                        const gfxIntSize aSize)
         235                 :  : gfxDrawable(aSize)
         236               0 :  , mPattern(aPattern)
         237                 : {
         238               0 : }
         239                 :
         240                 : class DrawingCallbackFromDrawable : public gfxDrawingCallback {
         241                 : public:
         242               0 :     DrawingCallbackFromDrawable(gfxDrawable* aDrawable)
         243               0 :      : mDrawable(aDrawable) {
         244               0 :         NS_ASSERTION(aDrawable, "aDrawable is null!");
         245               0 :     }
         246                 :
         247               0 :     virtual ~DrawingCallbackFromDrawable() {}
         248                 :
         249               0 :     virtual bool operator()(gfxContext* aContext,
         250                 :                               const gfxRect& aFillRect,
         251                 :                               const gfxPattern::GraphicsFilter& aFilter,
         252                 :                               const gfxMatrix& aTransform = gfxMatrix())
         253                 :     {
         254               0 :         return mDrawable->Draw(aContext, aFillRect, false, aFilter,
         255               0 :                                aTransform);
         256                 :     }
         257                 : private:
         258                 :     nsRefPtr<gfxDrawable> mDrawable;
         259                 : };
         260                 :
         261                 : already_AddRefed<gfxCallbackDrawable>
         262               0 : gfxPatternDrawable::MakeCallbackDrawable()
         263                 : {
         264                 :     nsRefPtr<gfxDrawingCallback> callback =
         265               0 :         new DrawingCallbackFromDrawable(this);
         266                 :     nsRefPtr<gfxCallbackDrawable> callbackDrawable =
         267               0 :         new gfxCallbackDrawable(callback, mSize);
         268               0 :     return callbackDrawable.forget();
         269                 : }
         270                 :
         271                 : bool
         272               0 : gfxPatternDrawable::Draw(gfxContext* aContext,
         273                 :                          const gfxRect& aFillRect,
         274                 :                          bool aRepeat,
         275                 :                          const gfxPattern::GraphicsFilter& aFilter,
         276                 :                          const gfxMatrix& aTransform)
         277                 : {
         278               0 :     if (!mPattern)
         279               0 :         return false;
         280                 :
         281               0 :     if (aRepeat) {
         282                 :         // We can't use mPattern directly: We want our repeated tiles to have
         283                 :         // the size mSize, which might not be the case in mPattern.
         284                 :         // So we need to draw mPattern into a surface of size mSize, create
         285                 :         // a pattern from the surface and draw that pattern.
         286                 :         // gfxCallbackDrawable and gfxSurfaceDrawable already know how to do
         287                 :         // those things, so we use them here. Drawing mPattern into the surface
         288                 :         // will happen through this Draw() method with aRepeat = false.
         289               0 :         nsRefPtr<gfxCallbackDrawable> callbackDrawable = MakeCallbackDrawable();
         290               0 :         return callbackDrawable->Draw(aContext, aFillRect, true, aFilter,
         291               0 :                                       aTransform);
         292                 :     }
         293                 :
         294               0 :     aContext->NewPath();
         295               0 :     gfxMatrix oldMatrix = mPattern->GetMatrix();
         296               0 :     mPattern->SetMatrix(gfxMatrix(aTransform).Multiply(oldMatrix));
         297               0 :     aContext->SetPattern(mPattern);
         298               0 :     aContext->Rectangle(aFillRect);
         299               0 :     aContext->Fill();
         300               0 :     mPattern->SetMatrix(oldMatrix);
         301               0 :     return true;
         302                 : }

Generated by: LCOV version 1.7