/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ImageOps.h" #include "ClippedImage.h" #include "DecodePool.h" #include "Decoder.h" #include "DecoderFactory.h" #include "DynamicImage.h" #include "FrozenImage.h" #include "IDecodingTask.h" #include "Image.h" #include "imgIContainer.h" #include "mozilla/gfx/2D.h" #include "nsStreamUtils.h" #include "OrientedImage.h" #include "SourceBuffer.h" using namespace mozilla::gfx; namespace mozilla { namespace image { /* static */ already_AddRefed ImageOps::Freeze(Image* aImage) { RefPtr frozenImage = new FrozenImage(aImage); return frozenImage.forget(); } /* static */ already_AddRefed ImageOps::Freeze(imgIContainer* aImage) { nsCOMPtr frozenImage = new FrozenImage(static_cast(aImage)); return frozenImage.forget(); } /* static */ already_AddRefed ImageOps::Clip(Image* aImage, nsIntRect aClip, const Maybe& aSVGViewportSize) { RefPtr clippedImage = new ClippedImage(aImage, aClip, aSVGViewportSize); return clippedImage.forget(); } /* static */ already_AddRefed ImageOps::Clip(imgIContainer* aImage, nsIntRect aClip, const Maybe& aSVGViewportSize) { nsCOMPtr clippedImage = new ClippedImage(static_cast(aImage), aClip, aSVGViewportSize); return clippedImage.forget(); } /* static */ already_AddRefed ImageOps::Orient(Image* aImage, Orientation aOrientation) { RefPtr orientedImage = new OrientedImage(aImage, aOrientation); return orientedImage.forget(); } /* static */ already_AddRefed ImageOps::Orient(imgIContainer* aImage, Orientation aOrientation) { nsCOMPtr orientedImage = new OrientedImage(static_cast(aImage), aOrientation); return orientedImage.forget(); } /* static */ already_AddRefed ImageOps::CreateFromDrawable(gfxDrawable* aDrawable) { nsCOMPtr drawableImage = new DynamicImage(aDrawable); return drawableImage.forget(); } /* static */ already_AddRefed ImageOps::DecodeToSurface(nsIInputStream* aInputStream, const nsACString& aMimeType, uint32_t aFlags) { MOZ_ASSERT(aInputStream); nsresult rv; // Prepare the input stream. nsCOMPtr inputStream = aInputStream; if (!NS_InputStreamIsBuffered(aInputStream)) { nsCOMPtr bufStream; rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), aInputStream, 1024); if (NS_SUCCEEDED(rv)) { inputStream = bufStream; } } // Figure out how much data we've been passed. uint64_t length; rv = inputStream->Available(&length); if (NS_FAILED(rv) || length > UINT32_MAX) { return nullptr; } // Write the data into a SourceBuffer. NotNull> sourceBuffer = WrapNotNull(new SourceBuffer()); sourceBuffer->ExpectLength(length); rv = sourceBuffer->AppendFromInputStream(inputStream, length); if (NS_FAILED(rv)) { return nullptr; } // Make sure our sourceBuffer is marked as complete. if (sourceBuffer->IsComplete()) { NS_WARNING("The SourceBuffer was unexpectedly marked as complete. This may " "indicate either an OOM condition, or that imagelib was not " "initialized properly."); return nullptr; } sourceBuffer->Complete(NS_OK); // Create a decoder. DecoderType decoderType = DecoderFactory::GetDecoderType(PromiseFlatCString(aMimeType).get()); RefPtr decoder = DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer, Nothing(), ToSurfaceFlags(aFlags)); if (!decoder) { return nullptr; } // Run the decoder synchronously. RefPtr task = new AnonymousDecodingTask(WrapNotNull(decoder)); task->Run(); if (!decoder->GetDecodeDone() || decoder->HasError()) { return nullptr; } // Pull out the surface. RawAccessFrameRef frame = decoder->GetCurrentFrameRef(); if (!frame) { return nullptr; } RefPtr surface = frame->GetSourceSurface(); if (!surface) { return nullptr; } return surface.forget(); } } // namespace image } // namespace mozilla