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

Java example source code file (DrawParallelogram.c)

This example Java source code file (DrawParallelogram.c) 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

deltax1, deltax2, edgeinfo, handle_pgram_edge, null, slope1, slope2, store_edge, store_pgram

The DrawParallelogram.c Java example source code

/*
 * Copyright (c) 2008, 2010, 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 "math.h"
#include "GraphicsPrimitiveMgr.h"
#include "LineUtils.h"
#include "Trace.h"
#include "ParallelogramUtils.h"

#include "sun_java2d_loops_DrawParallelogram.h"

#define HANDLE_PGRAM_EDGE(X1, Y1, X2, Y2, \
                          pRasInfo, pixel, pPrim, pFunc, pCompInfo) \
    do { \
         jint ix1 = (jint) floor(X1); \
         jint ix2 = (jint) floor(X2); \
         jint iy1 = (jint) floor(Y1); \
         jint iy2 = (jint) floor(Y2); \
         LineUtils_ProcessLine(pRasInfo, pixel, \
                               pFunc, pPrim, pCompInfo, \
                               ix1, iy1, ix2, iy2, JNI_TRUE); \
    } while (0)

typedef struct {
    jdouble x0;
    jdouble y0;
    jdouble y1;
    jdouble slope;
    jlong dx;
    jint ystart;
    jint yend;
} EdgeInfo;

#define STORE_EDGE(pEDGE, X0, Y0, Y1, SLOPE, DELTAX) \
    do { \
        (pEDGE)->x0 = (X0); \
        (pEDGE)->y0 = (Y0); \
        (pEDGE)->y1 = (Y1); \
        (pEDGE)->slope = (SLOPE); \
        (pEDGE)->dx = (DELTAX); \
        (pEDGE)->ystart = (jint) floor((Y0) + 0.5); \
        (pEDGE)->yend   = (jint) floor((Y1) + 0.5); \
    } while (0)

#define STORE_PGRAM(pLTEDGE, pRTEDGE, \
                    X0, Y0, dX1, dY1, dX2, dY2, \
                    SLOPE1, SLOPE2, DELTAX1, DELTAX2) \
    do { \
        STORE_EDGE((pLTEDGE)+0, \
                   (X0), (Y0), (Y0) + (dY1), \
                   (SLOPE1), (DELTAX1)); \
        STORE_EDGE((pRTEDGE)+0, \
                   (X0), (Y0), (Y0) + (dY2), \
                   (SLOPE2), (DELTAX2)); \
        STORE_EDGE((pLTEDGE)+1, \
                   (X0) + (dX1), (Y0) + (dY1), (Y0) + (dY1) + (dY2), \
                   (SLOPE2), (DELTAX2)); \
        STORE_EDGE((pRTEDGE)+1, \
                   (X0) + (dX2), (Y0) + (dY2), (Y0) + (dY1) + (dY2), \
                   (SLOPE1), (DELTAX1)); \
    } while (0)

/*
 * Class:     sun_java2d_loops_DrawParallelogram
 * Method:    DrawParallelogram
 * Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;DDDDDDDD)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_loops_DrawParallelogram_DrawParallelogram
    (JNIEnv *env, jobject self,
     jobject sg2d, jobject sData,
     jdouble x0, jdouble y0,
     jdouble dx1, jdouble dy1,
     jdouble dx2, jdouble dy2,
     jdouble lw1, jdouble lw2)
{
    SurfaceDataOps *sdOps;
    SurfaceDataRasInfo rasInfo;
    NativePrimitive *pPrim;
    CompositeInfo compInfo;
    jint pixel;
    EdgeInfo edges[8];
    EdgeInfo *active[4];
    jint ix1, iy1, ix2, iy2;
    jdouble ldx1, ldy1, ldx2, ldy2;
    jdouble ox0, oy0;

    /*
     * Sort parallelogram by y values, ensure that each delta vector
     * has a non-negative y delta.
     */
    SORT_PGRAM(x0, y0, dx1, dy1, dx2, dy2,
               v = lw1; lw1 = lw2; lw2 = v;);

    // dx,dy for line width in the "1" and "2" directions.
    ldx1 = dx1 * lw1;
    ldy1 = dy1 * lw1;
    ldx2 = dx2 * lw2;
    ldy2 = dy2 * lw2;

    // calculate origin of the outer parallelogram
    ox0 = x0 - (ldx1 + ldx2) / 2.0;
    oy0 = y0 - (ldy1 + ldy2) / 2.0;

    PGRAM_MIN_MAX(ix1, ix2, ox0, dx1+ldx1, dx2+ldx2, JNI_FALSE);
    iy1 = (jint) floor(oy0 + 0.5);
    iy2 = (jint) floor(oy0 + dy1 + ldy1 + dy2 + ldy2 + 0.5);

    pPrim = GetNativePrim(env, self);
    if (pPrim == NULL) {
        return;
    }
    pixel = GrPrim_Sg2dGetPixel(env, sg2d);
    if (pPrim->pCompType->getCompInfo != NULL) {
        GrPrim_Sg2dGetCompInfo(env, sg2d, pPrim, &compInfo);
    }

    sdOps = SurfaceData_GetOps(env, sData);
    if (sdOps == NULL) {
        return;
    }

    GrPrim_Sg2dGetClip(env, sg2d, &rasInfo.bounds);
    SurfaceData_IntersectBoundsXYXY(&rasInfo.bounds, ix1, iy1, ix2, iy2);
    if (rasInfo.bounds.y2 <= rasInfo.bounds.y1 ||
        rasInfo.bounds.x2 <= rasInfo.bounds.x1)
    {
        return;
    }

    if (sdOps->Lock(env, sdOps, &rasInfo, pPrim->dstflags) != SD_SUCCESS) {
        return;
    }

    ix1 = rasInfo.bounds.x1;
    iy1 = rasInfo.bounds.y1;
    ix2 = rasInfo.bounds.x2;
    iy2 = rasInfo.bounds.y2;
    if (ix2 > ix1 && iy2 > iy1) {
        sdOps->GetRasInfo(env, sdOps, &rasInfo);
        if (rasInfo.rasBase) {
            jdouble lslope, rslope;
            jlong ldx, rdx;
            jint loy, hiy, numedges;
            FillParallelogramFunc *pFill =
                pPrim->funcs.drawparallelogram->fillpgram;

            lslope = (dy1 == 0) ? 0 : dx1 / dy1;
            rslope = (dy2 == 0) ? 0 : dx2 / dy2;
            ldx = DblToLong(lslope);
            rdx = DblToLong(rslope);

            // Only need to generate 4 quads if the interior still
            // has a hole in it (i.e. if the line width ratios were
            // both less than 1.0)
            if (lw1 < 1.0 && lw2 < 1.0) {
                // If the line widths are both less than a pixel wide
                // then we can use a drawline function instead for even
                // more performance.
                lw1 = sqrt(ldx1*ldx1 + ldy1*ldy1);
                lw2 = sqrt(ldx2*ldx2 + ldy2*ldy2);
                if (lw1 <= 1.0001 && lw2 <= 1.0001) {
                    jdouble x3, y3;
                    DrawLineFunc *pLine =
                        pPrim->funcs.drawparallelogram->drawline;

                    x3 = (dx1 += x0);
                    y3 = (dy1 += y0);
                    x3 += dx2;
                    y3 += dy2;
                    dx2 += x0;
                    dy2 += y0;

                    HANDLE_PGRAM_EDGE( x0,  y0, dx1, dy1,
                                      &rasInfo, pixel, pPrim, pLine, &compInfo);
                    HANDLE_PGRAM_EDGE(dx1, dy1,  x3,  y3,
                                      &rasInfo, pixel, pPrim, pLine, &compInfo);
                    HANDLE_PGRAM_EDGE( x3,  y3, dx2, dy2,
                                      &rasInfo, pixel, pPrim, pLine, &compInfo);
                    HANDLE_PGRAM_EDGE(dx2, dy2,  x0,  y0,
                                      &rasInfo, pixel, pPrim, pLine, &compInfo);
                    SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
                    SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
                    return;
                }

                // To simplify the edge management below we presort the
                // inner and outer edges so that they are globally sorted
                // from left to right.  If you scan across the array of
                // edges for a given Y range then the edges you encounter
                // will be sorted in X as well.
                // If AB are left top and bottom edges of outer parallelogram,
                // and CD are the right pair of edges, and abcd are the
                // corresponding inner parallelogram edges then we want them
                // sorted as ABabcdCD to ensure this horizontal ordering.
                // Conceptually it is like 2 pairs of nested parentheses.
                STORE_PGRAM(edges + 2, edges + 4,
                            ox0 + ldx1 + ldx2, oy0 + ldy1 + ldy2,
                            dx1 - ldx1, dy1 - ldy1,
                            dx2 - ldx2, dy2 - ldy2,
                            lslope, rslope, ldx, rdx);
                numedges = 8;
            } else {
                // The line width ratios were large enough to consume
                // the entire hole in the middle of the parallelogram
                // so we can just issue one large quad for the outer
                // parallelogram.
                numedges = 4;
            }

            // The outer parallelogram always goes in the first two
            // and last two entries in the array so we either have
            // ABabcdCD ordering for 8 edges or ABCD ordering for 4
            // edges.  See comment above where we store the inner
            // parallelogram for a more complete description.
            STORE_PGRAM(edges + 0, edges + numedges-2,
                        ox0, oy0,
                        dx1 + ldx1, dy1 + ldy1,
                        dx2 + ldx2, dy2 + ldy2,
                        lslope, rslope, ldx, rdx);

            loy = edges[0].ystart;
            if (loy < iy1) loy = iy1;
            while (loy < iy2) {
                jint numactive = 0;
                jint cur;

                hiy = iy2;
                // Maintaining a sorted edge list is probably overkill for
                // 4 or 8 edges.  The indices chosen above for storing the
                // inner and outer left and right edges already guarantee
                // left to right ordering so we just need to scan for edges
                // that overlap the current Y range (and also determine the
                // maximum Y value for which the range is valid).
                for (cur = 0; cur < numedges; cur++) {
                    EdgeInfo *pEdge = &edges[cur];
                    jint yend = pEdge->yend;
                    if (loy < yend) {
                        // This edge is still in play, have we reached it yet?
                        jint ystart = pEdge->ystart;
                        if (loy < ystart) {
                            // This edge is not active (yet)
                            // Stop before we get to the top of it
                            if (hiy > ystart) hiy = ystart;
                        } else {
                            // This edge is active, store it
                            active[numactive++] = pEdge;
                            // And stop when we get to the bottom of it
                            if (hiy > yend) hiy = yend;
                        }
                    }
                }
#ifdef DEBUG
                if ((numactive & 1) != 0) {
                    J2dTraceLn1(J2D_TRACE_ERROR,
                                "DrawParallelogram: "
                                "ODD NUMBER OF PGRAM EDGES (%d)!!",
                                numactive);
                }
#endif
                for (cur = 0; cur < numactive; cur += 2) {
                    EdgeInfo *pLeft  = active[cur+0];
                    EdgeInfo *pRight = active[cur+1];
                    jlong lx = PGRAM_INIT_X(loy,
                                            pLeft->x0, pLeft->y0,
                                            pLeft->slope);
                    jlong rx = PGRAM_INIT_X(loy,
                                            pRight->x0, pRight->y0,
                                            pRight->slope);
                    (*pFill)(&rasInfo,
                             ix1, loy, ix2, hiy,
                             lx, pLeft->dx,
                             rx, pRight->dx,
                             pixel, pPrim, &compInfo);
                }
                loy = hiy;
            }
        }
        SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
    }
    SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
}

Other Java examples (source code examples)

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

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

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2024 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.