Path: blob/master/src/java.desktop/share/native/libawt/java2d/pipe/Region.c
41159 views
/*1* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <stdlib.h>2627#include "jni_util.h"2829#include "Region.h"30#include "sizecalc.h"3132static jfieldID endIndexID;33static jfieldID bandsID;34static jfieldID loxID;35static jfieldID loyID;36static jfieldID hixID;37static jfieldID hiyID;3839#define InitField(var, env, jcl, name, type) \40do { \41var = (*env)->GetFieldID(env, jcl, name, type); \42if (var == NULL) { \43return; \44} \45} while (0)4647/*48* Class: sun_java2d_pipe_Region49* Method: initIDs50* Signature: ()V51*/52JNIEXPORT void JNICALL53Java_sun_java2d_pipe_Region_initIDs(JNIEnv *env, jclass reg)54{55InitField(endIndexID, env, reg, "endIndex", "I");56InitField(bandsID, env, reg, "bands", "[I");5758InitField(loxID, env, reg, "lox", "I");59InitField(loyID, env, reg, "loy", "I");60InitField(hixID, env, reg, "hix", "I");61InitField(hiyID, env, reg, "hiy", "I");62}6364JNIEXPORT jint JNICALL65Region_GetInfo(JNIEnv *env, jobject region, RegionData *pRgnInfo)66{67if (JNU_IsNull(env, region)) {68pRgnInfo->bounds.x1 = pRgnInfo->bounds.y1 = 0x80000000;69pRgnInfo->bounds.x2 = pRgnInfo->bounds.y2 = 0x7fffffff;70pRgnInfo->endIndex = 0;71} else {72pRgnInfo->bounds.x1 = (*env)->GetIntField(env, region, loxID);73pRgnInfo->bounds.y1 = (*env)->GetIntField(env, region, loyID);74pRgnInfo->bounds.x2 = (*env)->GetIntField(env, region, hixID);75pRgnInfo->bounds.y2 = (*env)->GetIntField(env, region, hiyID);76pRgnInfo->endIndex = (*env)->GetIntField(env, region, endIndexID);77}78pRgnInfo->bands = (Region_IsRectangular(pRgnInfo)79? NULL80: (*env)->GetObjectField(env, region, bandsID));81return 0;82}8384JNIEXPORT void JNICALL85Region_GetBounds(JNIEnv *env, jobject region, SurfaceDataBounds *b)86{87if (JNU_IsNull(env, region)) {88b->x1 = b->y1 = 0x80000000;89b->x2 = b->y2 = 0x7fffffff;90} else {91b->x1 = (*env)->GetIntField(env, region, loxID);92b->y1 = (*env)->GetIntField(env, region, loyID);93b->x2 = (*env)->GetIntField(env, region, hixID);94b->y2 = (*env)->GetIntField(env, region, hiyID);95}96}9798JNIEXPORT void JNICALL99Region_StartIteration(JNIEnv *env, RegionData *pRgnInfo)100{101pRgnInfo->pBands =102(Region_IsRectangular(pRgnInfo)103? NULL104: (*env)->GetPrimitiveArrayCritical(env, pRgnInfo->bands, 0));105pRgnInfo->index = 0;106pRgnInfo->numrects = 0;107}108109JNIEXPORT jint JNICALL110Region_CountIterationRects(RegionData *pRgnInfo)111{112jint totalrects;113if (Region_IsEmpty(pRgnInfo)) {114totalrects = 0;115} else if (Region_IsRectangular(pRgnInfo)) {116totalrects = 1;117} else {118jint *pBands = pRgnInfo->pBands;119int index = 0;120totalrects = 0;121while (index < pRgnInfo->endIndex) {122jint xy1 = pBands[index++];123jint xy2 = pBands[index++];124jint numrects = pBands[index++];125if (xy1 >= pRgnInfo->bounds.y2) {126break;127}128if (xy2 > pRgnInfo->bounds.y1) {129while (numrects > 0) {130xy1 = pBands[index++];131xy2 = pBands[index++];132numrects--;133if (xy1 >= pRgnInfo->bounds.x2) {134break;135}136if (xy2 > pRgnInfo->bounds.x1) {137totalrects++;138}139}140}141index += numrects * 2;142}143}144return totalrects;145}146147JNIEXPORT jint JNICALL148Region_NextIteration(RegionData *pRgnInfo, SurfaceDataBounds *pSpan)149{150jint index = pRgnInfo->index;151if (Region_IsRectangular(pRgnInfo)) {152if (index > 0 || Region_IsEmpty(pRgnInfo)) {153return 0;154}155pSpan->x1 = pRgnInfo->bounds.x1;156pSpan->x2 = pRgnInfo->bounds.x2;157pSpan->y1 = pRgnInfo->bounds.y1;158pSpan->y2 = pRgnInfo->bounds.y2;159index = 1;160} else {161jint *pBands = pRgnInfo->pBands;162jint xy1, xy2;163jint numrects = pRgnInfo->numrects;164while (JNI_TRUE) {165if (numrects <= 0) {166if (index >= pRgnInfo->endIndex) {167return 0;168}169xy1 = pBands[index++];170if (xy1 >= pRgnInfo->bounds.y2) {171return 0;172}173if (xy1 < pRgnInfo->bounds.y1) {174xy1 = pRgnInfo->bounds.y1;175}176xy2 = pBands[index++];177numrects = pBands[index++];178if (xy2 > pRgnInfo->bounds.y2) {179xy2 = pRgnInfo->bounds.y2;180}181if (xy2 <= xy1) {182index += numrects * 2;183numrects = 0;184continue;185}186pSpan->y1 = xy1;187pSpan->y2 = xy2;188}189xy1 = pBands[index++];190xy2 = pBands[index++];191numrects--;192if (xy1 >= pRgnInfo->bounds.x2) {193index += numrects * 2;194numrects = 0;195continue;196}197if (xy1 < pRgnInfo->bounds.x1) {198xy1 = pRgnInfo->bounds.x1;199}200if (xy2 > pRgnInfo->bounds.x2) {201xy2 = pRgnInfo->bounds.x2;202}203if (xy2 > xy1) {204pSpan->x1 = xy1;205pSpan->x2 = xy2;206break;207}208}209pRgnInfo->numrects = numrects;210}211pRgnInfo->index = index;212return 1;213}214215JNIEXPORT void JNICALL216Region_EndIteration(JNIEnv *env, RegionData *pRgnInfo)217{218if (pRgnInfo->endIndex != 0) {219(*env)->ReleasePrimitiveArrayCritical(env, pRgnInfo->bands,220pRgnInfo->pBands, JNI_ABORT);221}222}223224/*225* The code was extracted from226* src/solaris/native/sun/java2d/x11/X11SurfaceData.c227* XSetClip() method.228*229* If the region is null, the shape is considered to be230* a rectangle (x1, y1, x2-x1, y2-y1).231*232* The *pRect must point to a buffer of initialBufferSize233* rectangles. If there're more than initialBufferSize234* rectangles in the region, the buffer is reallocated235* and its pointer is being stored at the *pRect. Using236* this practice we may use a small local (on the stack)237* buffer and avoid allocating/freeing a memory if we238* operate simple regions.239*/240JNIEXPORT int JNICALL241RegionToYXBandedRectangles(JNIEnv *env,242jint x1, jint y1, jint x2, jint y2, jobject region,243RECT_T ** pRect, unsigned int initialBufferSize)244{245RegionData clipInfo;246SurfaceDataBounds span;247int i, numrects;248249if (region == NULL) {250if (x2 <= x1 || y2 <= y1) {251/* empty clip, disable rendering */252numrects = 0;253} else {254RECT_SET(**pRect, x1, y1, x2 - x1, y2 - y1);255numrects = 1;256}257} else {258if (Region_GetInfo(env, region, &clipInfo)) {259/* return; REMIND: What to do here? */260}261Region_StartIteration(env, &clipInfo);262if ((*env)->ExceptionCheck(env)) {263return 0;264}265266numrects = Region_CountIterationRects(&clipInfo);267if ((unsigned long)numrects > initialBufferSize) {268*pRect = (RECT_T *) SAFE_SIZE_ARRAY_ALLOC(malloc, numrects, sizeof(RECT_T));269if (*pRect == NULL) {270Region_EndIteration(env, &clipInfo);271JNU_ThrowOutOfMemoryError(env,272"Can't allocate shape region memory");273return 0;274}275}276for (i = 0; Region_NextIteration(&clipInfo, &span); i++) {277RECT_SET((*pRect)[i], span.x1, span.y1, span.x2 - span.x1, span.y2 - span.y1);278}279Region_EndIteration(env, &clipInfo);280}281282return numrects;283}284285286