func()

in draw/impl.go [4535:4646]


func (q *Kernel) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) {
	var o Options
	if opts != nil {
		o = *opts
	}

	dr := transformRect(&s2d, &sr)
	// adr is the affected destination pixels.
	adr := dst.Bounds().Intersect(dr)
	adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
	if adr.Empty() || sr.Empty() {
		return
	}
	if op == Over && o.SrcMask == nil && opaque(src) {
		op = Src
	}
	d2s := invert(&s2d)
	// bias is a translation of the mapping from dst coordinates to src
	// coordinates such that the latter temporarily have non-negative X
	// and Y coordinates. This allows us to write int(f) instead of
	// int(math.Floor(f)), since "round to zero" and "round down" are
	// equivalent when f >= 0, but the former is much cheaper. The X--
	// and Y-- are because the TransformLeaf methods have a "sx -= 0.5"
	// adjustment.
	bias := transformRect(&d2s, &adr).Min
	bias.X--
	bias.Y--
	d2s[2] -= float64(bias.X)
	d2s[5] -= float64(bias.Y)
	// Make adr relative to dr.Min.
	adr = adr.Sub(dr.Min)

	if u, ok := src.(*image.Uniform); ok && o.DstMask != nil && o.SrcMask != nil && sr.In(src.Bounds()) {
		transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
		return
	}

	xscale := abs(d2s[0])
	if s := abs(d2s[1]); xscale < s {
		xscale = s
	}
	yscale := abs(d2s[3])
	if s := abs(d2s[4]); yscale < s {
		yscale = s
	}

	// sr is the source pixels. If it extends beyond the src bounds,
	// we cannot use the type-specific fast paths, as they access
	// the Pix fields directly without bounds checking.
	//
	// Similarly, the fast paths assume that the masks are nil.
	if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
		switch op {
		case Over:
			q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
		case Src:
			q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
		}
	} else {
		switch op {
		case Over:
			switch dst := dst.(type) {
			case *image.RGBA:
				switch src := src.(type) {
				case *image.NRGBA:
					q.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
				case *image.RGBA:
					q.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
				default:
					q.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
				}
			default:
				switch src := src.(type) {
				default:
					q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
				}
			}
		case Src:
			switch dst := dst.(type) {
			case *image.RGBA:
				switch src := src.(type) {
				case *image.Gray:
					q.transform_RGBA_Gray_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
				case *image.NRGBA:
					q.transform_RGBA_NRGBA_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
				case *image.RGBA:
					q.transform_RGBA_RGBA_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
				case *image.YCbCr:
					switch src.SubsampleRatio {
					default:
						q.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
					case image.YCbCrSubsampleRatio444:
						q.transform_RGBA_YCbCr444_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
					case image.YCbCrSubsampleRatio422:
						q.transform_RGBA_YCbCr422_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
					case image.YCbCrSubsampleRatio420:
						q.transform_RGBA_YCbCr420_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
					case image.YCbCrSubsampleRatio440:
						q.transform_RGBA_YCbCr440_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
					}
				default:
					q.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
				}
			default:
				switch src := src.(type) {
				default:
					q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
				}
			}
		}
	}
}