/*
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

package com.facebook.imagepipeline.request;

import javax.annotation.Nullable;

import android.graphics.Bitmap;

import com.facebook.cache.common.CacheKey;
import com.facebook.common.references.CloseableReference;
import com.facebook.imagepipeline.bitmaps.PlatformBitmapFactory;
import com.facebook.imagepipeline.nativecode.Bitmaps;

/**
 * Base implementation of {@link Postprocessor} interface.
 *
 * <p> Clients should override exactly one of the three provided {@link #process} methods.
 */
public abstract class BasePostprocessor implements Postprocessor {

  @Override
  public String getName() {
    return "Unknown postprocessor";
  }

  /**
   * Clients should override this method only if the post-processed bitmap has to be of a different
   * size than the source bitmap. If the post-processed bitmap is of the same size, clients should
   * override one of the other two methods.
   *
   * <p> The source bitmap must not be modified as it may be shared by the other clients. The
   * implementation must create a new bitmap that is safe to be modified and return a reference
   * to it. Clients should use <code>bitmapFactory</code> to create a new bitmap.
   *
   * @param sourceBitmap The source bitmap.
   * @param bitmapFactory The factory to create a destination bitmap.
   * @return a reference to the newly created bitmap
   */
  @Override
  public CloseableReference<Bitmap> process(
      Bitmap sourceBitmap,
      PlatformBitmapFactory bitmapFactory) {
    CloseableReference<Bitmap> destBitmapRef =
        bitmapFactory.createBitmapInternal(
            sourceBitmap.getWidth(),
            sourceBitmap.getHeight(),
            sourceBitmap.getConfig());
    try {
      process(destBitmapRef.get(), sourceBitmap);
      return CloseableReference.cloneOrNull(destBitmapRef);
    } finally {
      CloseableReference.closeSafely(destBitmapRef);
    }
  }

  /**
   * Clients should override this method if the post-processing cannot be done in place. If the
   * post-processing can be done in place, clients should override the {@link #process(Bitmap)}
   * method.
   *
   * <p> The provided destination bitmap is of the same size as the source bitmap. There are no
   * guarantees on the initial content of the destination bitmap, so the implementation has to make
   * sure that it properly populates it.
   *
   * <p> The source bitmap must not be modified as it may be shared by the other clients.
   * The implementation must use the provided destination bitmap as its output.
   *
   * @param destBitmap the destination bitmap to be used as output
   * @param sourceBitmap the source bitmap to be used as input
   */
  public void process(Bitmap destBitmap, Bitmap sourceBitmap) {
    Bitmaps.copyBitmap(destBitmap, sourceBitmap);
    process(destBitmap);
  }

  /**
   * Clients should override this method if the post-processing can be done in place.
   *
   * <p> The provided bitmap is a copy of the source bitmap and the implementation is free to
   * modify it.
   *
   * @param bitmap the bitmap to be used both as input and as output
   */
  public void process(Bitmap bitmap) {
  }

  /**
   * The default implementation of the CacheKey for a Postprocessor is null
   * @return The CacheKey to use for caching. Not used if null
   */
  @Override
  @Nullable
  public CacheKey getPostprocessorCacheKey() {
    return null;
  }
}

@@ -413,16 +413,48 @@
 .Bitmap;
+%0Aimport android.graphics.Canvas;
 %0A%0Aimport
@@ -897,16 +897,327 @@
 ssor %7B%0A%0A
+  /**%0A   * The fallback bitmap configuration is used for creating a new destination bitmap when the%0A   * source bitmap has %3Ccode%3Econfig==null%3C/code%3E. This is the case for preview images for GIF%0A   * animations.%0A   */%0A  public static final Bitmap.Config FALLBACK_BITMAP_CONFIGURATION = Bitmap.Config.ARGB_8888;%0A%0A
   @Overr
@@ -2118,24 +2118,95 @@
 pFactory) %7B%0A
+    final Bitmap.Config sourceBitmapConfig = sourceBitmap.getConfig();%0A
     Closeabl
@@ -2383,28 +2383,83 @@
 ceBitmap
-.getConfig()
+Config != null ? sourceBitmapConfig : FALLBACK_BITMAP_CONFIGURATION
 );%0A    t
@@ -3494,17 +3494,17 @@
     
-Bitmaps.c
+internalC
 opyB
@@ -4115,24 +4115,24 @@
 acheKey() %7B%0A
-
     return n
@@ -4139,11 +4139,941 @@
 ull;%0A  %7D
+%0A%0A  /**%0A   * Copies the content of %3Ccode%3EsourceBitmap%3C/code%3E to %3Ccode%3EdestBitmap%3C/code%3E. Both bitmaps must%0A   * have the same width and height. If their %7B@link Bitmap.Config%7D are identical, the memory is%0A   * directly copied. Otherwise, the %3Ccode%3EsourceBitmap%3C/code%3E is drawn into%0A   * %3Ccode%3EdestBitmap%3C/code%3E.%0A   */%0A  private static void internalCopyBitmap(Bitmap destBitmap, Bitmap sourceBitmap) %7B%0A    if (destBitmap.getConfig() == sourceBitmap.getConfig()) %7B%0A      Bitmaps.copyBitmap(destBitmap, sourceBitmap);%0A    %7D else %7B%0A      // The bitmap configurations might be different when the source bitmap's configuration is%0A      // null, because it uses an internal configuration and the destination bitmap's configuration%0A      // is the FALLBACK_BITMAP_CONFIGURATION. This is the case for static images for animated GIFs.%0A      Canvas canvas = new Canvas(destBitmap);%0A      canvas.drawBitmap(sourceBitmap, 0, 0, null);%0A    %7D%0A  %7D
 %0A%7D%0A

Allow for Bitmap.Config being null in BasePostProcessor