예제 #1
0
/*
 * Class:     sun_java2d_windows_GDIRenderer
 * Method:    doDrawOval
 * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;IIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIRenderer_doDrawOval
    (JNIEnv *env, jobject wr,
     jobject sData,
     jobject clip, jobject comp, jint color,
     jint x, jint y, jint w, jint h)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doDrawOval");
    J2dTraceLn5(J2D_TRACE_VERBOSE,
                "  color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d",
                color, x, y, w, h);
    if (w < 2 || h < 2) {
        // Thin enough ovals have no room for curvature.  Defer to
        // the DrawRect method which handles degenerate sizes better.
        Java_sun_java2d_windows_GDIRenderer_doDrawRect(env, wr,
                                                       sData, clip,
                                                       comp, color,
                                                       x, y, w, h);
        return;
    }

    GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData);
    if (wsdo == NULL) {
        return;
    }
    HDC hdc = wsdo->GetDC(env, wsdo, PENONLY, NULL, clip, comp, color);
    if (hdc == NULL) {
        return;
    }
    ::Ellipse(hdc, x, y, x+w+1, y+h+1);
    wsdo->ReleaseDC(env, wsdo, hdc);
}
예제 #2
0
/*
 * Class:     sun_java2d_windows_GDIRenderer
 * Method:    doFillRect
 * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;IIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIRenderer_doFillRect
    (JNIEnv *env, jobject wr,
     jobject sData,
     jobject clip, jobject comp, jint color,
     jint x, jint y, jint w, jint h)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doFillRect");
    J2dTraceLn5(J2D_TRACE_VERBOSE,
                "  color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d",
                color, x, y, w, h);
    if (w <= 0 || h <= 0) {
        return;
    }

    GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData);
    if (wsdo == NULL) {
        return;
    }
    jint patrop;
    HDC hdc = wsdo->GetDC(env, wsdo, BRUSH, &patrop, clip, comp, color);
    if (hdc == NULL) {
        return;
    }
    ::PatBlt(hdc, x, y, w, h, patrop);
    wsdo->ReleaseDC(env, wsdo, hdc);
}
예제 #3
0
/*
 * Class:     sun_java2d_windows_GDIRenderer
 * Method:    doFillPoly
 * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;III[I[II)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIRenderer_doFillPoly
    (JNIEnv *env, jobject wr,
     jobject sData,
     jobject clip, jobject comp, jint color,
     jint transx, jint transy,
     jintArray xpointsarray, jintArray ypointsarray,
     jint npoints)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doFillPoly");
    J2dTraceLn4(J2D_TRACE_VERBOSE,
                "  color=0x%x transx=%-4d transy=%-4d npoints=%-4d",
                color, transx, transy, npoints);
    if (JNU_IsNull(env, xpointsarray) || JNU_IsNull(env, ypointsarray)) {
        JNU_ThrowNullPointerException(env, "coordinate array");
        return;
    }
    if (env->GetArrayLength(xpointsarray) < npoints ||
        env->GetArrayLength(ypointsarray) < npoints)
    {
        JNU_ThrowArrayIndexOutOfBoundsException(env, "coordinate array");
        return;
    }
    if (npoints < 3) {
        // Fix for 4067534 - assertion failure in 1.3.1 for degenerate polys
        // Not enough points for a triangle.
        // Note that this would be ignored later anyway, but returning
        // here saves us from mistakes in TransformPoly and seeing bad
        // return values from the Windows Polyline function.
        return;
    }

    GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData);
    if (wsdo == NULL) {
        return;
    }

    POINT tmpPts[POLYTEMPSIZE], *pPoints;
    jint *xpoints = (jint *) env->GetPrimitiveArrayCritical(xpointsarray, NULL);
    jint *ypoints = (jint *) env->GetPrimitiveArrayCritical(ypointsarray, NULL);
    pPoints = TransformPoly(xpoints, ypoints, transx, transy,
                            tmpPts, &npoints, FALSE, FALSE);
    env->ReleasePrimitiveArrayCritical(xpointsarray, xpoints, JNI_ABORT);
    env->ReleasePrimitiveArrayCritical(ypointsarray, ypoints, JNI_ABORT);
    if (pPoints == NULL) {
        return;
    }

    HDC hdc = wsdo->GetDC(env, wsdo, BRUSHONLY, NULL, clip, comp, color);
    if (hdc == NULL) {
        return;
    }
    ::SetPolyFillMode(hdc, ALTERNATE);
    ::Polygon(hdc, pPoints, npoints);
    wsdo->ReleaseDC(env, wsdo, hdc);
    if (pPoints != tmpPts) {
        free(pPoints);
    }
}
예제 #4
0
/*
 * Class:     sun_java2d_windows_GDIRenderer
 * Method:    devCopyArea
 * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;IIIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIRenderer_devCopyArea
    (JNIEnv *env, jobject wr,
     jobject wsd,
     jint srcx, jint srcy,
     jint dx, jint dy,
     jint width, jint height)
{
    GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, wsd);
    J2dTraceLn(J2D_TRACE_INFO, "GDIWindowSurfaceData_devCopyArea");
    J2dTraceLn4(J2D_TRACE_VERBOSE, "   srcx=%-4d srcy=%-4d dx=%-4d dy=%-4d",
                srcx, srcy, dx, dy);
    J2dTraceLn2(J2D_TRACE_VERBOSE, "     w=%-4d h=%-4d", width, height);
    if (wsdo == NULL) {
        return;
    }
    if (wsdo->invalid) {
        SurfaceData_ThrowInvalidPipeException(env,
            "GDIRenderer_devCopyArea: invalid surface data");
        return;
    }

    HDC hDC = wsdo->GetDC(env, wsdo, 0, NULL, NULL, NULL, 0);
    if (hDC == NULL) {
        return;
    }

    RECT r;
    ::SetRect(&r, srcx, srcy, srcx + width, srcy + height);
    HRGN rgnUpdate = ::CreateRectRgn(0, 0, 0, 0);
    VERIFY(::ScrollDC(hDC, dx, dy, &r, NULL, rgnUpdate, NULL));

    // ScrollDC invalidates the part of the source rectangle that
    // is outside of the destination rectangle on the assumption
    // that you wanted to "move" the pixels from source to dest,
    // and so now you will want to paint new pixels in the source.
    // Since our copyarea operation involves no such semantics we
    // are only interested in the part of the update region that
    // corresponds to unavailable source pixels - i.e. the part
    // that falls within the destination rectangle.

    // The update region will be in client relative coordinates
    // but the destination rect will be in window relative coordinates
    ::OffsetRect(&r, dx-wsdo->insets.left, dy-wsdo->insets.top);
    HRGN rgnDst = ::CreateRectRgnIndirect(&r);
    int result = ::CombineRgn(rgnUpdate, rgnUpdate, rgnDst, RGN_AND);

    // Invalidate the exposed area.
    if (result != NULLREGION) {
        ::InvalidateRgn(wsdo->window, rgnUpdate, TRUE);
    }
    ::DeleteObject(rgnUpdate);
    ::DeleteObject(rgnDst);

    wsdo->ReleaseDC(env, wsdo, hDC);
}
예제 #5
0
/*
 * Class:     sun_java2d_windows_GDIRenderer
 * Method:    doFillArc
 * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;IIIIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIRenderer_doFillArc
    (JNIEnv *env, jobject wr,
     jobject sData,
     jobject clip, jobject comp, jint color,
     jint x, jint y, jint w, jint h,
     jint angleStart, jint angleExtent)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doFillArc");
    J2dTraceLn5(J2D_TRACE_VERBOSE,
                "  color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d",
                color, x, y, w, h);
    J2dTraceLn2(J2D_TRACE_VERBOSE,
                "  angleStart=%-4d angleExtent=%-4d",
                angleStart, angleExtent);
    if (w <= 0 || h <= 0 || angleExtent == 0) {
        return;
    }
    if (angleExtent >= 360 || angleExtent <= -360) {
        // Fix related to 4411814 - small ovals (and arcs) do not draw
        // If the arc is a full circle, let the Oval method handle it
        // since that method can deal with degenerate sizes better.
        Java_sun_java2d_windows_GDIRenderer_doFillOval(env, wr,
                                                       sData, clip,
                                                       comp, color,
                                                       x, y, w, h);
        return;
    }

    GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData);
    if (wsdo == NULL) {
        return;
    }
    long sx, sy, ex, ey;
    int angleEnd;
    if (angleExtent < 0) {
        angleEnd = angleStart;
        angleStart += angleExtent;
    } else {
        angleEnd = angleStart + angleExtent;
    }
    AngleToCoord(angleStart, w, h, &sx, &sy);
    sx += x + w/2;
    sy += y + h/2;
    AngleToCoord(angleEnd, w, h, &ex, &ey);
    ex += x + w/2;
    ey += y + h/2;
    HDC hdc = wsdo->GetDC(env, wsdo, BRUSHONLY, NULL, clip, comp, color);
    if (hdc == NULL) {
        return;
    }
    ::Pie(hdc, x, y, x+w+1, y+h+1, sx, sy, ex, ey);
    wsdo->ReleaseDC(env, wsdo, hdc);
}
예제 #6
0
/*
 * Class:     sun_java2d_windows_GDIRenderer
 * Method:    doDrawArc
 * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;IIIIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIRenderer_doDrawArc
    (JNIEnv *env, jobject wr,
     jobject sData,
     jobject clip, jobject comp, jint color,
     jint x, jint y, jint w, jint h,
     jint angleStart, jint angleExtent)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doDrawArc");
    J2dTraceLn5(J2D_TRACE_VERBOSE,
                "  color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d",
                color, x, y, w, h);
    J2dTraceLn2(J2D_TRACE_VERBOSE,
                "  angleStart=%-4d angleExtent=%-4d",
                angleStart, angleExtent);
    if (w < 0 || h < 0 || angleExtent == 0) {
        return;
    }

    GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData);
    if (wsdo == NULL) {
        return;
    }

    long sx, sy, ex, ey;
    if (angleExtent >= 360 || angleExtent <= -360) {
        sx = ex = x + w;
        sy = ey = y + h/2;
    } else {
        int angleEnd;
        if (angleExtent < 0) {
            angleEnd = angleStart;
            angleStart += angleExtent;
        } else {
            angleEnd = angleStart + angleExtent;
        }
        AngleToCoord(angleStart, w, h, &sx, &sy);
        sx += x + w/2;
        sy += y + h/2;
        AngleToCoord(angleEnd, w, h, &ex, &ey);
        ex += x + w/2;
        ey += y + h/2;
    }
    HDC hdc = wsdo->GetDC(env, wsdo, PEN, NULL, clip, comp, color);
    if (hdc == NULL) {
        return;
    }
    ::Arc(hdc, x, y, x+w+1, y+h+1, sx, sy, ex, ey);
    wsdo->ReleaseDC(env, wsdo, hdc);
}
예제 #7
0
/*
 * Class:     sun_java2d_windows_GDIRenderer
 * Method:    doDrawLine
 * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;IIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIRenderer_doDrawLine
    (JNIEnv *env, jobject wr,
     jobject sData,
     jobject clip, jobject comp, jint color,
     jint x1, jint y1, jint x2, jint y2)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doDrawLine");
    J2dTraceLn5(J2D_TRACE_VERBOSE,
                "  color=0x%x x1=%-4d y1=%-4d x2=%-4d y2=%-4d",
                color, x1, y1, x2, y2);
    GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData);
    if (wsdo == NULL) {
        return;
    }

    HDC hdc;
    jint patrop;
    if (x1 == x2 || y1 == y2) {
        if (x1 > x2) {
            jint t = x1; x1 = x2; x2 = t;
        }
        if (y1 > y2) {
            jint t = y1; y1 = y2; y2 = t;
        }
        hdc = wsdo->GetDC(env, wsdo, BRUSH, &patrop, clip, comp, color);
        if (hdc == NULL) {
            return;
        }
        ::PatBlt(hdc, x1, y1, x2-x1+1, y2-y1+1, patrop);
    } else {
        hdc = wsdo->GetDC(env, wsdo, PENBRUSH, &patrop, clip, comp, color);
        if (hdc == NULL) {
            return;
        }
        ::MoveToEx(hdc, x1, y1, NULL);
        ::LineTo(hdc, x2, y2);
        ::PatBlt(hdc, x2, y2, 1, 1, patrop);
    }
    wsdo->ReleaseDC(env, wsdo, hdc);
}
예제 #8
0
/*
 * Class:     sun_java2d_windows_GDIRenderer
 * Method:    doDrawRect
 * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;IIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIRenderer_doDrawRect
    (JNIEnv *env, jobject wr,
     jobject sData,
     jobject clip, jobject comp, jint color,
     jint x, jint y, jint w, jint h)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doDrawRect");
    J2dTraceLn5(J2D_TRACE_VERBOSE,
                "  color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d",
                color, x, y, w, h);
    if (w < 0 || h < 0) {
        return;
    }

    GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData);
    if (wsdo == NULL) {
        return;
    }
    jint patrop;
    HDC hdc = wsdo->GetDC(env, wsdo, BRUSH, &patrop, clip, comp, color);
    if (hdc == NULL) {
        return;
    }
    if (w < 2 || h < 2) {
        // If one dimension is less than 2 then there is no
        // gap in the middle - draw a solid filled rectangle.
        ::PatBlt(hdc, x, y, w+1, h+1, patrop);
    } else {
        // Avoid drawing the endpoints twice.
        // Also prefer including the endpoints in the
        // horizontal sections which draw pixels faster.
        ::PatBlt(hdc,  x,   y,  w+1,  1,  patrop);
        ::PatBlt(hdc,  x,  y+1,  1,  h-1, patrop);
        ::PatBlt(hdc, x+w, y+1,  1,  h-1, patrop);
        ::PatBlt(hdc,  x,  y+h, w+1,  1,  patrop);
    }
    wsdo->ReleaseDC(env, wsdo, hdc);
}
예제 #9
0
/*
 * Class:     sun_java2d_windows_GDIRenderer
 * Method:    doDrawRoundRect
 * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;IIIIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIRenderer_doDrawRoundRect
    (JNIEnv *env, jobject wr,
     jobject sData,
     jobject clip, jobject comp, jint color,
     jint x, jint y, jint w, jint h, jint arcW, jint arcH)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doDrawRoundRect");
    J2dTraceLn5(J2D_TRACE_VERBOSE,
                "  color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d",
                color, x, y, w, h);
    J2dTraceLn2(J2D_TRACE_VERBOSE, "  arcW=%-4d arcH=%-4d",
                arcW, arcH);
    if (w < 2 || h < 2 || arcW <= 0 || arcH <= 0) {
        // Fix for 4524760 - drawRoundRect0 test case fails on Windows 98
        // Thin round rects degenerate into regular rectangles
        // because there is no room for the arc sections.  Also
        // if there is no arc dimension then the roundrect must
        // be a simple rectangle.  Defer to the DrawRect function
        // which handles degenerate sizes better.
        Java_sun_java2d_windows_GDIRenderer_doDrawRect(env, wr,
                                                       sData, clip,
                                                       comp, color,
                                                       x, y, w, h);
        return;
    }

    GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData);
    if (wsdo == NULL) {
        return;
    }
    HDC hdc = wsdo->GetDC(env, wsdo, PENONLY, NULL, clip, comp, color);
    if (hdc == NULL) {
        return;
    }
    ::RoundRect(hdc, x, y, x+w+1, y+h+1, arcW, arcH);
    wsdo->ReleaseDC(env, wsdo, hdc);
}
예제 #10
0
/*
 * Class:     sun_java2d_windows_GDIRenderer
 * Method:    doFillRoundRect
 * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;IIIIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIRenderer_doFillRoundRect
    (JNIEnv *env, jobject wr,
     jobject sData,
     jobject clip, jobject comp, jint color,
     jint x, jint y, jint w, jint h, jint arcW, jint arcH)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doFillRoundRect");
    J2dTraceLn5(J2D_TRACE_VERBOSE,
                "  color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d",
                color, x, y, w, h);
    J2dTraceLn2(J2D_TRACE_VERBOSE, "  arcW=%-4d arcH=%-4d",
                arcW, arcH);
    if (w < 2 || h < 2 || arcW <= 0 || arcH <= 0) {
        // Fix related to 4524760 - drawRoundRect0 fails on Windows 98
        // Thin round rects have no room for curvature.  Also, if
        // the curvature is empty then the primitive has degenerated
        // into a simple rectangle.  Defer to the FillRect method
        // which deals with degenerate sizes better.
        Java_sun_java2d_windows_GDIRenderer_doFillRect(env, wr,
                                                       sData, clip,
                                                       comp, color,
                                                       x, y, w, h);
        return;
    }

    GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData);
    if (wsdo == NULL) {
        return;
    }
    HDC hdc = wsdo->GetDC(env, wsdo, BRUSHONLY, NULL, clip, comp, color);
    if (hdc == NULL) {
        return;
    }
    ::RoundRect(hdc, x, y, x+w+1, y+h+1, arcW, arcH);
    wsdo->ReleaseDC(env, wsdo, hdc);
}
예제 #11
0
/*
 * Class:     sun_java2d_windows_GDIRenderer
 * Method:    doShape
 * Signature:  (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;
 *              Ljava/awt/Composite;IIILjava/awt/geom/Path2D.Float;Z)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIRenderer_doShape
    (JNIEnv *env, jobject wr,
     jobject sData,
     jobject clip, jobject comp, jint color,
     jint transX, jint transY,
     jobject p2df, jboolean isfill)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doShape");
    J2dTraceLn4(J2D_TRACE_VERBOSE,
                "  color=0x%x transx=%-4d transy=%-4d isfill=%-4d",
                color, transX, transY, isfill);
    GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData);
    if (wsdo == NULL) {
        return;
    }

    jarray typesarray = (jarray) env->GetObjectField(p2df, path2DTypesID);
    jarray coordsarray = (jarray) env->GetObjectField(p2df,
                                                      path2DFloatCoordsID);
    if (coordsarray == NULL) {
        JNU_ThrowNullPointerException(env, "coordinates array");
        return;
    }
    jint numtypes = env->GetIntField(p2df, path2DNumTypesID);
    if (env->GetArrayLength(typesarray) < numtypes) {
        JNU_ThrowArrayIndexOutOfBoundsException(env, "types array");
        return;
    }
    jint maxcoords = env->GetArrayLength(coordsarray);
    jint rule = env->GetIntField(p2df, path2DWindingRuleID);

    HDC hdc = wsdo->GetDC(env, wsdo, (isfill ? BRUSH : PEN), NULL,
                          clip, comp, color);
    if (hdc == NULL) {
        return;
    }
    ::SetPolyFillMode(hdc, (rule == java_awt_geom_PathIterator_WIND_NON_ZERO
                            ? WINDING : ALTERNATE));
    ::BeginPath(hdc);
    jbyte *types = (jbyte *) env->GetPrimitiveArrayCritical(typesarray,
                                                            NULL);
    jfloat *coords = (jfloat *) env->GetPrimitiveArrayCritical(coordsarray,
                                                               NULL);
    int index = 0;
    BOOL ok = TRUE;
    BOOL isempty = TRUE;
    BOOL isapoint = TRUE;
    int mx = 0, my = 0, x1 = 0, y1 = 0;
    POINT ctrlpts[3];
    for (int i = 0; ok && i < numtypes; i++) {
        switch (types[i]) {
        case java_awt_geom_PathIterator_SEG_MOVETO:
            if (!isfill && !isempty) {
                // Fix for 4298688 - draw(Line) omits last pixel
                // Windows omits the last pixel of a path when stroking.
                // Fix up the last segment of the previous subpath by
                // adding another segment after it that is only 1 pixel
                // long.  The first pixel of that segment will be drawn,
                // but the second pixel is the one that Windows omits.
                ::LineTo(hdc, x1+1, y1);
            }
            if (index + 2 <= maxcoords) {
                mx = x1 = transX + (int) floor(coords[index++]);
                my = y1 = transY + (int) floor(coords[index++]);
                ::MoveToEx(hdc, x1, y1, NULL);
                isempty = TRUE;
                isapoint = TRUE;
            } else {
                ok = FALSE;
            }
            break;
        case java_awt_geom_PathIterator_SEG_LINETO:
            if (index + 2 <= maxcoords) {
                x1 = transX + (int) floor(coords[index++]);
                y1 = transY + (int) floor(coords[index++]);
                ::LineTo(hdc, x1, y1);
                isapoint = isapoint && (x1 == mx && y1 == my);
                isempty = FALSE;
            } else {
                ok = FALSE;
            }
            break;
        case java_awt_geom_PathIterator_SEG_QUADTO:
            if (index + 4 <= maxcoords) {
                ctrlpts[0].x = transX + (int) floor(coords[index++]);
                ctrlpts[0].y = transY + (int) floor(coords[index++]);
                ctrlpts[2].x = transX + (int) floor(coords[index++]);
                ctrlpts[2].y = transY + (int) floor(coords[index++]);
                ctrlpts[1].x = (ctrlpts[0].x * 2 + ctrlpts[2].x) / 3;
                ctrlpts[1].y = (ctrlpts[0].y * 2 + ctrlpts[2].y) / 3;
                ctrlpts[0].x = (ctrlpts[0].x * 2 + x1) / 3;
                ctrlpts[0].y = (ctrlpts[0].y * 2 + y1) / 3;
                x1 = ctrlpts[2].x;
                y1 = ctrlpts[2].y;
                ::PolyBezierTo(hdc, ctrlpts, 3);
                isapoint = isapoint && (x1 == mx && y1 == my);
                isempty = FALSE;
            } else {
                ok = FALSE;
            }
            break;
        case java_awt_geom_PathIterator_SEG_CUBICTO:
            if (index + 6 <= maxcoords) {
                ctrlpts[0].x = transX + (int) floor(coords[index++]);
                ctrlpts[0].y = transY + (int) floor(coords[index++]);
                ctrlpts[1].x = transX + (int) floor(coords[index++]);
                ctrlpts[1].y = transY + (int) floor(coords[index++]);
                ctrlpts[2].x = transX + (int) floor(coords[index++]);
                ctrlpts[2].y = transY + (int) floor(coords[index++]);
                x1 = ctrlpts[2].x;
                y1 = ctrlpts[2].y;
                ::PolyBezierTo(hdc, ctrlpts, 3);
                isapoint = isapoint && (x1 == mx && y1 == my);
                isempty = FALSE;
            } else {
                ok = FALSE;
            }
            break;
        case java_awt_geom_PathIterator_SEG_CLOSE:
            ::CloseFigure(hdc);
            if (x1 != mx || y1 != my) {
                x1 = mx;
                y1 = my;
                ::MoveToEx(hdc, x1, y1, NULL);
                isempty = TRUE;
                isapoint = TRUE;
            } else if (!isfill && !isempty && isapoint) {
                ::LineTo(hdc, x1+1, y1);
                ::MoveToEx(hdc, x1, y1, NULL);
                isempty = TRUE;
                isapoint = TRUE;
            }
            break;
        }
    }
    env->ReleasePrimitiveArrayCritical(typesarray, types, JNI_ABORT);
    env->ReleasePrimitiveArrayCritical(coordsarray, coords, JNI_ABORT);
    if (ok) {
        if (!isfill && !isempty) {
            // Fix for 4298688 - draw(Line) omits last pixel
            // Windows omits the last pixel of a path when stroking.
            // Fix up the last segment of the previous subpath by
            // adding another segment after it that is only 1 pixel
            // long.  The first pixel of that segment will be drawn,
            // but the second pixel is the one that Windows omits.
            ::LineTo(hdc, x1+1, y1);
        }
        ::EndPath(hdc);
        if (isfill) {
            ::FillPath(hdc);
        } else {
            ::StrokePath(hdc);
        }
    } else {
        ::AbortPath(hdc);
        JNU_ThrowArrayIndexOutOfBoundsException(env, "coords array");
    }
    wsdo->ReleaseDC(env, wsdo, hdc);
}
예제 #12
0
/*
 * Class:     sun_java2d_windows_GDIRenderer
 * Method:    doFillOval
 * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;IIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIRenderer_doFillOval
    (JNIEnv *env, jobject wr,
     jobject sData,
     jobject clip, jobject comp, jint color,
     jint x, jint y, jint w, jint h)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doFillOval");
    J2dTraceLn5(J2D_TRACE_VERBOSE,
                "  color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d",
                color, x, y, w, h);
    if (w < 3 || h < 3) {
        // Fix for 4411814 - small ovals do not draw anything
        // (related to 4205762 on Solaris platform)
        // Most platform graphics packages have poor rendering
        // for thin ellipses and the rendering is most strikingly
        // different from our theoretical arcs.  Ideally we should
        // trap all ovals less than some fairly large size and
        // try to draw aesthetically pleasing ellipses, but that
        // would require considerably more work to get the corresponding
        // drawArc variants to match pixel for pixel.
        // Thin ovals of girth 1 pixel are simple rectangles.
        // Thin ovals of girth 2 pixels are simple rectangles with
        // potentially smaller lengths.  Determine the correct length
        // by calculating .5*.5 + scaledlen*scaledlen == 1.0 which
        // means that scaledlen is the sqrt(0.75).  Scaledlen is
        // relative to the true length (w or h) and needs to be
        // adjusted by half a pixel in different ways for odd or
        // even lengths.
#define SQRT_3_4 0.86602540378443864676
        if (w > 2 && h > 1) {
            int adjw = (int) ((SQRT_3_4 * w - ((w&1)-1)) * 0.5);
            adjw = adjw * 2 + (w&1);
            x += (w-adjw)/2;
            w = adjw;
        } else if (h > 2 && w > 1) {
            int adjh = (int) ((SQRT_3_4 * h - ((h&1)-1)) * 0.5);
            adjh = adjh * 2 + (h&1);
            y += (h-adjh)/2;
            h = adjh;
        }
#undef SQRT_3_4
        if (w > 0 && h > 0) {
            Java_sun_java2d_windows_GDIRenderer_doFillRect(env, wr, sData,
                                                           clip, comp, color,
                                                           x, y, w, h);
        }
        return;
    }

    GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData);
    if (wsdo == NULL) {
        return;
    }
    HDC hdc = wsdo->GetDC(env, wsdo, BRUSHONLY, NULL, clip, comp, color);
    if (hdc == NULL) {
        return;
    }
    ::Ellipse(hdc, x, y, x+w+1, y+h+1);
    wsdo->ReleaseDC(env, wsdo, hdc);
}
예제 #13
0
/*
 * Class:     sun_java2d_windows_GDIBlitLoops
 * Method:    nativeBlit
 * Signature: (Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;IIIIIIZ)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIBlitLoops_nativeBlit
    (JNIEnv *env, jobject joSelf,
     jobject srcData, jobject dstData,
     jobject clip,
     jint srcx, jint srcy,
     jint dstx, jint dsty,
     jint width, jint height,
     jint rmask, jint gmask, jint bmask,
     jboolean needLut)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIBlitLoops_nativeBlit");

    SurfaceDataRasInfo srcInfo;
    SurfaceDataOps *srcOps = SurfaceData_GetOps(env, srcData);
    GDIWinSDOps *dstOps = GDIWindowSurfaceData_GetOps(env, dstData);
    jint lockFlags;    
    HDC hDC = dstOps->GetDC(env, dstOps, 0, NULL, clip, NULL, 0);

    if (hDC == NULL) {
        return;
    }
    srcInfo.bounds.x1 = srcx;
    srcInfo.bounds.y1 = srcy;
    srcInfo.bounds.x2 = srcx + width;
    srcInfo.bounds.y2 = srcy + height;
    if (needLut) {
	lockFlags = (SD_LOCK_READ | SD_LOCK_LUT);
    } else {
	lockFlags = SD_LOCK_READ;
    }
    if (srcOps->Lock(env, srcOps, &srcInfo, lockFlags) != SD_SUCCESS) {
	dstOps->ReleaseDC(env, dstOps, hDC);
	return;
    }

    SurfaceDataBounds dstBounds = {dstx, dsty, dstx + width, dsty + height};
    // Intersect the source and dest rects. Note that the source blit bounds
    // will be adjusted to the surfaces's bounds if needed.
    SurfaceData_IntersectBlitBounds(&(srcInfo.bounds), &dstBounds, 
                                    dstx - srcx, dsty - srcy);

    srcx = srcInfo.bounds.x1;
    srcy = srcInfo.bounds.y1;
    dstx = dstBounds.x1;
    dsty = dstBounds.y1;
    width = srcInfo.bounds.x2 - srcInfo.bounds.x1;
    height = srcInfo.bounds.y2 - srcInfo.bounds.y1;

    if (width > 0 && height > 0)
    {
	BmiType bmi;
	// REMIND: A performance tweak here would be to make some of this 
	// data static.  For example, we could have one structure that is
	// always used for ByteGray copies and we only change dynamic data
	// in the structure with every new copy.  Also, we could store
	// structures with Ops or with the Java objects so that surfaces
	// could retain their own DIB info and we would not need to 
	// recreate it every time.

	srcOps->GetRasInfo(env, srcOps, &srcInfo);
	void *rasBase = ((char *)srcInfo.rasBase) + srcInfo.scanStride * srcy +
			srcInfo.pixelStride * srcx;

	// If scanlines are DWORD-aligned (scanStride is a multiple of 4),
	// then we can do the work much faster.  This is due to a constraint
	// in the way DIBs are structured and parsed by GDI
	jboolean fastBlt = ((srcInfo.scanStride & 0x03) == 0);

	bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
	bmi.bmiHeader.biWidth = srcInfo.scanStride/srcInfo.pixelStride;
	// fastBlt copies whole image in one call; else copy line-by-line
	bmi.bmiHeader.biHeight = (fastBlt) ? 
	    -(srcInfo.bounds.y2 - srcInfo.bounds.y1) : -1;
	bmi.bmiHeader.biPlanes = 1;
	bmi.bmiHeader.biBitCount = srcInfo.pixelStride * 8;
	// 1,3,4 byte use BI_RGB, 2 byte use BI_BITFIELD...
	// 4 byte _can_ use BI_BITFIELD, but this seems to cause a performance
	// penalty.  Since we only ever have one format (xrgb) for 32-bit
	// images that enter this function, just use BI_RGB.
	// Could do BI_RGB for 2-byte 555 format, but no perceived
	// performance benefit.
	bmi.bmiHeader.biCompression = (srcInfo.pixelStride != 2)
		? BI_RGB : BI_BITFIELDS;
	bmi.bmiHeader.biSizeImage = (bmi.bmiHeader.biWidth * 
				     bmi.bmiHeader.biHeight * 
				     srcInfo.pixelStride);
	bmi.bmiHeader.biXPelsPerMeter = 0;
	bmi.bmiHeader.biYPelsPerMeter = 0;
	bmi.bmiHeader.biClrUsed = 0;
	bmi.bmiHeader.biClrImportant = 0;
	if (srcInfo.pixelStride == 1) {
	    // Copy palette info into bitmap for 8-bit image
	    if (needLut) {
		memcpy(bmi.colors.palette, srcInfo.lutBase, srcInfo.lutSize * sizeof(RGBQUAD));
		if (srcInfo.lutSize != 256) {
		    bmi.bmiHeader.biClrUsed = srcInfo.lutSize;
		}
	    } else {
		// If no LUT needed, must be ByteGray src.  If we have not
		// yet created the byteGrayPalette, create it now and copy
		// it into our temporary bmi structure.
		// REMIND: byteGrayPalette is a leak since we do not have
		// a mechansim to free it up.  This should be fine, since it
		// is only 256 bytes for any process and only gets malloc'd
		// when using ByteGray surfaces.  Eventually, we should use
		// the new Disposer mechanism to delete this native memory.
		if (byteGrayPalette == NULL) {
		    byteGrayPalette = (RGBQUAD *)safe_Malloc(256 * sizeof(RGBQUAD));
		    for (int i = 0; i < 256; ++i) {
			byteGrayPalette[i].rgbRed = i;
			byteGrayPalette[i].rgbGreen = i;
			byteGrayPalette[i].rgbBlue = i;
		    }
		}
		memcpy(bmi.colors.palette, byteGrayPalette, 256 * sizeof(RGBQUAD));
	    }
	} else if (srcInfo.pixelStride == 2) {
	    // For 16-bit case, init the masks for the pixel depth
	    bmi.colors.dwMasks[0] = rmask;
	    bmi.colors.dwMasks[1] = gmask;
	    bmi.colors.dwMasks[2] = bmask;
	} 
	if (fastBlt) {
	    // Window could go away at any time, leaving bits on the screen
	    // from this GDI call, so make sure window still exists
	    if (::IsWindowVisible(dstOps->window)) {
		// Could also call StretchDIBits.  Testing showed slight
		// performance advantage of SetDIBits instead, so since we
		// have no need of scaling, might as well use SetDIBits.
		SetDIBitsToDevice(hDC, dstx, dsty, width, height, 
		    0, 0, 0, height, rasBase, 
		    (BITMAPINFO*)&bmi, DIB_RGB_COLORS);
	    }
	} else {
	    // Source scanlines not DWORD-aligned - copy each scanline individually
	    for (int i = 0; i < height; i += 1) {
		if (::IsWindowVisible(dstOps->window)) {
		    SetDIBitsToDevice(hDC, dstx, dsty+i, width, 1, 
			0, 0, 0, 1, rasBase, 
			(BITMAPINFO*)&bmi, DIB_RGB_COLORS);
		    rasBase = (void*)((char*)rasBase + srcInfo.scanStride);
		} else {
		    break;
		}
	    }
	}	
	SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
    }
    SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
    dstOps->ReleaseDC(env, dstOps, hDC);

    return;
}