alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (GDIRenderer.cpp)

This example Java source code file (GDIRenderer.cpp) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

bool, false, gdiwindowsurfacedata_getops, gdiwinsdops, hdc, j2dtraceln, j2dtraceln5, jni_abort, jnicall, jnienv, jniexport, null, patblt, true

The GDIRenderer.cpp Java example source code

/*
 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include "awt.h"
#include "sun_java2d_windows_GDIRenderer.h"
#include "java_awt_geom_PathIterator.h"

#include "GDIWindowSurfaceData.h"
#include "awt_Component.h"
#include "awt_Pen.h"
#include "awt_Brush.h"

#include "GraphicsPrimitiveMgr.h"

#include <math.h>                /* for cos(), sin(), etc */

#define MAX_CLAMP_BND (1<<26)
#define MIN_CLAMP_BND (-MAX_CLAMP_BND)

#define CLAMP(x) (((x) > MAX_CLAMP_BND) ?   \
    MAX_CLAMP_BND : ((x) < MIN_CLAMP_BND) ? \
        MIN_CLAMP_BND : (x))


extern "C" {

#define POLYTEMPSIZE    (512 / sizeof(POINT))

static void AngleToCoord(jint angle, jint w, jint h, jint *x, jint *y)
{
    const double pi = 3.1415926535;
    const double toRadians = 2 * pi / 360;

    *x = (long)(cos((double)angle * toRadians) * w);
    *y = -(long)(sin((double)angle * toRadians) * h);
}

static POINT *TransformPoly(jint *xpoints, jint *ypoints,
                            jint transx, jint transy,
                            POINT *pPoints, jint *pNpoints,
                            BOOL close, BOOL fixend)
{
    int npoints = *pNpoints;
    int outpoints = npoints;
    jint x, y;

    // Fix for 4298688 - draw(Line) and Polygon omit last pixel
    // We will need to add a point if we need to close it off or
    // if we need to fix the endpoint to accommodate the Windows
    // habit of never drawing the last pixel of a Polyline.  Note
    // that if the polyline is already closed then neither fix
    // is needed because the last pixel is also the first pixel
    // and so will be drawn just fine.
    // Clarification for 4298688 - regression bug 4678208 points
    // out that we still need to fix the endpoint if the closed
    // polygon never went anywhere (all vertices on same coordinate).
    jint mx = xpoints[0];
    jint my = ypoints[0];
    BOOL isclosed = (xpoints[npoints-1] == mx && ypoints[npoints-1] == my);
    if ((close && !isclosed) || fixend) {
        outpoints++;
        *pNpoints = outpoints;
    }
    if (outpoints > POLYTEMPSIZE) {
        pPoints = (POINT *) SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, sizeof(POINT), outpoints);
    }
    BOOL isempty = fixend;
    for (int i = 0; i < npoints; i++) {
        x = xpoints[i];
        y = ypoints[i];
        isempty = isempty && (x == mx && y == my);
        pPoints[i].x = CLAMP(x + transx);
        pPoints[i].y = CLAMP(y + transy);
    }
    if (close && !isclosed) {
        pPoints[npoints] = pPoints[0];
    } else if (fixend) {
        if (!close || isempty) {
            // Fix for 4298688 - draw(Line) and Polygon omit last pixel
            // Fix up the last segment 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.
            pPoints[npoints] = pPoints[npoints-1];
            pPoints[npoints].x++;
        } else {
            outpoints--;
            *pNpoints = outpoints;
        }
    }

    return pPoints;
}

/*
 * 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);
}

/*
 * 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);
}

/*
 * 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);
}

/*
 * 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);
}

/*
 * 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);
}

/*
 * Class:     sun_java2d_windows_GDIRenderer
 * Method:    doDrawPoly
 * Signature: (Lsun/java2d/windows/GDIWindowSurfaceData;Lsun/java2d/pipe/Region;Ljava/awt/Composite;III[I[IIZ)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIRenderer_doDrawPoly
    (JNIEnv *env, jobject wr,
     jobject sData,
     jobject clip, jobject comp, jint color,
     jint transx, jint transy,
     jintArray xpointsarray, jintArray ypointsarray,
     jint npoints, jboolean isclosed)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doDrawPoly");
    J2dTraceLn5(J2D_TRACE_VERBOSE,
                "  color=0x%x transx=%-4d transy=%-4d "\
                "npoints=%-4d isclosed=%-4d",
                color, transx, transy, npoints, isclosed);
    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 < 2) {
        // Fix for 4067534 - assertion failure in 1.3.1 for degenerate polys
        // Not enough points for a line.
        // 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, isclosed, TRUE);
    env->ReleasePrimitiveArrayCritical(xpointsarray, xpoints, JNI_ABORT);
    env->ReleasePrimitiveArrayCritical(ypointsarray, ypoints, JNI_ABORT);
    if (pPoints == NULL) {
        return;
    }

    HDC hdc = wsdo->GetDC(env, wsdo, PEN, NULL, clip, comp, color);
    if (hdc == NULL) {
        return;
    }
    ::Polyline(hdc, pPoints, npoints);
    wsdo->ReleaseDC(env, wsdo, hdc);
    if (pPoints != tmpPts) {
        free(pPoints);
    }
}

/*
 * 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);
}

/*
 * 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);
}

/*
 * 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);
}

/*
 * 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);
}

/*
 * 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);
    }
}

/*
 * 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);
}

} /* extern "C" */

INLINE BOOL RectInMonitorRect(RECT *rCheck, RECT *rContainer)
{
    // Assumption: left <= right, top <= bottom
    if (rCheck->left >= rContainer->left &&
        rCheck->right <= rContainer->right &&
        rCheck->top >= rContainer->top &&
        rCheck->bottom <= rContainer->bottom)
    {
        return TRUE;
    } else {
        return FALSE;
    }
}

/*
 * 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);
}

Other Java examples (source code examples)

Here is a short list of links related to this Java GDIRenderer.cpp source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.