Path: blob/master/src/java.desktop/share/native/libawt/awt/image/BufImgSurfaceData.c
41159 views
/*1* Copyright (c) 1999, 2019, 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 "BufImgSurfaceData.h"26#include <stdlib.h>2728#include "sun_awt_image_BufImgSurfaceData.h"2930#include "img_util_md.h"31#include "jni_util.h"32/* Define uintptr_t */33#include "gdefs.h"34#include "Disposer.h"3536/**37* This include file contains support code for loops using the38* SurfaceData interface to talk to an X11 drawable from native39* code.40*/4142static LockFunc BufImg_Lock;43static GetRasInfoFunc BufImg_GetRasInfo;44static ReleaseFunc BufImg_Release;45static DisposeFunc BufImg_Dispose;4647static ColorData *BufImg_SetupICM(JNIEnv *env, BufImgSDOps *bisdo);4849static jfieldID rgbID;50static jfieldID mapSizeID;51static jfieldID colorDataID;52static jfieldID pDataID;53static jfieldID allGrayID;5455static jclass clsICMCD;56static jmethodID initICMCDmID;57/*58* Class: sun_awt_image_BufImgSurfaceData59* Method: initIDs60* Signature: ()V61*/62JNIEXPORT void JNICALL63Java_sun_awt_image_BufImgSurfaceData_initIDs64(JNIEnv *env, jclass bisd, jclass icm, jclass cd)65{66if (sizeof(BufImgRIPrivate) > SD_RASINFO_PRIVATE_SIZE) {67JNU_ThrowInternalError(env, "Private RasInfo structure too large!");68return;69}7071clsICMCD = (*env)->NewWeakGlobalRef(env, cd);72JNU_CHECK_EXCEPTION(env);73CHECK_NULL(initICMCDmID = (*env)->GetMethodID(env, cd, "<init>", "(J)V"));74CHECK_NULL(pDataID = (*env)->GetFieldID(env, cd, "pData", "J"));75CHECK_NULL(rgbID = (*env)->GetFieldID(env, icm, "rgb", "[I"));76CHECK_NULL(allGrayID = (*env)->GetFieldID(env, icm, "allgrayopaque", "Z"));77CHECK_NULL(mapSizeID = (*env)->GetFieldID(env, icm, "map_size", "I"));78CHECK_NULL(colorDataID = (*env)->GetFieldID(env, icm, "colorData",79"Lsun/awt/image/BufImgSurfaceData$ICMColorData;"));80}8182/*83* Class: sun_awt_image_BufImgSurfaceData84* Method: initOps85* Signature: (Ljava/lang/Object;IIIII)V86*/87JNIEXPORT void JNICALL88Java_sun_awt_image_BufImgSurfaceData_initRaster(JNIEnv *env, jobject bisd,89jobject array,90jint offset, jint bitoffset,91jint width, jint height,92jint pixStr, jint scanStr,93jobject icm)94{95BufImgSDOps *bisdo =96(BufImgSDOps*)SurfaceData_InitOps(env, bisd, sizeof(BufImgSDOps));97if (bisdo == NULL) {98JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");99return;100}101bisdo->sdOps.Lock = BufImg_Lock;102bisdo->sdOps.GetRasInfo = BufImg_GetRasInfo;103bisdo->sdOps.Release = BufImg_Release;104bisdo->sdOps.Unlock = NULL;105bisdo->sdOps.Dispose = BufImg_Dispose;106bisdo->array = (*env)->NewWeakGlobalRef(env, array);107JNU_CHECK_EXCEPTION(env);108bisdo->offset = offset;109bisdo->bitoffset = bitoffset;110bisdo->scanStr = scanStr;111bisdo->pixStr = pixStr;112if (JNU_IsNull(env, icm)) {113bisdo->lutarray = NULL;114bisdo->lutsize = 0;115bisdo->icm = NULL;116} else {117jobject lutarray = (*env)->GetObjectField(env, icm, rgbID);118bisdo->lutarray = (*env)->NewWeakGlobalRef(env, lutarray);119JNU_CHECK_EXCEPTION(env);120bisdo->lutsize = (*env)->GetIntField(env, icm, mapSizeID);121bisdo->icm = (*env)->NewWeakGlobalRef(env, icm);122}123bisdo->rasbounds.x1 = 0;124bisdo->rasbounds.y1 = 0;125bisdo->rasbounds.x2 = width;126bisdo->rasbounds.y2 = height;127}128129/*130* Releases native structures associated with BufImgSurfaceData.ICMColorData.131*/132static void BufImg_Dispose_ICMColorData(JNIEnv *env, jlong pData)133{134ColorData *cdata = (ColorData*)jlong_to_ptr(pData);135freeICMColorData(cdata);136}137138/*139* Method for disposing native BufImgSD140*/141static void BufImg_Dispose(JNIEnv *env, SurfaceDataOps *ops)142{143/* ops is assumed non-null as it is checked in SurfaceData_DisposeOps */144BufImgSDOps *bisdo = (BufImgSDOps *)ops;145(*env)->DeleteWeakGlobalRef(env, bisdo->array);146if (bisdo->lutarray != NULL) {147(*env)->DeleteWeakGlobalRef(env, bisdo->lutarray);148}149if (bisdo->icm != NULL) {150(*env)->DeleteWeakGlobalRef(env, bisdo->icm);151}152}153154static jint BufImg_Lock(JNIEnv *env,155SurfaceDataOps *ops,156SurfaceDataRasInfo *pRasInfo,157jint lockflags)158{159BufImgSDOps *bisdo = (BufImgSDOps *)ops;160BufImgRIPrivate *bipriv = (BufImgRIPrivate *) &(pRasInfo->priv);161162if ((lockflags & (SD_LOCK_LUT)) != 0 && JNU_IsNull(env, bisdo->lutarray)) {163/* REMIND: Should this be an InvalidPipe exception? */164JNU_ThrowNullPointerException(env, "Attempt to lock missing colormap");165return SD_FAILURE;166}167if ((lockflags & SD_LOCK_INVCOLOR) != 0 ||168(lockflags & SD_LOCK_INVGRAY) != 0)169{170bipriv->cData = BufImg_SetupICM(env, bisdo);171if (bipriv->cData == NULL) {172(*env)->ExceptionClear(env);173JNU_ThrowNullPointerException(env, "Could not initialize inverse tables");174return SD_FAILURE;175}176} else {177bipriv->cData = NULL;178}179180bipriv->lockFlags = lockflags;181bipriv->base = NULL;182bipriv->lutbase = NULL;183184SurfaceData_IntersectBounds(&pRasInfo->bounds, &bisdo->rasbounds);185186return SD_SUCCESS;187}188189static void BufImg_GetRasInfo(JNIEnv *env,190SurfaceDataOps *ops,191SurfaceDataRasInfo *pRasInfo)192{193BufImgSDOps *bisdo = (BufImgSDOps *)ops;194BufImgRIPrivate *bipriv = (BufImgRIPrivate *) &(pRasInfo->priv);195196if ((bipriv->lockFlags & (SD_LOCK_RD_WR)) != 0) {197bipriv->base =198(*env)->GetPrimitiveArrayCritical(env, bisdo->array, NULL);199CHECK_NULL(bipriv->base);200}201if ((bipriv->lockFlags & (SD_LOCK_LUT)) != 0) {202bipriv->lutbase =203(*env)->GetPrimitiveArrayCritical(env, bisdo->lutarray, NULL);204}205206if (bipriv->base == NULL) {207pRasInfo->rasBase = NULL;208pRasInfo->pixelStride = 0;209pRasInfo->pixelBitOffset = 0;210pRasInfo->scanStride = 0;211} else {212pRasInfo->rasBase = (void *)213(((uintptr_t) bipriv->base) + bisdo->offset);214pRasInfo->pixelStride = bisdo->pixStr;215pRasInfo->pixelBitOffset = bisdo->bitoffset;216pRasInfo->scanStride = bisdo->scanStr;217}218if (bipriv->lutbase == NULL) {219pRasInfo->lutBase = NULL;220pRasInfo->lutSize = 0;221} else {222pRasInfo->lutBase = bipriv->lutbase;223pRasInfo->lutSize = bisdo->lutsize;224}225if (bipriv->cData == NULL) {226pRasInfo->invColorTable = NULL;227pRasInfo->redErrTable = NULL;228pRasInfo->grnErrTable = NULL;229pRasInfo->bluErrTable = NULL;230pRasInfo->representsPrimaries = 0;231} else {232pRasInfo->invColorTable = bipriv->cData->img_clr_tbl;233pRasInfo->redErrTable = bipriv->cData->img_oda_red;234pRasInfo->grnErrTable = bipriv->cData->img_oda_green;235pRasInfo->bluErrTable = bipriv->cData->img_oda_blue;236pRasInfo->invGrayTable = bipriv->cData->pGrayInverseLutData;237pRasInfo->representsPrimaries = bipriv->cData->representsPrimaries;238}239}240241static void BufImg_Release(JNIEnv *env,242SurfaceDataOps *ops,243SurfaceDataRasInfo *pRasInfo)244{245BufImgSDOps *bisdo = (BufImgSDOps *)ops;246BufImgRIPrivate *bipriv = (BufImgRIPrivate *) &(pRasInfo->priv);247248if (bipriv->base != NULL) {249jint mode = (((bipriv->lockFlags & (SD_LOCK_WRITE)) != 0)250? 0 : JNI_ABORT);251(*env)->ReleasePrimitiveArrayCritical(env, bisdo->array,252bipriv->base, mode);253}254if (bipriv->lutbase != NULL) {255(*env)->ReleasePrimitiveArrayCritical(env, bisdo->lutarray,256bipriv->lutbase, JNI_ABORT);257}258}259260static int calculatePrimaryColorsApproximation(int* cmap, unsigned char* cube, int cube_size) {261int i, j, k;262int index, value, color;263// values calculated from cmap264int r, g, b;265// maximum positive/negative variation allowed for r, g, b values for primary colors266int delta = 5;267// get the primary color cmap indices from corner of inverse color table268for (i = 0; i < cube_size; i += (cube_size - 1)) {269for (j = 0; j < cube_size; j += (cube_size - 1)) {270for (k = 0; k < cube_size; k += (cube_size - 1)) {271// calculate inverse color table index272index = i + cube_size * (j + cube_size * k);273// get value present in corners of inverse color table274value = cube[index];275// use the corner values as index for cmap276color = cmap[value];277// extract r,g,b values from cmap value278r = ((color) >> 16) & 0xff;279g = ((color) >> 8) & 0xff;280b = color & 0xff;281/*282* If i/j/k value is 0 optimum value of b/g/r should be 0 but we allow283* maximum positive variation of 5. If i/j/k value is 31 optimum value284* of b/g/r should be 255 but we allow maximum negative variation of 5.285*/286if (i == 0) {287if (b > delta)288return 0;289} else {290if (b < (255 - delta))291return 0;292}293if (j == 0) {294if (g > delta)295return 0;296} else {297if (g < (255 - delta))298return 0;299}300if (k == 0) {301if (r > delta)302return 0;303} else {304if (r < (255 - delta))305return 0;306}307}308}309}310return 1;311}312313static ColorData *BufImg_SetupICM(JNIEnv *env,314BufImgSDOps *bisdo)315{316ColorData *cData = NULL;317jobject colorData;318319if (JNU_IsNull(env, bisdo->icm)) {320return (ColorData *) NULL;321}322323colorData = (*env)->GetObjectField(env, bisdo->icm, colorDataID);324325if (JNU_IsNull(env, colorData)) {326if (JNU_IsNull(env, clsICMCD)) {327// we are unable to create a wrapper object328return (ColorData*)NULL;329}330} else {331cData = (ColorData*)JNU_GetLongFieldAsPtr(env, colorData, pDataID);332}333334if (cData != NULL) {335return cData;336}337338cData = (ColorData*)calloc(1, sizeof(ColorData));339340if (cData != NULL) {341jboolean allGray342= (*env)->GetBooleanField(env, bisdo->icm, allGrayID);343int *pRgb = (int *)344((*env)->GetPrimitiveArrayCritical(env, bisdo->lutarray, NULL));345346if (pRgb == NULL) {347free(cData);348return (ColorData*)NULL;349}350351cData->img_clr_tbl = initCubemap(pRgb, bisdo->lutsize, 32);352if (cData->img_clr_tbl == NULL) {353(*env)->ReleasePrimitiveArrayCritical(env, bisdo->lutarray, pRgb, JNI_ABORT);354free(cData);355return (ColorData*)NULL;356}357cData->representsPrimaries = calculatePrimaryColorsApproximation(pRgb, cData->img_clr_tbl, 32);358if (allGray == JNI_TRUE) {359initInverseGrayLut(pRgb, bisdo->lutsize, cData);360}361(*env)->ReleasePrimitiveArrayCritical(env, bisdo->lutarray, pRgb,362JNI_ABORT);363364initDitherTables(cData);365366if (JNU_IsNull(env, colorData)) {367jlong pData = ptr_to_jlong(cData);368colorData = (*env)->NewObjectA(env, clsICMCD, initICMCDmID, (jvalue *)&pData);369370if ((*env)->ExceptionCheck(env))371{372free(cData);373return (ColorData*)NULL;374}375376(*env)->SetObjectField(env, bisdo->icm, colorDataID, colorData);377Disposer_AddRecord(env, colorData, BufImg_Dispose_ICMColorData, pData);378}379}380381return cData;382}383384385