Commit d413fc19 authored by aardgoose's avatar aardgoose
Browse files

Bug 1687658 - Recursive createImageBitmap ignores source cropping r=aosmond

Note: if the original imageBitmap has been use for display, the source surface will have been cropped and
the original cropping IntRect has been lost, in this case use cropped mSurface instead of mdata.

If some of the new clip rect falls outside the source we have to crop the source if it hasn't been cropped.

Q: Should I attempt to get tests for this added to WPT?

Differential Revision: https://phabricator.services.mozilla.com/D124607
parent 17570fcc
Loading
Loading
Loading
Loading
+38 −4
Original line number Diff line number Diff line
@@ -1136,14 +1136,48 @@ already_AddRefed<ImageBitmap> ImageBitmap::CreateInternal(
    return nullptr;
  }

  IntRect cropRect = aImageBitmap.mPictureRect;
  RefPtr<SourceSurface> surface;

  bool needToReportMemoryAllocation = false;

  if (aImageBitmap.mSurface) {
    // the source imageBitmap already has a cropped surface, just use this
    surface = aImageBitmap.mSurface;
    cropRect = aCropRect.valueOr(cropRect);
  } else {
    RefPtr<layers::Image> data = aImageBitmap.mData;
    surface = data->GetAsSourceSurface();

  RefPtr<SourceSurface> surface = data->GetAsSourceSurface();
    if (aCropRect.isSome()) {
      // get new crop rect relative to original uncropped surface
      IntRect newCropRect = aCropRect.ref();
      newCropRect = FixUpNegativeDimension(newCropRect, aRv);

  bool needToReportMemoryAllocation = false;
      newCropRect.MoveBy(cropRect.X(), cropRect.Y());

      if (cropRect.Contains(newCropRect)) {
        // new crop region within existing surface
        // safe to just crop this with new rect
        cropRect = newCropRect;
      } else {
        // crop includes area outside original cropped region
        // create new surface cropped by original bitmap crop rect
        RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();

        surface = CropAndCopyDataSourceSurface(dataSurface, cropRect);
        if (NS_WARN_IF(!surface)) {
          aRv.Throw(NS_ERROR_NOT_AVAILABLE);
          return nullptr;
        }
        needToReportMemoryAllocation = true;
        cropRect = aCropRect.ref();
      }
    }
  }

  return CreateImageBitmapInternal(
      aGlobal, surface, aCropRect, aOptions, aImageBitmap.mWriteOnly,
      aGlobal, surface, Some(cropRect), aOptions, aImageBitmap.mWriteOnly,
      needToReportMemoryAllocation, false, aImageBitmap.mAlphaType, aRv);
}