Ejemplo n.º 1
0
/*
 * Class:     sun_java2d_loops_ScaledBlit
 * Method:    Scale
 * Signature: (Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;Ljava/awt/Composite;Lsun/java2d/pipe/Region;IIIIDDDD)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_loops_ScaledBlit_Scale
    (JNIEnv *env, jobject self,
     jobject srcData, jobject dstData,
     jobject comp, jobject clip,
     jint sx1, jint sy1, jint sx2, jint sy2,
     jdouble ddx1, jdouble ddy1, jdouble ddx2, jdouble ddy2)
{
    SurfaceDataOps *srcOps;
    SurfaceDataOps *dstOps;
    SurfaceDataRasInfo srcInfo;
    SurfaceDataRasInfo dstInfo;
    NativePrimitive *pPrim;
    CompositeInfo compInfo;
    jint sxinc, syinc, shift;
    jint tilesize;
    jint idx1, idy1;
    jdouble scalex, scaley;
    RegionData clipInfo;
    jint dstFlags;
    jboolean xunderflow, yunderflow;

    pPrim = GetNativePrim(env, self);
    if (pPrim == NULL) {
	return;
    }
    if (pPrim->pCompType->getCompInfo != NULL) {
	(*pPrim->pCompType->getCompInfo)(env, &compInfo, comp);
    }
    if (Region_GetInfo(env, clip, &clipInfo)) {
	return;
    }

    srcOps = SurfaceData_GetOps(env, srcData);
    dstOps = SurfaceData_GetOps(env, dstData);
    if (srcOps == 0 || dstOps == 0) {
	return;
    }

    /*
     * Determine the precision to use for the fixed point math
     * for the coordinate scaling.
     * - OR together srcw and srch to get the MSB between the two
     * - Next shift it up until it goes negative
     * - Count the shifts and that will be the most accurate
     *   precision available for the fixed point math
     * - a source coordinate of 1.0 will be (1 << shift)
     * - srcw & srch will be (srcw << shift) and (srch << shift)
     *   and will not overflow
     * Note that if srcw or srch are so large that they are
     * negative numbers before shifting, then:
     * - shift will be 0
     * - tilesize will end up being 1x1 tiles
     * - we will brute force calculate the source location
     *   of every destination pixel using the TILESTART and
     *   SRCLOC macros in this function and then call the
     *   scale helper function to copy one pixel at a time.
     * - TILESTART involves mostly jdouble calculations so
     *   it should not have integer overflow problems.
     */
    sxinc = (sx2 - sx1) | (sy2 - sy1);
    shift = 0;
    if (sxinc > 0) {
        while ((sxinc <<= 1) > 0) {
            shift++;
        }
    }
    /*
     * Now determine the scaled integer increments used to traverse
     * the source image for each destination pixel.  Our shift value
     * has been calculated above so that any location within the
     * destination image can be represented as a scaled integer
     * without incurring integer overflow.
     *
     * But we also need to worry about overflow of the sxinc and syinc
     * parameters.  We already know that "srcw<<shift" and "srch<<shift"
     * cannot overflow a jint, and the only time that sxinc and syinc
     * can be larger than those two values is if ddy2-ddy1 or ddx2-ddx1
     * are smaller than 1.  Since this situation implies that the
     * output area is no more than one pixel wide or tall, then we are
     * stepping by distances that are at least the size of the image
     * and only one destination pixel will ever be rendered - thus the
     * amount by which we step is largely irrelevant since after
     * drawing the first "in bounds" pixel, we will step completely
     * out of the source image and render nothing more.  As a result,
     * we assign the appropriate "size of image" stepping parameter
     * for any scale to smaller than one device pixel.
     */
    yunderflow = (ddy2 - ddy1) < 1.0;
    scaley = (((jdouble) (sy2 - sy1)) / (ddy2 - ddy1)) * (1 << shift);
    syinc = (yunderflow ? ((sy2 - sy1) << shift) : (jint) scaley);
    xunderflow = (ddx2 - ddx1) < 1.0;
    scalex = (((jdouble) (sx2 - sx1)) / (ddx2 - ddx1)) * (1 << shift);
    sxinc = (xunderflow ? ((sx2 - sx1) << shift) : (jint) scalex);
    tilesize = findpow2tilesize(shift, sxinc, syinc);


    srcInfo.bounds.x1 = sx1;
    srcInfo.bounds.y1 = sy1;
    srcInfo.bounds.x2 = sx2;
    srcInfo.bounds.y2 = sy2;
    if (srcOps->Lock(env, srcOps, &srcInfo, pPrim->srcflags) != SD_SUCCESS) {
	return;
    }
    if (srcInfo.bounds.x2 <= srcInfo.bounds.x1 ||
	srcInfo.bounds.y2 <= srcInfo.bounds.y1)
    {
	SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
	return;
    }

    /*
     * Only refine lower bounds if lower source coordinate was clipped
     * because the math will work out to be exactly idx1, idy1 if not.
     * Always refine upper bounds since we want to make sure not to
     * overstep the source bounds based on the tiled iteration math.
     *
     * For underflow cases, simply check if the SRCLOC for the single
     * destination pixel maps inside the source bounds.  If it does,
     * we render that pixel row or column (and only that pixel row
     * or column).  If it does not, we render nothing.
     */
    idx1 = (jint) ceil(ddx1 - 0.5);
    idy1 = (jint) ceil(ddy1 - 0.5);
    if (xunderflow) {
        jdouble x = sx1 + (SRCLOC(idx1, ddx1, scalex) / (1 << shift));
        dstInfo.bounds.x1 = dstInfo.bounds.x2 = idx1;
        if (x >= srcInfo.bounds.x1 && x < srcInfo.bounds.x2) {
            dstInfo.bounds.x2++;
        }
    } else {
        dstInfo.bounds.x1 = ((srcInfo.bounds.x1 <= sx1)
                             ? idx1
                             : refine(idx1, ddx1, tilesize, scalex,
                                      (srcInfo.bounds.x1-sx1) << shift, sxinc));
        dstInfo.bounds.x2 = refine(idx1, ddx1, tilesize, scalex,
                                   (srcInfo.bounds.x2-sx1) << shift, sxinc);
    }
    if (yunderflow) {
        jdouble y = sy1 + (SRCLOC(idy1, ddy1, scaley) / (1 << shift));
        dstInfo.bounds.y1 = dstInfo.bounds.y2 = idy1;
        if (y >= srcInfo.bounds.y1 && y < srcInfo.bounds.y2) {
            dstInfo.bounds.y2++;
        }
    } else {
        dstInfo.bounds.y1 = ((srcInfo.bounds.y1 <= sy1)
                             ? idy1
                             : refine(idy1, ddy1, tilesize, scaley,
                                      (srcInfo.bounds.y1-sy1) << shift, syinc));
        dstInfo.bounds.y2 = refine(idy1, ddy1, tilesize, scaley,
                                   (srcInfo.bounds.y2-sy1) << shift, syinc);
    }

    SurfaceData_IntersectBounds(&dstInfo.bounds, &clipInfo.bounds);
    dstFlags = pPrim->dstflags;
    if (!Region_IsRectangular(&clipInfo)) {
	dstFlags |= SD_LOCK_PARTIAL_WRITE;
    }
    if (dstOps->Lock(env, dstOps, &dstInfo, dstFlags) != SD_SUCCESS) {
	SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
	return;
    }

    if (dstInfo.bounds.x2 > dstInfo.bounds.x1 &&
	dstInfo.bounds.y2 > dstInfo.bounds.y1)
    {
	srcOps->GetRasInfo(env, srcOps, &srcInfo);
	dstOps->GetRasInfo(env, dstOps, &dstInfo);
	if (srcInfo.rasBase && dstInfo.rasBase) {
	    SurfaceDataBounds span;
	    void *pSrc = PtrCoord(srcInfo.rasBase,
				  sx1, srcInfo.pixelStride,
				  sy1, srcInfo.scanStride);

	    Region_IntersectBounds(&clipInfo, &dstInfo.bounds);
	    Region_StartIteration(env, &clipInfo);
	    if (tilesize >= (ddx2 - ddx1) &&
		tilesize >= (ddy2 - ddy1))
	    {
		/* Do everything in one tile */
		jint sxloc = (jint) SRCLOC(idx1, ddx1, scalex);
		jint syloc = (jint) SRCLOC(idy1, ddy1, scaley);
		while (Region_NextIteration(&clipInfo, &span)) {
		    jint tsxloc = sxloc;
		    jint tsyloc = syloc;
		    void *pDst;

		    if (span.y1 > idy1) {
			tsyloc += syinc * (span.y1 - idy1);
		    }
		    if (span.x1 > idx1) {
			tsxloc += sxinc * (span.x1 - idx1);
		    }

		    pDst = PtrCoord(dstInfo.rasBase,
				    span.x1, dstInfo.pixelStride,
				    span.y1, dstInfo.scanStride);
		    (*pPrim->funcs.scaledblit)(pSrc, pDst,
					       span.x2-span.x1, span.y2-span.y1,
					       tsxloc, tsyloc,
					       sxinc, syinc, shift,
					       &srcInfo, &dstInfo,
					       pPrim, &compInfo);
		}
	    } else {
		/* Break each clip span into tiles for better accuracy. */
		while (Region_NextIteration(&clipInfo, &span)) {
		    jint tilex, tiley;
		    jint sxloc, syloc;
		    jint x1, y1, x2, y2;
		    void *pDst;

		    for (tiley = TILESTART(span.y1, idy1, tilesize);
			 tiley < span.y2;
			 tiley += tilesize)
		    {
			/* Clip span to Y range of current tile */
			y1 = tiley;
			y2 = tiley + tilesize;
			if (y1 < span.y1) y1 = span.y1;
			if (y2 > span.y2) y2 = span.y2;

			/* Find scaled source coordinate of first pixel */
			syloc = (jint) SRCLOC(tiley, ddy1, scaley);
			if (y1 > tiley) {
			    syloc += syinc * (y1 - tiley);
			}

			for (tilex = TILESTART(span.x1, idx1, tilesize);
			     tilex < span.x2;
			     tilex += tilesize)
			{
			    /* Clip span to X range of current tile */
			    x1 = tilex;
			    x2 = tilex + tilesize;
			    if (x1 < span.x1) x1 = span.x1;
			    if (x2 > span.x2) x2 = span.x2;

			    /* Find scaled source coordinate of first pixel */
			    sxloc = (jint) SRCLOC(tilex, ddx1, scalex);
			    if (x1 > tilex) {
				sxloc += sxinc * (x1 - tilex);
			    }

			    pDst = PtrCoord(dstInfo.rasBase,
					    x1, dstInfo.pixelStride,
					    y1, dstInfo.scanStride);
			    (*pPrim->funcs.scaledblit)(pSrc, pDst, x2-x1, y2-y1,
						       sxloc, syloc,
						       sxinc, syinc, shift,
						       &srcInfo, &dstInfo,
						       pPrim, &compInfo);
			}
		    }
		}
	    }
	    Region_EndIteration(env, &clipInfo);
	}
	SurfaceData_InvokeRelease(env, dstOps, &dstInfo);
	SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
    }
    SurfaceData_InvokeUnlock(env, dstOps, &dstInfo);
    SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
}
Ejemplo n.º 2
0
/*
 * Class:     sun_java2d_loops_Blit
 * Method:    Blit
 * Signature: (Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;Ljava/awt/Composite;IIIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_loops_Blit_Blit
    (JNIEnv *env, jobject self,
     jobject srcData, jobject dstData, jobject comp, jobject clip,
     jint srcx, jint srcy, jint dstx, jint dsty, jint width, jint height)
{
    SurfaceDataOps *srcOps;
    SurfaceDataOps *dstOps;
    SurfaceDataRasInfo srcInfo;
    SurfaceDataRasInfo dstInfo;
    NativePrimitive *pPrim;
    CompositeInfo compInfo;
    RegionData clipInfo;
    jint dstFlags;

    pPrim = GetNativePrim(env, self);
    if (pPrim == NULL) {
	return;
    }
    if (pPrim->pCompType->getCompInfo != NULL) {
	(*pPrim->pCompType->getCompInfo)(env, &compInfo, comp);
    }
    if (Region_GetInfo(env, clip, &clipInfo)) {
	return;
    }

    srcOps = SurfaceData_GetOps(env, srcData);
    dstOps = SurfaceData_GetOps(env, dstData);
    if (srcOps == 0 || dstOps == 0) {
	return;
    }

    srcInfo.bounds.x1 = srcx;
    srcInfo.bounds.y1 = srcy;
    srcInfo.bounds.x2 = srcx + width;
    srcInfo.bounds.y2 = srcy + height;
    dstInfo.bounds.x1 = dstx;
    dstInfo.bounds.y1 = dsty;
    dstInfo.bounds.x2 = dstx + width;
    dstInfo.bounds.y2 = dsty + height;
    srcx -= dstx;
    srcy -= dsty;
    SurfaceData_IntersectBounds(&dstInfo.bounds, &clipInfo.bounds);
    if (srcOps->Lock(env, srcOps, &srcInfo, pPrim->srcflags) != SD_SUCCESS) {
	return;
    }

    dstFlags = pPrim->dstflags;
    if (!Region_IsRectangular(&clipInfo)) {
	dstFlags |= SD_LOCK_PARTIAL_WRITE;
    }
    if (dstOps->Lock(env, dstOps, &dstInfo, dstFlags) != SD_SUCCESS) {
	SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
	return;
    }
    SurfaceData_IntersectBlitBounds(&dstInfo.bounds, &srcInfo.bounds,
				    srcx, srcy);
    Region_IntersectBounds(&clipInfo, &dstInfo.bounds);

    if (!Region_IsEmpty(&clipInfo)) {
	srcOps->GetRasInfo(env, srcOps, &srcInfo);
	dstOps->GetRasInfo(env, dstOps, &dstInfo);
	if (srcInfo.rasBase && dstInfo.rasBase) {
	    SurfaceDataBounds span;
	    jint savesx = srcInfo.bounds.x1;
	    jint savedx = dstInfo.bounds.x1;
	    Region_StartIteration(env, &clipInfo);
	    while (Region_NextIteration(&clipInfo, &span)) {
		void *pSrc = PtrCoord(srcInfo.rasBase,
				      srcx + span.x1, srcInfo.pixelStride,
				      srcy + span.y1, srcInfo.scanStride);
		void *pDst = PtrCoord(dstInfo.rasBase,
				      span.x1, dstInfo.pixelStride,
				      span.y1, dstInfo.scanStride);
		/*
		 * Fix for 4804375
		 * REMIND: There should probably be a better
		 * way to give the span coordinates to the
		 * inner loop.  This is only really needed
		 * for the 1, 2, and 4 bit loops.
		 */
		srcInfo.bounds.x1 = srcx + span.x1;
		dstInfo.bounds.x1 = span.x1;
		(*pPrim->funcs.blit)(pSrc, pDst,
				     span.x2 - span.x1, span.y2 - span.y1,
				     &srcInfo, &dstInfo, pPrim, &compInfo);
	    }
	    Region_EndIteration(env, &clipInfo);
	    srcInfo.bounds.x1 = savesx;
	    dstInfo.bounds.x1 = savedx;
	}
	SurfaceData_InvokeRelease(env, dstOps, &dstInfo);
	SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
    }
    SurfaceData_InvokeUnlock(env, dstOps, &dstInfo);
    SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
}
Ejemplo n.º 3
0
/*
 * Class:     sun_java2d_loops_ScaledBlit
 * Method:    Scale
 * Signature: (Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;Ljava/awt/Composite;IIIIIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_loops_ScaledBlit_Scale
    (JNIEnv *env, jobject self,
     jobject srcData, jobject dstData,
     jobject comp, jobject clip,
     jint srcx, jint srcy, jint dstx, jint dsty,
     jint srcw, jint srch, jint dstw, jint dsth)
{
    SurfaceDataOps *srcOps;
    SurfaceDataOps *dstOps;
    SurfaceDataRasInfo srcInfo;
    SurfaceDataRasInfo dstInfo;
    NativePrimitive *pPrim;
    CompositeInfo compInfo;
    jint sxloc, syloc, sxinc, syinc, shift;
    double scale;
    RegionData clipInfo;
    jint dstFlags;

    pPrim = GetNativePrim(env, self);
    if (pPrim == NULL) {
	return;
    }
    if (pPrim->pCompType->getCompInfo != NULL) {
	(*pPrim->pCompType->getCompInfo)(env, &compInfo, comp);
    }
    if (Region_GetInfo(env, clip, &clipInfo)) {
	return;
    }

    srcOps = SurfaceData_GetOps(env, srcData);
    dstOps = SurfaceData_GetOps(env, dstData);
    if (srcOps == 0 || dstOps == 0) {
	return;
    }

    /*
     * Determine the precision to use for the fixed point math
     * for the coordinate scaling.
     * - OR together srcw and srch to get the MSB between the two
     * - Next shift it up until it goes negative
     * - Count the shifts and that will be the most accurate
     *   precision available for the fixed point math
     * - 1.0 will be (1 << shift)
     * - srcw & srch will be (srcw << shift) and (srch << shift)
     *   and will not overflow
     */
    sxloc = srcw | srch;
    shift = 0;
    while ((sxloc <<= 1) > 0) {
	shift++;
    }
    sxloc = (1 << shift);
    scale = ((double) (srch)) / ((double) (dsth));
    syinc = (int) (scale * sxloc);
    scale = ((double) (srcw)) / ((double) (dstw));
    sxinc = (int) (scale * sxloc);

    /*
     * Round by setting the initial sxyloc to half a destination
     * pixel which equals half of the x/y increments.
     */
    sxloc = sxinc / 2;
    syloc = syinc / 2;

    srcw += srcx;
    srch += srcy;
    srcInfo.bounds.x1 = srcx;
    srcInfo.bounds.y1 = srcy;
    srcInfo.bounds.x2 = srcw;
    srcInfo.bounds.y2 = srch;
    if (srcOps->Lock(env, srcOps, &srcInfo, pPrim->srcflags) != SD_SUCCESS) {
	return;
    }
    if (srcInfo.bounds.x2 <= srcInfo.bounds.x1 ||
	srcInfo.bounds.y2 <= srcInfo.bounds.y1)
    {
	SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
	return;
    }
    dstw += dstx;
    dsth += dsty;
    Scale_adjustUp(srcx, srcInfo.bounds.x1,
		   &sxloc, sxinc, shift,
		   &dstx);
    Scale_adjustUp(srcy, srcInfo.bounds.y1,
		   &syloc, syinc, shift,
		   &dsty);
    Scale_adjustDn(srcw, srcInfo.bounds.x1, srcInfo.bounds.x2,
		   sxloc, sxinc, shift,
		   dstx, &dstw);
    Scale_adjustDn(srch, srcInfo.bounds.y1, srcInfo.bounds.y2,
		   syloc, syinc, shift,
		   dsty, &dsth);

    dstInfo.bounds.x1 = dstx;
    dstInfo.bounds.y1 = dsty;
    dstInfo.bounds.x2 = dstw;
    dstInfo.bounds.y2 = dsth;
    SurfaceData_IntersectBounds(&dstInfo.bounds, &clipInfo.bounds);
    dstFlags = pPrim->dstflags;
    if (!Region_IsRectangular(&clipInfo)) {
	dstFlags |= SD_LOCK_PARTIAL_WRITE;
    }
    if (dstOps->Lock(env, dstOps, &dstInfo, dstFlags) != SD_SUCCESS) {
	SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
	return;
    }

    if (dstInfo.bounds.x2 > dstInfo.bounds.x1 &&
	dstInfo.bounds.y2 > dstInfo.bounds.y1)
    {
	srcOps->GetRasInfo(env, srcOps, &srcInfo);
	dstOps->GetRasInfo(env, dstOps, &dstInfo);
	if (srcInfo.rasBase && dstInfo.rasBase) {
	    SurfaceDataBounds span;
	    void *pSrc = PtrCoord(srcInfo.rasBase,
				  srcInfo.bounds.x1, srcInfo.pixelStride,
				  srcInfo.bounds.y1, srcInfo.scanStride);
	    Region_IntersectBounds(&clipInfo, &dstInfo.bounds);
	    Region_StartIteration(env, &clipInfo);
	    while (Region_NextIteration(&clipInfo, &span)) {
		jint width = span.x2 - span.x1;
		jint height = span.y2 - span.y1;
		jint tsxloc = sxloc;
		jint tsyloc = syloc;
		void *pDst = PtrCoord(dstInfo.rasBase,
				      span.x1, dstInfo.pixelStride,
				      span.y1, dstInfo.scanStride);
		if (span.y1 > dsty) {
		    tsyloc += syinc * (span.y1 - dsty);
		}
		if (span.x1 > dstx) {
		    tsxloc += sxinc * (span.x1 - dstx);
		}
		(*pPrim->funcs.scaledblit)(pSrc, pDst, width, height,
					   tsxloc, tsyloc, sxinc, syinc, shift,
					   &srcInfo, &dstInfo,
					   pPrim, &compInfo);
	    }
	    Region_EndIteration(env, &clipInfo);
	}
	SurfaceData_InvokeRelease(env, dstOps, &dstInfo);
	SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
    }
    SurfaceData_InvokeUnlock(env, dstOps, &dstInfo);
    SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
}