LCOV - code coverage report
Current view: directory - image/src - Decoder.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 108 98 90.7 %
Date: 2012-06-02 Functions: 19 16 84.2 %

       1                 : 
       2                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * the Mozilla Foundation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2010.
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "Decoder.h"
      40                 : #include "nsIServiceManager.h"
      41                 : #include "nsIConsoleService.h"
      42                 : #include "nsIScriptError.h"
      43                 : 
      44                 : namespace mozilla {
      45                 : namespace image {
      46                 : 
      47              24 : Decoder::Decoder(RasterImage &aImage, imgIDecoderObserver* aObserver)
      48                 :   : mImage(aImage)
      49                 :   , mObserver(aObserver)
      50                 :   , mDecodeFlags(0)
      51                 :   , mDecodeDone(false)
      52                 :   , mDataError(false)
      53                 :   , mFrameCount(0)
      54                 :   , mFailCode(NS_OK)
      55                 :   , mInitialized(false)
      56                 :   , mSizeDecode(false)
      57                 :   , mInFrame(false)
      58              24 :   , mIsAnimated(false)
      59                 : {
      60              24 : }
      61                 : 
      62              48 : Decoder::~Decoder()
      63                 : {
      64              24 :   NS_WARN_IF_FALSE(!mInFrame, "Shutting down decoder mid-frame!");
      65              24 :   mInitialized = false;
      66              48 : }
      67                 : 
      68                 : /*
      69                 :  * Common implementation of the decoder interface.
      70                 :  */
      71                 : 
      72                 : void
      73              20 : Decoder::Init()
      74                 : {
      75                 :   // No re-initializing
      76              20 :   NS_ABORT_IF_FALSE(!mInitialized, "Can't re-initialize a decoder!");
      77                 : 
      78                 :   // Fire OnStartDecode at init time to support bug 512435
      79              20 :   if (!IsSizeDecode() && mObserver)
      80               2 :       mObserver->OnStartDecode(nsnull);
      81                 : 
      82                 :   // Implementation-specific initialization
      83              20 :   InitInternal();
      84              20 :   mInitialized = true;
      85              20 : }
      86                 : 
      87                 : // Initializes a decoder whose aImage and aObserver is already being used by a
      88                 : // parent decoder
      89                 : void
      90               4 : Decoder::InitSharedDecoder()
      91                 : {
      92                 :   // No re-initializing
      93               4 :   NS_ABORT_IF_FALSE(!mInitialized, "Can't re-initialize a decoder!");
      94                 : 
      95                 :   // Implementation-specific initialization
      96               4 :   InitInternal();
      97               4 :   mInitialized = true;
      98               4 : }
      99                 : 
     100                 : void
     101              73 : Decoder::Write(const char* aBuffer, PRUint32 aCount)
     102                 : {
     103                 :   // We're strict about decoder errors
     104              73 :   NS_ABORT_IF_FALSE(!HasDecoderError(),
     105                 :                     "Not allowed to make more decoder calls after error!");
     106                 : 
     107                 :   // If a data error occured, just ignore future data
     108              73 :   if (HasDataError())
     109               5 :     return;
     110                 : 
     111                 :   // Pass the data along to the implementation
     112              68 :   WriteInternal(aBuffer, aCount);
     113                 : }
     114                 : 
     115                 : void
     116              20 : Decoder::Finish()
     117                 : {
     118                 :   // Implementation-specific finalization
     119              20 :   if (!HasError())
     120              19 :     FinishInternal();
     121                 : 
     122                 :   // If the implementation left us mid-frame, finish that up.
     123              20 :   if (mInFrame && !HasDecoderError())
     124               0 :     PostFrameStop();
     125                 : 
     126                 :   // If PostDecodeDone() has not been called, we need to sent teardown
     127                 :   // notifications.
     128              20 :   if (!IsSizeDecode() && !mDecodeDone) {
     129                 : 
     130                 :     // Log data errors to the error console
     131                 :     nsCOMPtr<nsIConsoleService> consoleService =
     132               2 :       do_GetService(NS_CONSOLESERVICE_CONTRACTID);
     133                 :     nsCOMPtr<nsIScriptError> errorObject =
     134               2 :       do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
     135                 : 
     136               1 :     if (consoleService && errorObject && !HasDecoderError()) {
     137               1 :       nsAutoString msg(NS_LITERAL_STRING("Image corrupt or truncated: ") +
     138               3 :                        NS_ConvertASCIItoUTF16(mImage.GetURIString()));
     139                 : 
     140               1 :       if (NS_SUCCEEDED(errorObject->InitWithWindowID(
     141                 :                          msg.get(),
     142                 :                          NS_ConvertUTF8toUTF16(mImage.GetURIString()).get(),
     143                 :                          nsnull, 0, 0, nsIScriptError::errorFlag,
     144                 :                          "Image", mImage.InnerWindowID()
     145                 :                        ))) {
     146               1 :         consoleService->LogMessage(errorObject);
     147                 :       }
     148                 :     }
     149                 : 
     150                 :     // If we only have a data error, see if things are worth salvaging
     151               1 :     bool salvage = !HasDecoderError() && mImage.GetNumFrames();
     152                 : 
     153                 :     // If we're salvaging, say we finished decoding
     154               1 :     if (salvage)
     155               0 :       mImage.DecodingComplete();
     156                 : 
     157                 :     // Fire teardown notifications
     158               1 :     if (mObserver) {
     159               0 :       mObserver->OnStopContainer(nsnull, &mImage);
     160               0 :       mObserver->OnStopDecode(nsnull, salvage ? NS_OK : NS_ERROR_FAILURE, nsnull);
     161                 :     }
     162                 :   }
     163              20 : }
     164                 : 
     165                 : void
     166               4 : Decoder::FinishSharedDecoder()
     167                 : {
     168               4 :   if (!HasError()) {
     169               4 :     FinishInternal();
     170                 :   }
     171               4 : }
     172                 : 
     173                 : void
     174              72 : Decoder::FlushInvalidations()
     175                 : {
     176              72 :   NS_ABORT_IF_FALSE(!HasDecoderError(),
     177                 :                     "Not allowed to make more decoder calls after error!");
     178                 : 
     179                 :   // If we've got an empty invalidation rect, we have nothing to do
     180              72 :   if (mInvalidRect.IsEmpty())
     181              40 :     return;
     182                 : 
     183                 :   // Tell the image that it's been updated
     184              32 :   mImage.FrameUpdated(mFrameCount - 1, mInvalidRect);
     185                 : 
     186                 :   // Fire OnDataAvailable
     187              32 :   if (mObserver) {
     188                 : #ifdef XP_MACOSX
     189                 :     // Bug 703231
     190                 :     // Because of high quality down sampling on mac we show scan lines while decoding.
     191                 :     // Bypass this problem by redrawing the border.
     192                 :     PRInt32 width;
     193                 :     PRInt32 height;
     194                 : 
     195                 :     mImage.GetWidth(&width);
     196                 :     mImage.GetHeight(&height);
     197                 :     nsIntRect mImageBound(0, 0, width, height);
     198                 : 
     199                 :     mInvalidRect.Inflate(1);
     200                 :     mInvalidRect = mInvalidRect.Intersect(mImageBound);
     201                 : #endif
     202               2 :     bool isCurrentFrame = mImage.GetCurrentFrameIndex() == (mFrameCount - 1);
     203               2 :     mObserver->OnDataAvailable(nsnull, isCurrentFrame, &mInvalidRect);
     204                 :   }
     205                 : 
     206                 :   // Clear the invalidation rectangle
     207              32 :   mInvalidRect.SetEmpty();
     208                 : }
     209                 : 
     210                 : /*
     211                 :  * Hook stubs. Override these as necessary in decoder implementations.
     212                 :  */
     213                 : 
     214              13 : void Decoder::InitInternal() { }
     215               0 : void Decoder::WriteInternal(const char* aBuffer, PRUint32 aCount) { }
     216               6 : void Decoder::FinishInternal() { }
     217                 : 
     218                 : /*
     219                 :  * Progress Notifications
     220                 :  */
     221                 : 
     222                 : void
     223              19 : Decoder::PostSize(PRInt32 aWidth, PRInt32 aHeight)
     224                 : {
     225                 :   // Validate
     226              19 :   NS_ABORT_IF_FALSE(aWidth >= 0, "Width can't be negative!");
     227              19 :   NS_ABORT_IF_FALSE(aHeight >= 0, "Height can't be negative!");
     228                 : 
     229                 :   // Tell the image
     230              19 :   mImage.SetSize(aWidth, aHeight);
     231                 : 
     232                 :   // Notify the observer
     233              19 :   if (mObserver)
     234               6 :     mObserver->OnStartContainer(nsnull, &mImage);
     235              19 : }
     236                 : 
     237                 : void
     238              17 : Decoder::PostFrameStart()
     239                 : {
     240                 :   // We shouldn't already be mid-frame
     241              17 :   NS_ABORT_IF_FALSE(!mInFrame, "Starting new frame but not done with old one!");
     242                 : 
     243                 :   // We should take care of any invalidation region when wrapping up the
     244                 :   // previous frame
     245              17 :   NS_ABORT_IF_FALSE(mInvalidRect.IsEmpty(),
     246                 :                     "Start image frame with non-empty invalidation region!");
     247                 : 
     248                 :   // Update our state to reflect the new frame
     249              17 :   mFrameCount++;
     250              17 :   mInFrame = true;
     251                 : 
     252                 :   // Decoder implementations should only call this method if they successfully
     253                 :   // appended the frame to the image. So mFrameCount should always match that
     254                 :   // reported by the Image.
     255              17 :   NS_ABORT_IF_FALSE(mFrameCount == mImage.GetNumFrames(),
     256                 :                     "Decoder frame count doesn't match image's!");
     257                 : 
     258                 :   // Fire notification
     259              17 :   if (mObserver)
     260               4 :     mObserver->OnStartFrame(nsnull, mFrameCount - 1); // frame # is zero-indexed
     261              17 : }
     262                 : 
     263                 : void
     264              17 : Decoder::PostFrameStop()
     265                 : {
     266                 :   // We should be mid-frame
     267              17 :   NS_ABORT_IF_FALSE(mInFrame, "Stopping frame when we didn't start one!");
     268                 : 
     269                 :   // Update our state
     270              17 :   mInFrame = false;
     271                 : 
     272                 :   // Flush any invalidations before we finish the frame
     273              17 :   FlushInvalidations();
     274                 : 
     275                 :   // Fire notifications
     276              17 :   if (mObserver) {
     277               4 :     mObserver->OnStopFrame(nsnull, mFrameCount - 1); // frame # is zero-indexed
     278               4 :     if (mFrameCount > 1 && !mIsAnimated) {
     279               1 :       mIsAnimated = true;
     280               1 :       mObserver->OnImageIsAnimated(nsnull);
     281                 :     }
     282                 :   }
     283              17 : }
     284                 : 
     285                 : void
     286             211 : Decoder::PostInvalidation(nsIntRect& aRect)
     287                 : {
     288                 :   // We should be mid-frame
     289             211 :   NS_ABORT_IF_FALSE(mInFrame, "Can't invalidate when not mid-frame!");
     290                 : 
     291                 :   // Account for the new region
     292             211 :   mInvalidRect.UnionRect(mInvalidRect, aRect);
     293             211 : }
     294                 : 
     295                 : void
     296              15 : Decoder::PostDecodeDone()
     297                 : {
     298              15 :   NS_ABORT_IF_FALSE(!IsSizeDecode(), "Can't be done with decoding with size decode!");
     299              15 :   NS_ABORT_IF_FALSE(!mInFrame, "Can't be done decoding if we're mid-frame!");
     300              15 :   NS_ABORT_IF_FALSE(!mDecodeDone, "Decode already done!");
     301              15 :   mDecodeDone = true;
     302                 : 
     303                 :   // Notify
     304              15 :   mImage.DecodingComplete();
     305              15 :   if (mObserver) {
     306               2 :     mObserver->OnStopContainer(nsnull, &mImage);
     307               2 :     mObserver->OnStopDecode(nsnull, NS_OK, nsnull);
     308                 :   }
     309              15 : }
     310                 : 
     311                 : void
     312               1 : Decoder::PostDataError()
     313                 : {
     314               1 :   mDataError = true;
     315               1 : }
     316                 : 
     317                 : void
     318               0 : Decoder::PostDecoderError(nsresult aFailureCode)
     319                 : {
     320               0 :   NS_ABORT_IF_FALSE(NS_FAILED(aFailureCode), "Not a failure code!");
     321                 : 
     322               0 :   mFailCode = aFailureCode;
     323                 : 
     324                 :   // XXXbholley - we should report the image URI here, but imgContainer
     325                 :   // needs to know its URI first
     326               0 :   NS_WARNING("Image decoding error - This is probably a bug!");
     327               0 : }
     328                 : 
     329                 : } // namespace image
     330                 : } // namespace mozilla

Generated by: LCOV version 1.7