0N/A/*
3909N/A * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
3265N/A#include <math.h>
3265N/A#include <stdlib.h>
3265N/A#include <string.h>
0N/A#include "GraphicsPrimitiveMgr.h"
3265N/A#include "ParallelogramUtils.h"
0N/A
0N/A#include "sun_java2d_loops_MaskFill.h"
0N/A
0N/A/*
0N/A * Class: sun_java2d_loops_MaskFill
0N/A * Method: MaskFill
0N/A * Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;Ljava/awt/Composite;IIII[BII)V
0N/A */
0N/AJNIEXPORT void JNICALL
0N/AJava_sun_java2d_loops_MaskFill_MaskFill
0N/A (JNIEnv *env, jobject self,
0N/A jobject sg2d, jobject sData, jobject comp,
0N/A jint x, jint y, jint w, jint h,
0N/A jbyteArray maskArray, jint maskoff, jint maskscan)
0N/A{
0N/A SurfaceDataOps *sdOps;
0N/A SurfaceDataRasInfo rasInfo;
0N/A NativePrimitive *pPrim;
0N/A CompositeInfo compInfo;
0N/A
0N/A pPrim = GetNativePrim(env, self);
0N/A if (pPrim == NULL) {
0N/A return;
0N/A }
0N/A if (pPrim->pCompType->getCompInfo != NULL) {
0N/A (*pPrim->pCompType->getCompInfo)(env, &compInfo, comp);
0N/A }
0N/A
0N/A sdOps = SurfaceData_GetOps(env, sData);
0N/A if (sdOps == 0) {
0N/A return;
0N/A }
0N/A
0N/A rasInfo.bounds.x1 = x;
0N/A rasInfo.bounds.y1 = y;
0N/A rasInfo.bounds.x2 = x + w;
0N/A rasInfo.bounds.y2 = y + h;
0N/A if (sdOps->Lock(env, sdOps, &rasInfo, pPrim->dstflags) != SD_SUCCESS) {
0N/A return;
0N/A }
0N/A
0N/A if (rasInfo.bounds.x2 > rasInfo.bounds.x1 &&
0N/A rasInfo.bounds.y2 > rasInfo.bounds.y1)
0N/A {
0N/A jint color = GrPrim_Sg2dGetEaRGB(env, sg2d);
0N/A sdOps->GetRasInfo(env, sdOps, &rasInfo);
0N/A if (rasInfo.rasBase) {
0N/A jint width = rasInfo.bounds.x2 - rasInfo.bounds.x1;
0N/A jint height = rasInfo.bounds.y2 - rasInfo.bounds.y1;
0N/A void *pDst = PtrCoord(rasInfo.rasBase,
0N/A rasInfo.bounds.x1, rasInfo.pixelStride,
0N/A rasInfo.bounds.y1, rasInfo.scanStride);
0N/A unsigned char *pMask =
0N/A (maskArray
0N/A ? (*env)->GetPrimitiveArrayCritical(env, maskArray, 0)
0N/A : 0);
0N/A maskoff += ((rasInfo.bounds.y1 - y) * maskscan +
0N/A (rasInfo.bounds.x1 - x));
0N/A (*pPrim->funcs.maskfill)(pDst,
0N/A pMask, maskoff, maskscan,
0N/A width, height,
0N/A color, &rasInfo,
0N/A pPrim, &compInfo);
0N/A if (pMask) {
0N/A (*env)->ReleasePrimitiveArrayCritical(env, maskArray,
0N/A pMask, JNI_ABORT);
0N/A }
0N/A }
0N/A SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
3265N/A }
3265N/A SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
3265N/A}
3265N/A
3265N/A#define MASK_BUF_LEN 1024
3265N/A
3265N/A#define DblToMask(v) ((unsigned char) ((v)*255.9999))
3265N/A
3265N/A/* Fills an aligned rectangle with potentially translucent edges. */
3265N/Astatic void
3265N/AfillAARect(NativePrimitive *pPrim, SurfaceDataRasInfo *pRasInfo,
3265N/A CompositeInfo *pCompInfo, jint color, unsigned char *pMask,
3265N/A void *pDst,
3265N/A jdouble x1, jdouble y1, jdouble x2, jdouble y2)
3265N/A{
3265N/A jint cx1 = pRasInfo->bounds.x1;
3265N/A jint cy1 = pRasInfo->bounds.y1;
3265N/A jint cx2 = pRasInfo->bounds.x2;
3265N/A jint cy2 = pRasInfo->bounds.y2;
3265N/A jint rx1 = (jint) ceil(x1);
3265N/A jint ry1 = (jint) ceil(y1);
3265N/A jint rx2 = (jint) floor(x2);
3265N/A jint ry2 = (jint) floor(y2);
3265N/A jint width = cx2 - cx1;
3265N/A jint scan = pRasInfo->scanStride;
3265N/A /* Convert xy12 into the edge coverage fractions for those edges. */
3265N/A x1 = rx1-x1;
3265N/A y1 = ry1-y1;
3265N/A x2 = x2-rx2;
3265N/A y2 = y2-ry2;
3265N/A if (ry2 < ry1) {
3265N/A /* Accumulate bottom coverage into top coverage. */
3265N/A y1 = y1 + y2 - 1.0;
3265N/A /* prevent processing of "bottom fractional row" */
3265N/A ry2 = cy2;
3265N/A }
3265N/A if (rx2 < rx1) {
3265N/A /* Accumulate right coverage into left coverage. */
3265N/A x1 = x1 + x2 - 1.0;
3265N/A /* prevent processing of "right fractional column" */
3265N/A rx2 = cx2;
3265N/A }
3265N/A /* Check for a visible "top fractional row" and process it */
3265N/A if (cy1 < ry1) {
3265N/A unsigned char midcov = DblToMask(y1);
3265N/A jint x;
3265N/A for (x = 0; x < width; x++) {
3265N/A pMask[x] = midcov;
3265N/A }
3265N/A if (cx1 < rx1) {
3265N/A pMask[0] = DblToMask(y1 * x1);
3265N/A }
3265N/A if (cx2 > rx2) {
3265N/A pMask[width-1] = DblToMask(y1 * x2);
3265N/A }
3265N/A (*pPrim->funcs.maskfill)(pDst,
3265N/A pMask, 0, 0,
3265N/A width, 1,
3265N/A color, pRasInfo,
3265N/A pPrim, pCompInfo);
3265N/A pDst = PtrAddBytes(pDst, scan);
3265N/A cy1++;
3265N/A }
3265N/A /* Check for a visible "left fract, solid middle, right fract" section. */
3265N/A if (cy1 < ry2 && cy1 < cy2) {
3265N/A jint midh = ((ry2 < cy2) ? ry2 : cy2) - cy1;
3265N/A jint midx = cx1;
3265N/A void *pMid = pDst;
3265N/A /* First process the left "fractional column" if it is visible. */
3265N/A if (midx < rx1) {
3265N/A pMask[0] = DblToMask(x1);
3265N/A /* Note: maskscan == 0 means we reuse this value for every row. */
3265N/A (*pPrim->funcs.maskfill)(pMid,
3265N/A pMask, 0, 0,
3265N/A 1, midh,
3265N/A color, pRasInfo,
3265N/A pPrim, pCompInfo);
3265N/A pMid = PtrAddBytes(pMid, pRasInfo->pixelStride);
3265N/A midx++;
3265N/A }
3265N/A /* Process the central solid section if it is visible. */
3265N/A if (midx < rx2 && midx < cx2) {
3265N/A jint midw = ((rx2 < cx2) ? rx2 : cx2) - midx;
3265N/A /* A NULL mask buffer means "all coverages are 0xff" */
3265N/A (*pPrim->funcs.maskfill)(pMid,
3265N/A NULL, 0, 0,
3265N/A midw, midh,
3265N/A color, pRasInfo,
3265N/A pPrim, pCompInfo);
3265N/A pMid = PtrCoord(pMid, midw, pRasInfo->pixelStride, 0, 0);
3265N/A midx += midw;
3265N/A }
3265N/A /* Finally process the right "fractional column" if it is visible. */
3265N/A if (midx < cx2) {
3265N/A pMask[0] = DblToMask(x2);
3265N/A /* Note: maskscan == 0 means we reuse this value for every row. */
3265N/A (*pPrim->funcs.maskfill)(pMid,
3265N/A pMask, 0, 0,
3265N/A 1, midh,
3265N/A color, pRasInfo,
3265N/A pPrim, pCompInfo);
3265N/A }
3265N/A cy1 += midh;
3265N/A pDst = PtrCoord(pDst, 0, 0, midh, scan);
3265N/A }
3265N/A /* Check for a visible "bottom fractional row" and process it */
3265N/A if (cy1 < cy2) {
3265N/A unsigned char midcov = DblToMask(y2);
3265N/A jint x;
3265N/A for (x = 0; x < width; x++) {
3265N/A pMask[x] = midcov;
3265N/A }
3265N/A if (cx1 < rx1) {
3265N/A pMask[0] = DblToMask(y2 * x1);
3265N/A }
3265N/A if (cx2 > rx2) {
3265N/A pMask[width-1] = DblToMask(y2 * x2);
3265N/A }
3265N/A (*pPrim->funcs.maskfill)(pDst,
3265N/A pMask, 0, 0,
3265N/A width, 1,
3265N/A color, pRasInfo,
3265N/A pPrim, pCompInfo);
3265N/A }
3265N/A}
3265N/A
3265N/A/*
3265N/A * Support code for arbitrary tracing and MaskFill filling of
3265N/A * non-rectilinear (diagonal) parallelograms.
3265N/A *
3265N/A * This code is based upon the following model of AA coverage.
3265N/A *
3265N/A * Each edge of a parallelogram (for fillPgram) or a double
3265N/A * parallelogram (inner and outer parallelograms for drawPgram)
3265N/A * can be rasterized independently because the geometry is well
3265N/A * defined in such a way that none of the sides will ever cross
3265N/A * each other and they have a fixed ordering that is fairly
3265N/A * well predetermined.
3265N/A *
3265N/A * So, for each edge we will look at the diagonal line that
3265N/A * the edge makes as it passes through a row of pixels. Some
3265N/A * such diagonal lines may pass entirely through the row of
3265N/A * pixels in a single pixel column. Some may cut across the
3265N/A * row and pass through several pixel columns before they pass
3265N/A * on to the next row.
3265N/A *
3265N/A * As the edge passes through the row of pixels it will affect
3265N/A * the coverage of the pixels it passes through as well as all
3265N/A * of the pixels to the right of the edge. The coverage will
3265N/A * either be increased (by a left edge of a parallelogram) or
3265N/A * decreased (by a right edge) for all pixels to the right, until
3265N/A * another edge passing the opposite direction is encountered.
3265N/A *
3265N/A * The coverage added or subtracted by an edge as it crosses a
3265N/A * given pixel is calculated using a trapezoid formula in the
3265N/A * following manner:
3265N/A *
3265N/A * /
3265N/A * +-----+---/-+-----+
3265N/A * | | / | |
3265N/A * | | / | |
3265N/A * +-----+/----+-----+
3265N/A * /
3265N/A *
3265N/A * The area to the right of that edge for the pixel where it
3265N/A * crosses is given as:
3265N/A *
3265N/A * trapheight * (topedge + bottomedge)/2
3265N/A *
3265N/A * Another thing to note is that the above formula gives the
3265N/A * contribution of that edge to the given pixel where it crossed,
3265N/A * but in so crossing the pixel row, it also created 100% coverage
3265N/A * for all of the pixels to the right.
3265N/A *
3265N/A * This example was simplified in that the edge depicted crossed
3265N/A * the complete pixel row and it did so entirely within the bounds
3265N/A * of a single pixel column. In practice, many edges may start or
3265N/A * end in a given row and thus provide only partial row coverage
3265N/A * (i.e. the total "trapheight" in the formula never reaches 1.0).
3265N/A * And in other cases, edges may travel sideways through several
3265N/A * pixel columns on a given pixel row from where they enter it to
3265N/A * where the leave it (which also mans that the trapheight for a
3265N/A * given pixel will be less than 1.0, but by the time the edge
3265N/A * completes its journey through the pixel row the "coverage shadow"
3265N/A * that it casts on all pixels to the right eventually reaches 100%).
3265N/A *
3265N/A * In order to simplify the calculations so that we don't have to
3265N/A * keep propagating coverages we calculate for one edge "until we
3265N/A * reach another edge" we will process one edge at a time and
3265N/A * simply record in a buffer the amount that an edge added to
3265N/A * or subtracted from the coverage for a given pixel and its
3265N/A * following right-side neighbors. Thus, the true total coverage
3265N/A * of a given pixel is only determined by summing the deltas for
3265N/A * that pixel and all of the pixels to its left. Since we already
3265N/A * have to scan the buffer to change floating point coverages into
3265N/A * mask values for a MaskFill loop, it is simple enough to sum the
3265N/A * values as we perform that scan from left to right.
3265N/A *
3265N/A * In the above example, note that 2 deltas need to be recorded even
3265N/A * though the edge only intersected a single pixel. The delta recorded
3265N/A * for the pixel where the edge crossed will be approximately 55%
3265N/A * (guesstimating by examining the poor ascii art) which is fine for
3265N/A * determining how to render that pixel, but the rest of the pixels
3265N/A * to its right should have their coverage modified by a full 100%
3265N/A * and the 55% delta value we recorded for the pixel that the edge
3265N/A * crossed will not get them there. We adjust for this by adding
3265N/A * the "remainder" of the coverage implied by the shadow to the
3265N/A * pixel immediately to the right of where we record a trapezoidal
3265N/A * contribution. In this case a delta of 45% will be recorded in
3265N/A * the pixel immediately to the right to raise the total to 100%.
3265N/A *
3265N/A * As we sum these delta values as we process the line from left
3265N/A * to right, these delta values will typically drive the sum from
3265N/A * 0% up to 100% and back down to 0% over the course of a single
3265N/A * pixel row. In the case of a drawn (double) parallelogram the
3265N/A * sum will go to 100% and back to 0% twice on most scanlines.
3265N/A *
3265N/A * The fillAAPgram and drawAAPgram functions drive the main flow
3265N/A * of the algorithm with help from the following structures,
3265N/A * macros, and functions. It is probably best to start with
3265N/A * those 2 functions to gain an understanding of the algorithm.
3265N/A */
3265N/Atypedef struct {
3265N/A jdouble x;
3265N/A jdouble y;
3265N/A jdouble xbot;
3265N/A jdouble ybot;
3265N/A jdouble xnexty;
3265N/A jdouble ynextx;
3265N/A jdouble xnextx;
3265N/A jdouble linedx;
3265N/A jdouble celldx;
3265N/A jdouble celldy;
3265N/A jboolean isTrailing;
3265N/A} EdgeInfo;
3265N/A
3265N/A#define MIN_DELTA (1.0/256.0)
3265N/A
3265N/A/*
3265N/A * Calculates slopes and deltas for an edge and stores results in an EdgeInfo.
3265N/A * Returns true if the edge was valid (i.e. not ignored for some reason).
3265N/A */
3265N/Astatic jboolean
3265N/AstoreEdge(EdgeInfo *pEdge,
3265N/A jdouble x, jdouble y, jdouble dx, jdouble dy,
3265N/A jint cx1, jint cy1, jint cx2, jint cy2,
3265N/A jboolean isTrailing)
3265N/A{
3265N/A jdouble xbot = x + dx;
3265N/A jdouble ybot = y + dy;
3265N/A jboolean ret;
3265N/A
3265N/A pEdge->x = x;
3265N/A pEdge->y = y;
3265N/A pEdge->xbot = xbot;
3265N/A pEdge->ybot = ybot;
3265N/A
3265N/A /* Note that parallelograms are sorted so dy is always non-negative */
3265N/A if (dy > MIN_DELTA && /* NaN and horizontal protection */
3265N/A ybot > cy1 && /* NaN and "OUT_ABOVE" protection */
3265N/A y < cy2 && /* NaN and "OUT_BELOW" protection */
3265N/A xbot == xbot && /* NaN protection */
3265N/A (x < cx2 || xbot < cx2)) /* "OUT_RIGHT" protection */
3265N/A /* Note: "OUT_LEFT" segments may still contribute coverage... */
3265N/A {
3265N/A /* no NaNs, dy is not horizontal, and segment contributes to clip */
3265N/A if (dx < -MIN_DELTA || dx > MIN_DELTA) {
3265N/A /* dx is not vertical */
3265N/A jdouble linedx;
3265N/A jdouble celldy;
3265N/A jdouble nextx;
3265N/A
3265N/A linedx = dx / dy;
3265N/A celldy = dy / dx;
3265N/A if (y < cy1) {
3265N/A pEdge->x = x = x + (cy1 - y) * linedx;
3265N/A pEdge->y = y = cy1;
3265N/A }
3265N/A pEdge->linedx = linedx;
3265N/A if (dx < 0) {
3265N/A pEdge->celldx = -1.0;
3265N/A pEdge->celldy = -celldy;
3265N/A pEdge->xnextx = nextx = ceil(x) - 1.0;
3265N/A } else {
3265N/A pEdge->celldx = +1.0;
3265N/A pEdge->celldy = celldy;
3265N/A pEdge->xnextx = nextx = floor(x) + 1.0;
3265N/A }
3265N/A pEdge->ynextx = y + (nextx - x) * celldy;
3265N/A pEdge->xnexty = x + ((floor(y) + 1) - y) * linedx;
3265N/A } else {
3265N/A /* dx is essentially vertical */
3265N/A if (y < cy1) {
3265N/A pEdge->y = y = cy1;
3265N/A }
3265N/A pEdge->xbot = x;
3265N/A pEdge->linedx = 0.0;
3265N/A pEdge->celldx = 0.0;
3265N/A pEdge->celldy = 1.0;
3265N/A pEdge->xnextx = x;
3265N/A pEdge->xnexty = x;
3265N/A pEdge->ynextx = ybot;
3265N/A }
3265N/A ret = JNI_TRUE;
3265N/A } else {
3265N/A /* There is some reason to ignore this segment, "celldy=0" omits it */
3265N/A pEdge->ybot = y;
3265N/A pEdge->linedx = dx;
3265N/A pEdge->celldx = dx;
3265N/A pEdge->celldy = 0.0;
3265N/A pEdge->xnextx = xbot;
3265N/A pEdge->xnexty = xbot;
3265N/A pEdge->ynextx = y;
3265N/A ret = JNI_FALSE;
3265N/A }
3265N/A pEdge->isTrailing = isTrailing;
3265N/A return ret;
3265N/A}
3265N/A
3265N/A/*
3265N/A * Calculates and stores slopes and deltas for all edges of a parallelogram.
3265N/A * Returns true if at least 1 edge was valid (i.e. not ignored for some reason).
3265N/A *
3265N/A * The inverted flag is true for an outer parallelogram (left and right
3265N/A * edges are leading and trailing) and false for an inner parallelogram
3265N/A * (where the left edge is trailing and the right edge is leading).
3265N/A */
3265N/Astatic jboolean
3265N/AstorePgram(EdgeInfo *pLeftEdge, EdgeInfo *pRightEdge,
3265N/A jdouble x, jdouble y,
3265N/A jdouble dx1, jdouble dy1,
3265N/A jdouble dx2, jdouble dy2,
3265N/A jint cx1, jint cy1, jint cx2, jint cy2,
3265N/A jboolean inverted)
3265N/A{
3265N/A jboolean ret = JNI_FALSE;
3265N/A ret = (storeEdge(pLeftEdge + 0,
3265N/A x , y , dx1, dy1,
3265N/A cx1, cy1, cx2, cy2, inverted) || ret);
3265N/A ret = (storeEdge(pLeftEdge + 1,
3265N/A x+dx1, y+dy1, dx2, dy2,
3265N/A cx1, cy1, cx2, cy2, inverted) || ret);
3265N/A ret = (storeEdge(pRightEdge + 0,
3265N/A x , y , dx2, dy2,
3265N/A cx1, cy1, cx2, cy2, !inverted) || ret);
3265N/A ret = (storeEdge(pRightEdge + 1,
3265N/A x+dx2, y+dy2, dx1, dy1,
3265N/A cx1, cy1, cx2, cy2, !inverted) || ret);
3265N/A return ret;
3265N/A}
3265N/A
3265N/A/*
3265N/A * The X0,Y0,X1,Y1 values represent a trapezoidal fragment whose
3265N/A * coverage must be accounted for in the accum buffer.
3265N/A *
3265N/A * All four values are assumed to fall within (or on the edge of)
3265N/A * a single pixel.
3265N/A *
3265N/A * The trapezoid area is accumulated into the proper element of
3265N/A * the accum buffer and the remainder of the "slice height" is
3265N/A * accumulated into the element to its right.
3265N/A */
3265N/A#define INSERT_ACCUM(pACCUM, IMIN, IMAX, X0, Y0, X1, Y1, CX1, CX2, MULT) \
3265N/A do { \
3265N/A jdouble xmid = ((X0) + (X1)) * 0.5; \
3265N/A if (xmid <= (CX2)) { \
3265N/A jdouble sliceh = ((Y1) - (Y0)); \
3265N/A jdouble slicearea; \
3265N/A jint i; \
3265N/A if (xmid < (CX1)) { \
3265N/A /* Accumulate the entire slice height into accum[0]. */ \
3265N/A i = 0; \
3265N/A slicearea = sliceh; \
3265N/A } else { \
3265N/A jdouble xpos = floor(xmid); \
3265N/A i = ((jint) xpos) - (CX1); \
3265N/A slicearea = (xpos+1-xmid) * sliceh; \
3265N/A } \
3265N/A if (IMIN > i) { \
3265N/A IMIN = i; \
3265N/A } \
3265N/A (pACCUM)[i++] += (jfloat) ((MULT) * slicearea); \
3265N/A (pACCUM)[i++] += (jfloat) ((MULT) * (sliceh - slicearea)); \
3265N/A if (IMAX < i) { \
3265N/A IMAX = i; \
3265N/A } \
3265N/A } \
3265N/A } while (0)
3265N/A
3265N/A/*
3265N/A * Accumulate the contributions for a given edge crossing a given
3265N/A * scan line into the corresponding entries of the accum buffer.
3265N/A * CY1 is the Y coordinate of the top edge of the scanline and CY2
3265N/A * is equal to (CY1 + 1) and is the Y coordinate of the bottom edge
3265N/A * of the scanline. CX1 and CX2 are the left and right edges of the
3265N/A * clip (or area of interest) being rendered.
3265N/A *
3265N/A * The edge is processed from the top edge to the bottom edge and
3265N/A * a single pixel column at a time.
3265N/A */
3265N/A#define ACCUM_EDGE(pEDGE, pACCUM, IMIN, IMAX, CX1, CY1, CX2, CY2) \
3265N/A do { \
3265N/A jdouble x, y, xnext, ynext, xlast, ylast, dx, dy, mult; \
3265N/A y = (pEDGE)->y; \
3265N/A dy = (pEDGE)->celldy; \
3265N/A ylast = (pEDGE)->ybot; \
3265N/A if (ylast <= (CY1) || y >= (CY2) || dy == 0.0) { \
3265N/A break; \
3265N/A } \
3265N/A x = (pEDGE)->x; \
3265N/A dx = (pEDGE)->celldx; \
3265N/A if (ylast > (CY2)) { \
3265N/A ylast = (CY2); \
3265N/A xlast = (pEDGE)->xnexty; \
3265N/A } else { \
3265N/A xlast = (pEDGE)->xbot; \
3265N/A } \
3265N/A xnext = (pEDGE)->xnextx; \
3265N/A ynext = (pEDGE)->ynextx; \
3265N/A mult = ((pEDGE)->isTrailing) ? -1.0 : 1.0; \
3265N/A while (ynext <= ylast) { \
3265N/A INSERT_ACCUM(pACCUM, IMIN, IMAX, \
3265N/A x, y, xnext, ynext, \
3265N/A CX1, CX2, mult); \
3265N/A x = xnext; \
3265N/A y = ynext; \
3265N/A xnext += dx; \
3265N/A ynext += dy; \
3265N/A } \
3265N/A (pEDGE)->ynextx = ynext; \
3265N/A (pEDGE)->xnextx = xnext; \
3265N/A INSERT_ACCUM(pACCUM, IMIN, IMAX, \
3265N/A x, y, xlast, ylast, \
3265N/A CX1, CX2, mult); \
3265N/A (pEDGE)->x = xlast; \
3265N/A (pEDGE)->y = ylast; \
3265N/A (pEDGE)->xnexty = xlast + (pEDGE)->linedx; \
3265N/A } while(0)
3265N/A
3265N/A/* Main function to fill a single Parallelogram */
3265N/Astatic void
3265N/AfillAAPgram(NativePrimitive *pPrim, SurfaceDataRasInfo *pRasInfo,
3265N/A CompositeInfo *pCompInfo, jint color, unsigned char *pMask,
3265N/A void *pDst,
3265N/A jdouble x1, jdouble y1,
3265N/A jdouble dx1, jdouble dy1,
3265N/A jdouble dx2, jdouble dy2)
3265N/A{
3265N/A jint cx1 = pRasInfo->bounds.x1;
3265N/A jint cy1 = pRasInfo->bounds.y1;
3265N/A jint cx2 = pRasInfo->bounds.x2;
3265N/A jint cy2 = pRasInfo->bounds.y2;
3265N/A jint width = cx2 - cx1;
3265N/A EdgeInfo edges[4];
3265N/A jfloat localaccum[MASK_BUF_LEN + 1];
3265N/A jfloat *pAccum;
3265N/A
3265N/A if (!storePgram(edges + 0, edges + 2,
3265N/A x1, y1, dx1, dy1, dx2, dy2,
3265N/A cx1, cy1, cx2, cy2,
3265N/A JNI_FALSE))
3265N/A {
3265N/A return;
3265N/A }
3265N/A
3265N/A pAccum = ((width > MASK_BUF_LEN)
3265N/A ? malloc((width + 1) * sizeof(jfloat))
3265N/A : localaccum);
3265N/A if (pAccum == NULL) {
3265N/A return;
3265N/A }
3265N/A memset(pAccum, 0, (width+1) * sizeof(jfloat));
3265N/A
3265N/A while (cy1 < cy2) {
3265N/A jint lmin, lmax, rmin, rmax;
3265N/A jint moff, x;
3265N/A jdouble accum;
3265N/A unsigned char lastcov;
3265N/A
3265N/A lmin = rmin = width + 2;
3265N/A lmax = rmax = 0;
3265N/A ACCUM_EDGE(&edges[0], pAccum, lmin, lmax,
3265N/A cx1, cy1, cx2, cy1+1);
3265N/A ACCUM_EDGE(&edges[1], pAccum, lmin, lmax,
3265N/A cx1, cy1, cx2, cy1+1);
3265N/A ACCUM_EDGE(&edges[2], pAccum, rmin, rmax,
3265N/A cx1, cy1, cx2, cy1+1);
3265N/A ACCUM_EDGE(&edges[3], pAccum, rmin, rmax,
3265N/A cx1, cy1, cx2, cy1+1);
3265N/A if (lmax > width) {
3265N/A lmax = width; /* Extra col has data we do not need. */
3265N/A }
3265N/A if (rmax > width) {
3265N/A rmax = width; /* Extra col has data we do not need. */
3265N/A }
3265N/A /* If ranges overlap, handle both in the first pass. */
3265N/A if (rmin <= lmax) {
3265N/A lmax = rmax;
3265N/A }
3265N/A
3265N/A x = lmin;
3265N/A accum = 0.0;
3265N/A moff = 0;
3265N/A lastcov = 0;
3265N/A while (x < lmax) {
3265N/A accum += pAccum[x];
3265N/A pAccum[x] = 0.0f;
3265N/A pMask[moff++] = lastcov = DblToMask(accum);
3265N/A x++;
3265N/A }
3265N/A /* Check for a solid center section. */
3265N/A if (lastcov == 0xFF) {
3265N/A jint endx;
3265N/A void *pRow;
3265N/A
3265N/A /* First process the existing partial coverage data. */
3265N/A if (moff > 0) {
3265N/A pRow = PtrCoord(pDst, x-moff, pRasInfo->pixelStride, 0, 0);
3265N/A (*pPrim->funcs.maskfill)(pRow,
3265N/A pMask, 0, 0,
3265N/A moff, 1,
3265N/A color, pRasInfo,
3265N/A pPrim, pCompInfo);
3265N/A moff = 0;
3265N/A }
3265N/A
3265N/A /* Where does the center section end? */
3265N/A /* If there is no right AA edge in the accum buffer, then */
3265N/A /* the right edge was beyond the clip, so fill out to width */
3265N/A endx = (rmin < rmax) ? rmin : width;
3265N/A if (x < endx) {
3265N/A pRow = PtrCoord(pDst, x, pRasInfo->pixelStride, 0, 0);
3265N/A (*pPrim->funcs.maskfill)(pRow,
3265N/A NULL, 0, 0,
3265N/A endx - x, 1,
3265N/A color, pRasInfo,
3265N/A pPrim, pCompInfo);
3265N/A x = endx;
3265N/A }
3265N/A } else if (lastcov > 0 && rmin >= rmax) {
3265N/A /* We are not at 0 coverage, but there is no right edge, */
3265N/A /* force a right edge so we process pixels out to width. */
3265N/A rmax = width;
3265N/A }
3265N/A /* The following loop will process the right AA edge and/or any */
3265N/A /* partial coverage center section not processed above. */
3265N/A while (x < rmax) {
3265N/A accum += pAccum[x];
3265N/A pAccum[x] = 0.0f;
3265N/A pMask[moff++] = DblToMask(accum);
3265N/A x++;
3265N/A }
3265N/A if (moff > 0) {
3265N/A void *pRow = PtrCoord(pDst, x-moff, pRasInfo->pixelStride, 0, 0);
3265N/A (*pPrim->funcs.maskfill)(pRow,
3265N/A pMask, 0, 0,
3265N/A moff, 1,
3265N/A color, pRasInfo,
3265N/A pPrim, pCompInfo);
3265N/A }
3265N/A pDst = PtrAddBytes(pDst, pRasInfo->scanStride);
3265N/A cy1++;
3265N/A }
3265N/A if (pAccum != localaccum) {
3265N/A free(pAccum);
3265N/A }
3265N/A}
3265N/A
3265N/A/*
3265N/A * Class: sun_java2d_loops_MaskFill
3265N/A * Method: FillAAPgram
3265N/A * Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;Ljava/awt/Composite;DDDDDD)V
3265N/A */
3265N/AJNIEXPORT void JNICALL
3265N/AJava_sun_java2d_loops_MaskFill_FillAAPgram
3265N/A (JNIEnv *env, jobject self,
3265N/A jobject sg2d, jobject sData, jobject comp,
3265N/A jdouble x0, jdouble y0,
3265N/A jdouble dx1, jdouble dy1,
3265N/A jdouble dx2, jdouble dy2)
3265N/A{
3265N/A SurfaceDataOps *sdOps;
3265N/A SurfaceDataRasInfo rasInfo;
3265N/A NativePrimitive *pPrim;
3265N/A CompositeInfo compInfo;
3265N/A jint ix1, iy1, ix2, iy2;
3265N/A
3265N/A if ((dy1 == 0 && dx1 == 0) || (dy2 == 0 && dx2 == 0)) {
3265N/A return;
3265N/A }
3265N/A
3265N/A /*
3265N/A * Sort parallelogram by y values, ensure that each delta vector
3265N/A * has a non-negative y delta.
3265N/A */
3265N/A SORT_PGRAM(x0, y0, dx1, dy1, dx2, dy2, );
3265N/A
3265N/A PGRAM_MIN_MAX(ix1, ix2, x0, dx1, dx2, JNI_TRUE);
3265N/A iy1 = (jint) floor(y0);
3265N/A iy2 = (jint) ceil(y0 + dy1 + dy2);
3265N/A
3265N/A pPrim = GetNativePrim(env, self);
3265N/A if (pPrim == NULL) {
3265N/A return;
3265N/A }
3265N/A if (pPrim->pCompType->getCompInfo != NULL) {
3265N/A (*pPrim->pCompType->getCompInfo)(env, &compInfo, comp);
3265N/A }
3265N/A
3265N/A sdOps = SurfaceData_GetOps(env, sData);
3265N/A if (sdOps == 0) {
3265N/A return;
3265N/A }
3265N/A
3265N/A GrPrim_Sg2dGetClip(env, sg2d, &rasInfo.bounds);
3265N/A SurfaceData_IntersectBoundsXYXY(&rasInfo.bounds, ix1, iy1, ix2, iy2);
3265N/A if (rasInfo.bounds.y2 <= rasInfo.bounds.y1 ||
3265N/A rasInfo.bounds.x2 <= rasInfo.bounds.x1)
3265N/A {
3265N/A return;
3265N/A }
3265N/A
3265N/A if (sdOps->Lock(env, sdOps, &rasInfo, pPrim->dstflags) != SD_SUCCESS) {
3265N/A return;
3265N/A }
3265N/A
3265N/A ix1 = rasInfo.bounds.x1;
3265N/A iy1 = rasInfo.bounds.y1;
3265N/A ix2 = rasInfo.bounds.x2;
3265N/A iy2 = rasInfo.bounds.y2;
3265N/A if (ix2 > ix1 && iy2 > iy1) {
3265N/A jint width = ix2 - ix1;
3265N/A jint color = GrPrim_Sg2dGetEaRGB(env, sg2d);
3265N/A unsigned char localmask[MASK_BUF_LEN];
3265N/A unsigned char *pMask = ((width > MASK_BUF_LEN)
3265N/A ? malloc(width)
3265N/A : localmask);
3265N/A
3265N/A sdOps->GetRasInfo(env, sdOps, &rasInfo);
3265N/A if (rasInfo.rasBase != NULL && pMask != NULL) {
3265N/A void *pDst = PtrCoord(rasInfo.rasBase,
3265N/A ix1, rasInfo.pixelStride,
3265N/A iy1, rasInfo.scanStride);
3265N/A if (dy1 == 0 && dx2 == 0) {
3265N/A if (dx1 < 0) {
3265N/A // We sorted by Y above, but not by X
3265N/A x0 += dx1;
3265N/A dx1 = -dx1;
3265N/A }
3265N/A fillAARect(pPrim, &rasInfo, &compInfo,
3265N/A color, pMask, pDst,
3265N/A x0, y0, x0+dx1, y0+dy2);
3265N/A } else if (dx1 == 0 && dy2 == 0) {
3265N/A if (dx2 < 0) {
3265N/A // We sorted by Y above, but not by X
3265N/A x0 += dx2;
3265N/A dx2 = -dx2;
3265N/A }
3265N/A fillAARect(pPrim, &rasInfo, &compInfo,
3265N/A color, pMask, pDst,
3265N/A x0, y0, x0+dx2, y0+dy1);
3265N/A } else {
3265N/A fillAAPgram(pPrim, &rasInfo, &compInfo,
3265N/A color, pMask, pDst,
3265N/A x0, y0, dx1, dy1, dx2, dy2);
3265N/A }
3265N/A }
3265N/A SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
3265N/A if (pMask != NULL && pMask != localmask) {
3265N/A free(pMask);
3265N/A }
0N/A }
0N/A SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
0N/A}
3265N/A
3265N/A/* Main function to fill a double pair of (inner and outer) parallelograms */
3265N/Astatic void
3265N/AdrawAAPgram(NativePrimitive *pPrim, SurfaceDataRasInfo *pRasInfo,
3265N/A CompositeInfo *pCompInfo, jint color, unsigned char *pMask,
3265N/A void *pDst,
3265N/A jdouble ox0, jdouble oy0,
3265N/A jdouble dx1, jdouble dy1,
3265N/A jdouble dx2, jdouble dy2,
3265N/A jdouble ldx1, jdouble ldy1,
3265N/A jdouble ldx2, jdouble ldy2)
3265N/A{
3265N/A jint cx1 = pRasInfo->bounds.x1;
3265N/A jint cy1 = pRasInfo->bounds.y1;
3265N/A jint cx2 = pRasInfo->bounds.x2;
3265N/A jint cy2 = pRasInfo->bounds.y2;
3265N/A jint width = cx2 - cx1;
3265N/A EdgeInfo edges[8];
3265N/A jfloat localaccum[MASK_BUF_LEN + 1];
3265N/A jfloat *pAccum;
3265N/A
3265N/A if (!storePgram(edges + 0, edges + 6,
3265N/A ox0, oy0,
3265N/A dx1 + ldx1, dy1 + ldy1,
3265N/A dx2 + ldx2, dy2 + ldy2,
3265N/A cx1, cy1, cx2, cy2,
3265N/A JNI_FALSE))
3265N/A {
3265N/A /* If outer pgram does not contribute, then inner cannot either. */
3265N/A return;
3265N/A }
3265N/A storePgram(edges + 2, edges + 4,
3265N/A ox0 + ldx1 + ldx2, oy0 + ldy1 + ldy2,
3265N/A dx1 - ldx1, dy1 - ldy1,
3265N/A dx2 - ldx2, dy2 - ldy2,
3265N/A cx1, cy1, cx2, cy2,
3265N/A JNI_TRUE);
3265N/A
3265N/A pAccum = ((width > MASK_BUF_LEN)
3265N/A ? malloc((width + 1) * sizeof(jfloat))
3265N/A : localaccum);
3265N/A if (pAccum == NULL) {
3265N/A return;
3265N/A }
3265N/A memset(pAccum, 0, (width+1) * sizeof(jfloat));
3265N/A
3265N/A while (cy1 < cy2) {
3265N/A jint lmin, lmax, rmin, rmax;
3265N/A jint moff, x;
3265N/A jdouble accum;
3265N/A unsigned char lastcov;
3265N/A
3265N/A lmin = rmin = width + 2;
3265N/A lmax = rmax = 0;
3265N/A ACCUM_EDGE(&edges[0], pAccum, lmin, lmax,
3265N/A cx1, cy1, cx2, cy1+1);
3265N/A ACCUM_EDGE(&edges[1], pAccum, lmin, lmax,
3265N/A cx1, cy1, cx2, cy1+1);
3265N/A ACCUM_EDGE(&edges[2], pAccum, lmin, lmax,
3265N/A cx1, cy1, cx2, cy1+1);
3265N/A ACCUM_EDGE(&edges[3], pAccum, lmin, lmax,
3265N/A cx1, cy1, cx2, cy1+1);
3265N/A ACCUM_EDGE(&edges[4], pAccum, rmin, rmax,
3265N/A cx1, cy1, cx2, cy1+1);
3265N/A ACCUM_EDGE(&edges[5], pAccum, rmin, rmax,
3265N/A cx1, cy1, cx2, cy1+1);
3265N/A ACCUM_EDGE(&edges[6], pAccum, rmin, rmax,
3265N/A cx1, cy1, cx2, cy1+1);
3265N/A ACCUM_EDGE(&edges[7], pAccum, rmin, rmax,
3265N/A cx1, cy1, cx2, cy1+1);
3265N/A if (lmax > width) {
3265N/A lmax = width; /* Extra col has data we do not need. */
3265N/A }
3265N/A if (rmax > width) {
3265N/A rmax = width; /* Extra col has data we do not need. */
3265N/A }
3265N/A /* If ranges overlap, handle both in the first pass. */
3265N/A if (rmin <= lmax) {
3265N/A lmax = rmax;
3265N/A }
3265N/A
3265N/A x = lmin;
3265N/A accum = 0.0;
3265N/A moff = 0;
3265N/A lastcov = 0;
3265N/A while (x < lmax) {
3265N/A accum += pAccum[x];
3265N/A pAccum[x] = 0.0f;
3265N/A pMask[moff++] = lastcov = DblToMask(accum);
3265N/A x++;
3265N/A }
3265N/A /* Check for an empty or solidcenter section. */
3265N/A if (lastcov == 0 || lastcov == 0xFF) {
3265N/A jint endx;
3265N/A void *pRow;
3265N/A
3265N/A /* First process the existing partial coverage data. */
3265N/A if (moff > 0) {
3265N/A pRow = PtrCoord(pDst, x-moff, pRasInfo->pixelStride, 0, 0);
3265N/A (*pPrim->funcs.maskfill)(pRow,
3265N/A pMask, 0, 0,
3265N/A moff, 1,
3265N/A color, pRasInfo,
3265N/A pPrim, pCompInfo);
3265N/A moff = 0;
3265N/A }
3265N/A
3265N/A /* Where does the center section end? */
3265N/A /* If there is no right AA edge in the accum buffer, then */
3265N/A /* the right edge was beyond the clip, so fill out to width */
3265N/A endx = (rmin < rmax) ? rmin : width;
3265N/A if (x < endx) {
3265N/A if (lastcov == 0xFF) {
3265N/A pRow = PtrCoord(pDst, x, pRasInfo->pixelStride, 0, 0);
3265N/A (*pPrim->funcs.maskfill)(pRow,
3265N/A NULL, 0, 0,
3265N/A endx - x, 1,
3265N/A color, pRasInfo,
3265N/A pPrim, pCompInfo);
3265N/A }
3265N/A x = endx;
3265N/A }
3265N/A } else if (rmin >= rmax) {
3265N/A /* We are not at 0 coverage, but there is no right edge, */
3265N/A /* force a right edge so we process pixels out to width. */
3265N/A rmax = width;
3265N/A }
3265N/A /* The following loop will process the right AA edge and/or any */
3265N/A /* partial coverage center section not processed above. */
3265N/A while (x < rmax) {
3265N/A accum += pAccum[x];
3265N/A pAccum[x] = 0.0f;
3265N/A pMask[moff++] = lastcov = DblToMask(accum);
3265N/A x++;
3265N/A }
3265N/A if (moff > 0) {
3265N/A void *pRow = PtrCoord(pDst, x-moff, pRasInfo->pixelStride, 0, 0);
3265N/A (*pPrim->funcs.maskfill)(pRow,
3265N/A pMask, 0, 0,
3265N/A moff, 1,
3265N/A color, pRasInfo,
3265N/A pPrim, pCompInfo);
3265N/A }
3265N/A if (lastcov == 0xFF && x < width) {
3265N/A void *pRow = PtrCoord(pDst, x, pRasInfo->pixelStride, 0, 0);
3265N/A (*pPrim->funcs.maskfill)(pRow,
3265N/A NULL, 0, 0,
3265N/A width - x, 1,
3265N/A color, pRasInfo,
3265N/A pPrim, pCompInfo);
3265N/A }
3265N/A pDst = PtrAddBytes(pDst, pRasInfo->scanStride);
3265N/A cy1++;
3265N/A }
3265N/A if (pAccum != localaccum) {
3265N/A free(pAccum);
3265N/A }
3265N/A}
3265N/A
3265N/A/*
3265N/A * Class: sun_java2d_loops_MaskFill
3265N/A * Method: DrawAAPgram
3265N/A * Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;Ljava/awt/Composite;DDDDDDDD)V
3265N/A */
3265N/AJNIEXPORT void JNICALL
3265N/AJava_sun_java2d_loops_MaskFill_DrawAAPgram
3265N/A (JNIEnv *env, jobject self,
3265N/A jobject sg2d, jobject sData, jobject comp,
3265N/A jdouble x0, jdouble y0,
3265N/A jdouble dx1, jdouble dy1,
3265N/A jdouble dx2, jdouble dy2,
3265N/A jdouble lw1, jdouble lw2)
3265N/A{
3265N/A SurfaceDataOps *sdOps;
3265N/A SurfaceDataRasInfo rasInfo;
3265N/A NativePrimitive *pPrim;
3265N/A CompositeInfo compInfo;
3265N/A jint ix1, iy1, ix2, iy2;
3265N/A jdouble ldx1, ldy1, ldx2, ldy2;
3265N/A jdouble ox0, oy0;
3265N/A
3265N/A if ((dy1 == 0 && dx1 == 0) || (dy2 == 0 && dx2 == 0)) {
3265N/A return;
3265N/A }
3265N/A
3265N/A /*
3265N/A * Sort parallelogram by y values, ensure that each delta vector
3265N/A * has a non-negative y delta.
3265N/A */
3265N/A SORT_PGRAM(x0, y0, dx1, dy1, dx2, dy2,
3265N/A v = lw1; lw1 = lw2; lw2 = v;);
3265N/A
3265N/A // dx,dy for line width in the "1" and "2" directions.
3265N/A ldx1 = dx1 * lw1;
3265N/A ldy1 = dy1 * lw1;
3265N/A ldx2 = dx2 * lw2;
3265N/A ldy2 = dy2 * lw2;
3265N/A
3265N/A // calculate origin of the outer parallelogram
3265N/A ox0 = x0 - (ldx1 + ldx2) / 2.0;
3265N/A oy0 = y0 - (ldy1 + ldy2) / 2.0;
3265N/A
3265N/A if (lw1 >= 1.0 || lw2 >= 1.0) {
3265N/A /* Only need to fill an outer pgram if the interior no longer
3265N/A * has a hole in it (i.e. if either of the line width ratios
3265N/A * were greater than or equal to 1.0).
3265N/A */
3265N/A Java_sun_java2d_loops_MaskFill_FillAAPgram(env, self,
3265N/A sg2d, sData, comp,
3265N/A ox0, oy0,
3265N/A dx1 + ldx1, dy1 + ldy1,
3265N/A dx2 + ldx2, dy2 + ldy2);
3265N/A return;
3265N/A }
3265N/A
3265N/A PGRAM_MIN_MAX(ix1, ix2, ox0, dx1+ldx1, dx2+ldx2, JNI_TRUE);
3265N/A iy1 = (jint) floor(oy0);
3265N/A iy2 = (jint) ceil(oy0 + dy1 + ldy1 + dy2 + ldy2);
3265N/A
3265N/A pPrim = GetNativePrim(env, self);
3265N/A if (pPrim == NULL) {
3265N/A return;
3265N/A }
3265N/A if (pPrim->pCompType->getCompInfo != NULL) {
3265N/A (*pPrim->pCompType->getCompInfo)(env, &compInfo, comp);
3265N/A }
3265N/A
3265N/A sdOps = SurfaceData_GetOps(env, sData);
3265N/A if (sdOps == 0) {
3265N/A return;
3265N/A }
3265N/A
3265N/A GrPrim_Sg2dGetClip(env, sg2d, &rasInfo.bounds);
3265N/A SurfaceData_IntersectBoundsXYXY(&rasInfo.bounds, ix1, iy1, ix2, iy2);
3265N/A if (rasInfo.bounds.y2 <= rasInfo.bounds.y1 ||
3265N/A rasInfo.bounds.x2 <= rasInfo.bounds.x1)
3265N/A {
3265N/A return;
3265N/A }
3265N/A
3265N/A if (sdOps->Lock(env, sdOps, &rasInfo, pPrim->dstflags) != SD_SUCCESS) {
3265N/A return;
3265N/A }
3265N/A
3265N/A ix1 = rasInfo.bounds.x1;
3265N/A iy1 = rasInfo.bounds.y1;
3265N/A ix2 = rasInfo.bounds.x2;
3265N/A iy2 = rasInfo.bounds.y2;
3265N/A if (ix2 > ix1 && iy2 > iy1) {
3265N/A jint width = ix2 - ix1;
3265N/A jint color = GrPrim_Sg2dGetEaRGB(env, sg2d);
3265N/A unsigned char localmask[MASK_BUF_LEN];
3265N/A unsigned char *pMask = ((width > MASK_BUF_LEN)
3265N/A ? malloc(width)
3265N/A : localmask);
3265N/A
3265N/A sdOps->GetRasInfo(env, sdOps, &rasInfo);
3265N/A if (rasInfo.rasBase != NULL && pMask != NULL) {
3265N/A void *pDst = PtrCoord(rasInfo.rasBase,
3265N/A ix1, rasInfo.pixelStride,
3265N/A iy1, rasInfo.scanStride);
3265N/A /*
3265N/A * NOTE: aligned rects could probably be drawn
3265N/A * even faster with a little work here.
3265N/A * if (dy1 == 0 && dx2 == 0) {
3265N/A * drawAARect(pPrim, &rasInfo, &compInfo,
3265N/A * color, pMask, pDst,
3265N/A * ox0, oy0, ox0+dx1+ldx1, oy0+dy2+ldy2, ldx1, ldy2);
3265N/A * } else if (dx1 == 0 && dy2 == 0) {
3265N/A * drawAARect(pPrim, &rasInfo, &compInfo,
3265N/A * color, pMask, pDst,
3265N/A * ox0, oy0, ox0+dx2+ldx2, oy0+dy1+ldy1, ldx2, ldy1);
3265N/A * } else {
3265N/A */
3265N/A drawAAPgram(pPrim, &rasInfo, &compInfo,
3265N/A color, pMask, pDst,
3265N/A ox0, oy0,
3265N/A dx1, dy1, dx2, dy2,
3265N/A ldx1, ldy1, ldx2, ldy2);
3265N/A /*
3265N/A * }
3265N/A */
3265N/A }
3265N/A SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
3265N/A if (pMask != NULL && pMask != localmask) {
3265N/A free(pMask);
3265N/A }
3265N/A }
3265N/A SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
3265N/A}