drawImage method

  1. @override
void drawImage(
  1. PdfImageRequest request
)

Implementation

@override
void drawImage(PdfImageRequest request) {
  final image = images[pdfImageKey(request)];
  if (image == null) return; // not decodable (yet): skip silently
  final softMask = pdfGpuSoftMaskOf(image);
  // antialiased edges leave hairline seams between abutting image slices
  // (PowerPoint and scanners split large images into strips)
  final paint = Paint()
    ..filterQuality = FilterQuality.medium
    ..isAntiAlias = false
    ..blendMode = softMask == null ? _fillElementBlend : BlendMode.srcOver;
  if (request.isStencil) {
    // stencil masks paint the fill color through the mask's alpha
    paint.colorFilter = ColorFilter.mode(
        _toColor(request.stencilColor, request.alpha), BlendMode.srcIn);
  } else {
    paint.color = Color.from(alpha: request.alpha, red: 0, green: 0, blue: 0);
  }
  canvas.save();
  canvas.transform(_toFloat64(request.transform));
  // image space: unit square, y-up; image pixels: y-down from the top
  canvas.translate(0, 1);
  canvas.scale(1, -1);
  if (softMask != null) {
    // Isolate the base + mask so the PDF blend mode applies to the finished
    // composite, not to the base against a transparent temporary surface.
    // The mask JPEG is grayscale, so its red sample is the specified alpha.
    canvas.saveLayer(
      const Rect.fromLTWH(0, 0, 1, 1),
      Paint()..blendMode = _fillElementBlend,
    );
  }
  canvas.drawImageRect(
    image,
    Rect.fromLTWH(0, 0, image.width.toDouble(), image.height.toDouble()),
    const Rect.fromLTWH(0, 0, 1, 1),
    paint,
  );
  if (softMask != null) {
    // The dstIn and the red->alpha filter go on a *layer* paint, not on the
    // mask's own draw paint. Impeller ignores a draw paint's blend mode when
    // that same paint also carries a colour filter: the mask then composites
    // srcOver, painting its filtered samples (opaque black where the mask is
    // white) over the base instead of cutting the base's alpha - every
    // /SMask'd JPEG on the page turns into a black rectangle (#675). Skia
    // honours both on one paint, and both engines honour this shape.
    canvas.saveLayer(
      const Rect.fromLTWH(0, 0, 1, 1),
      Paint()
        ..blendMode = BlendMode.dstIn
        ..colorFilter = const ColorFilter.matrix(_redToAlpha),
    );
    canvas.drawImageRect(
      softMask,
      Rect.fromLTWH(
        0,
        0,
        softMask.width.toDouble(),
        softMask.height.toDouble(),
      ),
      const Rect.fromLTWH(0, 0, 1, 1),
      Paint()
        ..filterQuality = FilterQuality.medium
        ..isAntiAlias = false,
    );
    canvas.restore();
    canvas.restore();
  }
  canvas.restore();
}