/* * Fill the edge buffer with pairs of coordinates representing the maximum * left and right pixels of the destination surface that should be processed * on each scanline, clipped to the bounds parameter. * The number of scanlines to calculate is implied by the bounds parameter. * Only pixels that map back through the specified (inverse) transform to a * source coordinate that falls within the (0, 0, sw, sh) bounds of the * source image should be processed. * pEdges points to an array of jints that holds 2 + numedges*2 values where * numedges should match (pBounds->y2 - pBounds->y1). * The first two jints in pEdges should be set to y1 and y2 and every pair * of jints after that represent the xmin,xmax of all pixels in range of * the transformed blit for the corresponding scanline. */ static void calculateEdges(jint *pEdges, SurfaceDataBounds *pBounds, TransformInfo *pItxInfo, jlong xbase, jlong ybase, juint sw, juint sh) { jlong dxdxlong, dydxlong; jlong dxdylong, dydylong; jlong drowxlong, drowylong; jint dx1, dy1, dx2, dy2; dxdxlong = DblToLong(pItxInfo->dxdx); dydxlong = DblToLong(pItxInfo->dydx); dxdylong = DblToLong(pItxInfo->dxdy); dydylong = DblToLong(pItxInfo->dydy); dx1 = pBounds->x1; dy1 = pBounds->y1; dx2 = pBounds->x2; dy2 = pBounds->y2; *pEdges++ = dy1; *pEdges++ = dy2; drowxlong = (dx2-dx1-1) * dxdxlong; drowylong = (dx2-dx1-1) * dydxlong; while (dy1 < dy2) { jlong xlong, ylong; dx1 = pBounds->x1; dx2 = pBounds->x2; xlong = xbase; ylong = ybase; while (dx1 < dx2 && (((juint) WholeOfLong(ylong)) >= sh || ((juint) WholeOfLong(xlong)) >= sw)) { dx1++; xlong += dxdxlong; ylong += dydxlong; } xlong = xbase + drowxlong; ylong = ybase + drowylong; while (dx2 > dx1 && (((juint) WholeOfLong(ylong)) >= sh || ((juint) WholeOfLong(xlong)) >= sw)) { dx2--; xlong -= dxdxlong; ylong -= dydxlong; } *pEdges++ = dx1; *pEdges++ = dx2; /* Increment to next scanline */ xbase += dxdylong; ybase += dydylong; dy1++; } }
static void Transform_SafeHelper(JNIEnv *env, SurfaceDataOps *srcOps, SurfaceDataOps *dstOps, SurfaceDataRasInfo *pSrcInfo, SurfaceDataRasInfo *pDstInfo, NativePrimitive *pMaskBlitPrim, CompositeInfo *pCompInfo, TransformHelperFunc *pHelperFunc, TransformInterpFunc *pInterpFunc, RegionData *pClipInfo, TransformInfo *pItxInfo, jint *pData, jint *pEdges, jint dxoff, jint dyoff, jint sw, jint sh) { SurfaceDataBounds span; jint dx1, dx2; jint dy1, dy2; jint i, iy; dy1 = pDstInfo->bounds.y1; dy2 = pDstInfo->bounds.y2; dx1 = pDstInfo->bounds.x1; dx2 = pDstInfo->bounds.x2; pEdges[0] = dy1; pEdges[1] = dy2; for (iy = dy1; iy < dy2; iy++) { jint i = (iy - dy1) * 2; /* row spans are set to max,min until we find a pixel in range below */ pEdges[i + 2] = dx2; pEdges[i + 3] = dx1; } Region_StartIteration(env, pClipInfo); while (Region_NextIteration(pClipInfo, &span)) { dy1 = span.y1; dy2 = span.y2; while (dy1 < dy2) { dx1 = span.x1; dx2 = span.x2; i = (dy1 - pDstInfo->bounds.y1) * 2; while (dx1 < dx2) { jdouble x, y; jlong xlong, ylong; x = dxoff + dx1 + 0.5; y = dyoff + dy1 + 0.5; Transform_transform(pItxInfo, &x, &y); xlong = DblToLong(x); ylong = DblToLong(y); /* Process only pixels with centers in bounds * Test double values to avoid overflow in conversion * to long values and then also test the long values * in case they rounded up and out of bounds during * the conversion. */ if (x >= 0 && y >= 0 && x < sw && y < sh && WholeOfLong(xlong) < sw && WholeOfLong(ylong) < sh) { void *pDst; if (pEdges[i + 2] > dx1) { pEdges[i + 2] = dx1; } if (pEdges[i + 3] <= dx1) { pEdges[i + 3] = dx1 + 1; } /* Get IntArgbPre pixel data from source */ (*pHelperFunc)(pSrcInfo, pData, 1, xlong, 0, ylong, 0); /* Interpolate result pixels if needed */ if (pInterpFunc) { (*pInterpFunc)(pData, 1, FractOfLong(xlong-LongOneHalf), 0, FractOfLong(ylong-LongOneHalf), 0); } /* Store/Composite interpolated pixels into dest */ pDst = PtrCoord(pDstInfo->rasBase, dx1, pDstInfo->pixelStride, dy1, pDstInfo->scanStride); (*pMaskBlitPrim->funcs.maskblit)(pDst, pData, 0, 0, 0, 1, 1, pDstInfo, pSrcInfo, pMaskBlitPrim, pCompInfo); } /* Increment to next input pixel */ dx1++; } /* Increment to next scanline */ dy1++; } } Region_EndIteration(env, pClipInfo); }
/* * Fill the edge buffer with pairs of coordinates representing the maximum * left and right pixels of the destination surface that should be processed * on each scanline, clipped to the bounds parameter. * The number of scanlines to calculate is implied by the bounds parameter. * Only pixels that map back through the specified (inverse) transform to a * source coordinate that falls within the (0, 0, sw, sh) bounds of the * source image should be processed. * pEdgeBuf points to an array of jints that holds MAXEDGES*2 values. * If more storage is needed, then this function allocates a new buffer. * In either case, a pointer to the buffer actually used to store the * results is returned. * The caller is responsible for freeing the buffer if the return value * is not the same as the original pEdgeBuf passed in. */ static jint * calculateEdges(jint *pEdgeBuf, SurfaceDataBounds *pBounds, TransformInfo *pItxInfo, jlong xbase, jlong ybase, juint sw, juint sh) { jint *pEdges; jlong dxdxlong, dydxlong; jlong dxdylong, dydylong; jlong drowxlong, drowylong; jint dx1, dy1, dx2, dy2; dxdxlong = DblToLong(pItxInfo->dxdx); dydxlong = DblToLong(pItxInfo->dydx); dxdylong = DblToLong(pItxInfo->dxdy); dydylong = DblToLong(pItxInfo->dydy); dx1 = pBounds->x1; dy1 = pBounds->y1; dx2 = pBounds->x2; dy2 = pBounds->y2; if ((dy2-dy1) > MAXEDGES) { pEdgeBuf = malloc(2 * (dy2-dy1) * sizeof (*pEdges)); } pEdges = pEdgeBuf; drowxlong = (dx2-dx1-1) * dxdxlong; drowylong = (dx2-dx1-1) * dydxlong; while (dy1 < dy2) { jlong xlong, ylong; dx1 = pBounds->x1; dx2 = pBounds->x2; xlong = xbase; ylong = ybase; while (dx1 < dx2 && (((juint) WholeOfLong(ylong)) >= sh || ((juint) WholeOfLong(xlong)) >= sw)) { dx1++; xlong += dxdxlong; ylong += dydxlong; } xlong = xbase + drowxlong; ylong = ybase + drowylong; while (dx2 > dx1 && (((juint) WholeOfLong(ylong)) >= sh || ((juint) WholeOfLong(xlong)) >= sw)) { dx2--; xlong -= dxdxlong; ylong -= dydxlong; } *pEdges++ = dx1; *pEdges++ = dx2; /* Increment to next scanline */ xbase += dxdylong; ybase += dydylong; dy1++; } return pEdgeBuf; }