gfx/thebes/gfxBlur.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "gfxBlur.h"
     7 #include "gfxContext.h"
     8 #include "gfxImageSurface.h"
     9 #include "gfxPlatform.h"
    11 #include "mozilla/gfx/Blur.h"
    12 #include "mozilla/gfx/2D.h"
    14 using namespace mozilla::gfx;
    16 gfxAlphaBoxBlur::gfxAlphaBoxBlur()
    17  : mBlur(nullptr)
    18 {
    19 }
    21 gfxAlphaBoxBlur::~gfxAlphaBoxBlur()
    22 {
    23   mContext = nullptr;
    24   delete mBlur;
    25 }
    27 gfxContext*
    28 gfxAlphaBoxBlur::Init(const gfxRect& aRect,
    29                       const gfxIntSize& aSpreadRadius,
    30                       const gfxIntSize& aBlurRadius,
    31                       const gfxRect* aDirtyRect,
    32                       const gfxRect* aSkipRect)
    33 {
    34     mozilla::gfx::Rect rect(Float(aRect.x), Float(aRect.y),
    35                             Float(aRect.width), Float(aRect.height));
    36     IntSize spreadRadius(aSpreadRadius.width, aSpreadRadius.height);
    37     IntSize blurRadius(aBlurRadius.width, aBlurRadius.height);
    38     nsAutoPtr<mozilla::gfx::Rect> dirtyRect;
    39     if (aDirtyRect) {
    40       dirtyRect = new mozilla::gfx::Rect(Float(aDirtyRect->x),
    41                                          Float(aDirtyRect->y),
    42                                          Float(aDirtyRect->width),
    43                                          Float(aDirtyRect->height));
    44     }
    45     nsAutoPtr<mozilla::gfx::Rect> skipRect;
    46     if (aSkipRect) {
    47       skipRect = new mozilla::gfx::Rect(Float(aSkipRect->x),
    48                                         Float(aSkipRect->y),
    49                                         Float(aSkipRect->width),
    50                                         Float(aSkipRect->height));
    51     }
    53     mBlur = new AlphaBoxBlur(rect, spreadRadius, blurRadius, dirtyRect, skipRect);
    54     size_t blurDataSize = mBlur->GetSurfaceAllocationSize();
    55     if (blurDataSize == 0)
    56         return nullptr;
    58     IntSize size = mBlur->GetSize();
    60     // Make an alpha-only surface to draw on. We will play with the data after
    61     // everything is drawn to create a blur effect.
    62     mData = new (std::nothrow) unsigned char[blurDataSize];
    63     if (!mData) {
    64         return nullptr;
    65     }
    66     memset(mData, 0, blurDataSize);
    68     mozilla::RefPtr<DrawTarget> dt =
    69         gfxPlatform::GetPlatform()->CreateDrawTargetForData(mData, size,
    70                                                             mBlur->GetStride(),
    71                                                             SurfaceFormat::A8);
    72     if (!dt) {
    73         nsRefPtr<gfxImageSurface> image =
    74             new gfxImageSurface(mData,
    75                                 gfxIntSize(size.width, size.height),
    76                                 mBlur->GetStride(),
    77                                 gfxImageFormat::A8);
    78         dt = Factory::CreateDrawTargetForCairoSurface(image->CairoSurface(), size);
    79         if (!dt) {
    80             return nullptr;
    81         }
    82     }
    84     IntRect irect = mBlur->GetRect();
    85     gfxPoint topleft(irect.TopLeft().x, irect.TopLeft().y);
    87     mContext = new gfxContext(dt);
    88     mContext->Translate(-topleft);
    90     return mContext;
    91 }
    93 void
    94 gfxAlphaBoxBlur::Paint(gfxContext* aDestinationCtx)
    95 {
    96     if (!mContext)
    97         return;
    99     mBlur->Blur(mData);
   101     mozilla::gfx::Rect* dirtyRect = mBlur->GetDirtyRect();
   103     DrawTarget *dest = aDestinationCtx->GetDrawTarget();
   104     if (!dest) {
   105       NS_WARNING("Blurring not supported for Thebes contexts!");
   106       return;
   107     }
   109     mozilla::RefPtr<SourceSurface> mask
   110       = dest->CreateSourceSurfaceFromData(mData,
   111                                           mBlur->GetSize(),
   112                                           mBlur->GetStride(),
   113                                           SurfaceFormat::A8);
   114     if (!mask) {
   115       NS_ERROR("Failed to create mask!");
   116       return;
   117     }
   119     nsRefPtr<gfxPattern> thebesPat = aDestinationCtx->GetPattern();
   120     Pattern* pat = thebesPat->GetPattern(dest, nullptr);
   122     Matrix oldTransform = dest->GetTransform();
   123     Matrix newTransform = oldTransform;
   124     newTransform.Translate(mBlur->GetRect().x, mBlur->GetRect().y);
   126     // Avoid a semi-expensive clip operation if we can, otherwise
   127     // clip to the dirty rect
   128     if (dirtyRect) {
   129         dest->PushClipRect(*dirtyRect);
   130     }
   132     dest->SetTransform(newTransform);
   133     dest->MaskSurface(*pat, mask, Point(0, 0));
   134     dest->SetTransform(oldTransform);
   136     if (dirtyRect) {
   137         dest->PopClip();
   138     }
   139 }
   141 gfxIntSize gfxAlphaBoxBlur::CalculateBlurRadius(const gfxPoint& aStd)
   142 {
   143     mozilla::gfx::Point std(Float(aStd.x), Float(aStd.y));
   144     IntSize size = AlphaBoxBlur::CalculateBlurRadius(std);
   145     return gfxIntSize(size.width, size.height);
   146 }
   148 /* static */ void
   149 gfxAlphaBoxBlur::BlurRectangle(gfxContext *aDestinationCtx,
   150                                const gfxRect& aRect,
   151                                gfxCornerSizes* aCornerRadii,
   152                                const gfxPoint& aBlurStdDev,
   153                                const gfxRGBA& aShadowColor,
   154                                const gfxRect& aDirtyRect,
   155                                const gfxRect& aSkipRect)
   156 {
   157   gfxIntSize blurRadius = CalculateBlurRadius(aBlurStdDev);
   159   // Create the temporary surface for blurring
   160   gfxAlphaBoxBlur blur;
   161   gfxContext *dest = blur.Init(aRect, gfxIntSize(), blurRadius, &aDirtyRect, &aSkipRect);
   163   if (!dest) {
   164     return;
   165   }
   167   gfxRect shadowGfxRect = aRect;
   168   shadowGfxRect.Round();
   170   dest->NewPath();
   171   if (aCornerRadii) {
   172     dest->RoundedRectangle(shadowGfxRect, *aCornerRadii);
   173   } else {
   174     dest->Rectangle(shadowGfxRect);
   175   }
   176   dest->Fill();
   178   aDestinationCtx->SetColor(aShadowColor);
   179   blur.Paint(aDestinationCtx);
   180 }

mercurial