0N/A/*
3261N/A * Copyright (c) 1999, 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
430N/A#include "sun_java2d_windows_GDIWindowSurfaceData.h"
0N/A
430N/A#include "GDIWindowSurfaceData.h"
0N/A#include "GraphicsPrimitiveMgr.h"
0N/A#include "Region.h"
0N/A#include "Disposer.h"
0N/A#include "WindowsFlags.h"
0N/A#include "awt_Component.h"
0N/A#include "awt_Palette.h"
0N/A#include "awt_Win32GraphicsDevice.h"
0N/A#include "gdefs.h"
0N/A#include "Trace.h"
0N/A#include "Devices.h"
0N/A
0N/A#include "jni_util.h"
0N/A
430N/Astatic LockFunc GDIWinSD_Lock;
430N/Astatic GetRasInfoFunc GDIWinSD_GetRasInfo;
430N/Astatic UnlockFunc GDIWinSD_Unlock;
430N/Astatic DisposeFunc GDIWinSD_Dispose;
430N/Astatic SetupFunc GDIWinSD_Setup;
430N/Astatic GetDCFunc GDIWinSD_GetDC;
430N/Astatic ReleaseDCFunc GDIWinSD_ReleaseDC;
430N/Astatic InvalidateSDFunc GDIWinSD_InvalidateSD;
0N/A
0N/Astatic HBRUSH nullbrush;
0N/Astatic HPEN nullpen;
0N/A
0N/Astatic jclass xorCompClass;
0N/A
0N/Astatic jboolean beingShutdown = JNI_FALSE;
3174N/Astatic volatile LONG timeStamp = 0;
0N/Aextern CriticalSection windowMoveLock;
0N/A
0N/Aextern "C"
0N/A{
0N/AGeneralDisposeFunc DisposeThreadGraphicsInfo;
0N/Ajobject JNI_GetCurrentThread(JNIEnv *env);
0N/Aint threadInfoIndex = TLS_OUT_OF_INDEXES;
0N/A
0N/Astatic jclass threadClass = NULL;
0N/Astatic jmethodID currentThreadMethodID = NULL;
0N/A
430N/Avoid SetupThreadGraphicsInfo(JNIEnv *env, GDIWinSDOps *wsdo) {
0N/A J2dTraceLn(J2D_TRACE_INFO, "SetupThreadGraphicsInfo");
0N/A
0N/A // REMIND: handle error when creation fails
0N/A ThreadGraphicsInfo *info =
0N/A (ThreadGraphicsInfo*)TlsGetValue(threadInfoIndex);
0N/A if (info == NULL) {
0N/A info = new ThreadGraphicsInfo;
0N/A ZeroMemory(info, sizeof(ThreadGraphicsInfo));
0N/A TlsSetValue(threadInfoIndex, (LPVOID)info);
0N/A J2dTraceLn2(J2D_TRACE_VERBOSE,
0N/A " current batch limit for for thread 0x%x is %d",
0N/A GetCurrentThreadId(), ::GdiGetBatchLimit());
0N/A J2dTraceLn(J2D_TRACE_VERBOSE, " setting to the limit to 1");
0N/A // Fix for bug 4374079
0N/A ::GdiSetBatchLimit(1);
0N/A
0N/A Disposer_AddRecord(env, JNI_GetCurrentThread(env),
0N/A DisposeThreadGraphicsInfo,
0N/A ptr_to_jlong(info));
0N/A }
0N/A
0N/A HDC oldhDC = info->hDC;
0N/A // the hDC is NULL for offscreen surfaces - we don't store it
0N/A // in TLS as it must be created new every time.
3174N/A
3174N/A if( ((oldhDC == NULL) && wsdo->window != NULL) ||
3174N/A (info->wsdo != wsdo) ||
3174N/A (info->wsdoTimeStamp != wsdo->timeStamp) )
3174N/A {
0N/A
0N/A // Init graphics state, either because this is our first time
0N/A // using it in this thread or because this thread is now
0N/A // dealing with a different window than it was last time.
0N/A
3174N/A //check extra condition:
3174N/A //(info->wsdoTimeStamp != wsdo->timeStamp).
3174N/A //Checking memory addresses (info->wsdo != wsdo) will not detect
3174N/A //that wsdo points to a newly allocated structure in case
3174N/A //that structure just got allocated at a "recycled" memory location
3174N/A //which previously was pointed by info->wsdo
3174N/A //see bug# 6859086
3174N/A
0N/A // Release cached DC. We use deferred DC releasing mechanism because
0N/A // the DC is associated with cached wsdo and component peer,
0N/A // which may've been disposed by this time, and we have
0N/A // no means of checking against it.
0N/A if (oldhDC != NULL) {
0N/A MoveDCToPassiveList(oldhDC);
0N/A info->hDC = NULL;
0N/A }
0N/A
0N/A if (wsdo->window != NULL){
0N/A HDC hDC;
0N/A // This is a window surface
0N/A // First, init the HDC object
430N/A AwtComponent *comp = GDIWindowSurfaceData_GetComp(env, wsdo);
0N/A if (comp == NULL) {
0N/A return;
0N/A }
0N/A hDC = comp->GetDCFromComponent();
0N/A if (hDC != NULL) {
0N/A ::SelectObject(hDC, nullbrush);
0N/A ::SelectObject(hDC, nullpen);
0N/A ::SelectClipRgn(hDC, (HRGN) NULL);
0N/A ::SetROP2(hDC, R2_COPYPEN);
0N/A wsdo->device->SelectPalette(hDC);
0N/A // Note that on NT4 we don't need to do a realize here: the
0N/A // palette-sharing takes care of color issues for us. But
0N/A // on win98 if we don't realize a DC's palette, that
0N/A // palette does not appear to have correct access to the
0N/A // logical->system mapping.
0N/A wsdo->device->RealizePalette(hDC);
0N/A
0N/A // Second, init the rest of the graphics state
0N/A ::GetClientRect(wsdo->window, &info->bounds);
0N/A // Make window-relative from client-relative
0N/A ::OffsetRect(&info->bounds, wsdo->insets.left, wsdo->insets.top);
0N/A //Likewise, translate GDI calls from client-relative to window-relative
0N/A ::OffsetViewportOrgEx(hDC, -wsdo->insets.left, -wsdo->insets.top, NULL);
0N/A }
0N/A
0N/A // Finally, set these new values in the info for this thread
0N/A info->hDC = hDC;
0N/A }
0N/A
0N/A // cached brush and pen are not associated with any DC, and can be
0N/A // reused, but have to set type to 0 to indicate that no pen/brush
0N/A // were set to the new hdc
0N/A info->type = 0;
0N/A
0N/A if (info->clip != NULL) {
0N/A env->DeleteWeakGlobalRef(info->clip);
0N/A }
0N/A info->clip = NULL;
0N/A
0N/A if (info->comp != NULL) {
0N/A env->DeleteWeakGlobalRef(info->comp);
0N/A }
0N/A info->comp = NULL;
0N/A
0N/A info->xorcolor = 0;
0N/A info->patrop = PATCOPY;
0N/A
3174N/A //store the address and time stamp of newly allocated GDIWinSDOps structure
0N/A info->wsdo = wsdo;
3174N/A info->wsdoTimeStamp = wsdo->timeStamp;
0N/A }
0N/A}
0N/A
0N/A/**
0N/A * Releases native data stored in Thread local storage.
0N/A * Called by the Disposer when the associated thread dies.
0N/A */
0N/Avoid DisposeThreadGraphicsInfo(JNIEnv *env, jlong tgi) {
0N/A J2dTraceLn(J2D_TRACE_INFO, "DisposeThreadGraphicsInfo");
0N/A ThreadGraphicsInfo *info = (ThreadGraphicsInfo*)jlong_to_ptr(tgi);
0N/A if (info != NULL) {
0N/A if (info->hDC != NULL) {
0N/A // move the DC from the active dcs list to
0N/A // the passive dc list to be released later
0N/A MoveDCToPassiveList(info->hDC);
0N/A }
0N/A
0N/A if (info->clip != NULL) {
0N/A env->DeleteWeakGlobalRef(info->clip);
0N/A }
0N/A if (info->comp != NULL) {
0N/A env->DeleteWeakGlobalRef(info->comp);
0N/A }
0N/A
0N/A if (info->brush != NULL) {
0N/A info->brush->Release();
0N/A }
0N/A if (info->pen != NULL) {
0N/A info->pen->Release();
0N/A }
0N/A
0N/A delete info;
0N/A }
0N/A}
0N/A
0N/A/**
0N/A * Returns current Thread object.
0N/A */
0N/Ajobject
0N/AJNI_GetCurrentThread(JNIEnv *env) {
0N/A return env->CallStaticObjectMethod(threadClass, currentThreadMethodID);
0N/A} /* JNI_GetCurrentThread() */
0N/A
0N/A/**
0N/A * Return the data associated with this thread.
0N/A * NOTE: This function assumes that the SetupThreadGraphicsInfo()
0N/A * function has already been called for this situation (thread,
0N/A * window, etc.), so we can assume that the thread info contains
430N/A * a valid hDC. This should usually be the case since GDIWinSD_Setup
0N/A * is called as part of the GetOps() process.
0N/A */
0N/AThreadGraphicsInfo *GetThreadGraphicsInfo(JNIEnv *env,
430N/A GDIWinSDOps *wsdo) {
0N/A return (ThreadGraphicsInfo*)TlsGetValue(threadInfoIndex);
0N/A}
0N/A
430N/A__inline HDC GetThreadDC(JNIEnv *env, GDIWinSDOps *wsdo) {
0N/A ThreadGraphicsInfo *info =
0N/A (ThreadGraphicsInfo *)GetThreadGraphicsInfo(env, wsdo);
0N/A if (!info) {
0N/A return (HDC) NULL;
0N/A }
0N/A return info->hDC;
0N/A}
0N/A
0N/A} // extern "C"
0N/A
0N/A/**
0N/A * This source file contains support code for loops using the
0N/A * SurfaceData interface to talk to a Win32 drawable from native
0N/A * code.
0N/A */
0N/A
430N/Astatic BOOL GDIWinSD_CheckMonitorArea(GDIWinSDOps *wsdo,
0N/A SurfaceDataBounds *bounds,
0N/A HDC hDC)
0N/A{
0N/A HWND hW = wsdo->window;
0N/A BOOL retCode = TRUE;
0N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_CheckMonitorArea");
0N/A int numScreens;
0N/A {
0N/A Devices::InstanceAccess devices;
0N/A numScreens = devices->GetNumDevices();
0N/A }
0N/A if( numScreens > 1 ) {
0N/A
862N/A LPMONITORINFO miInfo;
0N/A RECT rSect ={0,0,0,0};
0N/A RECT rView ={bounds->x1, bounds->y1, bounds->x2, bounds->y2};
0N/A retCode = FALSE;
0N/A
0N/A miInfo = wsdo->device->GetMonitorInfo();
0N/A
0N/A POINT ptOrig = {0, 0};
0N/A ::ClientToScreen(hW, &ptOrig);
0N/A ::OffsetRect(&rView,
0N/A (ptOrig.x), (ptOrig.y));
0N/A
862N/A ::IntersectRect(&rSect,&rView,&(miInfo->rcMonitor));
0N/A
0N/A if( FALSE == ::IsRectEmpty(&rSect) ) {
0N/A if( TRUE == ::EqualRect(&rSect,&rView) ) {
0N/A retCode = TRUE;
0N/A }
0N/A }
0N/A }
0N/A return retCode;
0N/A}
0N/A
0N/Aextern "C" {
0N/A
0N/Avoid
0N/AinitThreadInfoIndex()
0N/A{
0N/A if (threadInfoIndex == TLS_OUT_OF_INDEXES) {
0N/A threadInfoIndex = TlsAlloc();
0N/A }
0N/A}
0N/A
430N/A
430N/A/**
430N/A * Utility function to make sure that native and java-level
430N/A * surface depths are matched. They can be mismatched when display-depths
430N/A * change, either between the creation of the Java surfaceData structure
430N/A * and the native ddraw surface, or later when a surface is automatically
430N/A * adjusted to be the new display depth (even if it was created in a different
430N/A * depth to begin with)
430N/A */
430N/ABOOL SurfaceDepthsCompatible(int javaDepth, int nativeDepth)
430N/A{
430N/A if (nativeDepth != javaDepth) {
430N/A switch (nativeDepth) {
430N/A case 0: // Error condition: something is wrong with the surface
430N/A case 8:
430N/A case 24:
430N/A // Java and native surface depths should match exactly for
430N/A // these cases
430N/A return FALSE;
430N/A break;
430N/A case 16:
430N/A // Java surfaceData should be 15 or 16 bits
430N/A if (javaDepth < 15 || javaDepth > 16) {
430N/A return FALSE;
430N/A }
430N/A break;
430N/A case 32:
430N/A // Could have this native depth for either 24- or 32-bit
430N/A // Java surfaceData
430N/A if (javaDepth != 24 && javaDepth != 32) {
430N/A return FALSE;
430N/A }
430N/A break;
430N/A default:
430N/A // should not get here, but if we do something is odd, so
430N/A // just register a failure
430N/A return FALSE;
430N/A }
430N/A }
430N/A return TRUE;
430N/A}
430N/A
430N/A
0N/A/*
430N/A * Class: sun_java2d_windows_GDIWindowSurfaceData
0N/A * Method: initIDs
0N/A * Signature: ()V
0N/A */
0N/AJNIEXPORT void JNICALL
430N/AJava_sun_java2d_windows_GDIWindowSurfaceData_initIDs(JNIEnv *env, jclass wsd,
0N/A jclass XORComp)
0N/A{
0N/A jclass tc;
430N/A J2dTraceLn(J2D_TRACE_INFO, "GDIWindowSurfaceData_initIDs");
0N/A nullbrush = (HBRUSH) ::GetStockObject(NULL_BRUSH);
0N/A nullpen = (HPEN) ::GetStockObject(NULL_PEN);
0N/A
0N/A initThreadInfoIndex();
0N/A
0N/A xorCompClass = (jclass)env->NewGlobalRef(XORComp);
0N/A
0N/A tc = env->FindClass("java/lang/Thread");
0N/A DASSERT(tc != NULL);
0N/A threadClass = (jclass)env->NewGlobalRef(tc);
0N/A DASSERT(threadClass != NULL);
0N/A currentThreadMethodID =
0N/A env->GetStaticMethodID(threadClass,
0N/A "currentThread", "()Ljava/lang/Thread;");
0N/A DASSERT(currentThreadMethodID != NULL);
0N/A}
0N/A
0N/A/*
430N/A * Class: sun_java2d_windows_GDIWindowSurfaceData
0N/A * Method: initOps
0N/A * Signature: (Ljava/lang/Object;IIIIII)V
0N/A */
0N/AJNIEXPORT void JNICALL
430N/AJava_sun_java2d_windows_GDIWindowSurfaceData_initOps(JNIEnv *env, jobject wsd,
0N/A jobject peer, jint depth,
0N/A jint redMask, jint greenMask,
430N/A jint blueMask, jint screen)
0N/A{
430N/A J2dTraceLn(J2D_TRACE_INFO, "GDIWindowSurfaceData_initOps");
430N/A GDIWinSDOps *wsdo = (GDIWinSDOps *)SurfaceData_InitOps(env, wsd, sizeof(GDIWinSDOps));
2514N/A if (wsdo == NULL) {
2514N/A JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
2514N/A return;
2514N/A }
3174N/A wsdo->timeStamp = InterlockedIncrement(&timeStamp); //creation time stamp
430N/A wsdo->sdOps.Lock = GDIWinSD_Lock;
430N/A wsdo->sdOps.GetRasInfo = GDIWinSD_GetRasInfo;
430N/A wsdo->sdOps.Unlock = GDIWinSD_Unlock;
430N/A wsdo->sdOps.Dispose = GDIWinSD_Dispose;
430N/A wsdo->sdOps.Setup = GDIWinSD_Setup;
430N/A wsdo->GetDC = GDIWinSD_GetDC;
430N/A wsdo->ReleaseDC = GDIWinSD_ReleaseDC;
430N/A wsdo->InvalidateSD = GDIWinSD_InvalidateSD;
0N/A wsdo->invalid = JNI_FALSE;
0N/A wsdo->lockType = WIN32SD_LOCK_UNLOCKED;
0N/A wsdo->peer = env->NewWeakGlobalRef(peer);
0N/A wsdo->depth = depth;
0N/A wsdo->pixelMasks[0] = redMask;
0N/A wsdo->pixelMasks[1] = greenMask;
0N/A wsdo->pixelMasks[2] = blueMask;
0N/A // Init the DIB pixelStride and pixel masks according to
0N/A // the pixel depth. In the 8-bit case, there are no
0N/A // masks as a palette DIB is used instead. Likewise
0N/A // in the 24-bit case, Windows doesn't expect the masks
0N/A switch (depth) {
0N/A case 8:
0N/A wsdo->pixelStride = 1;
0N/A break;
0N/A case 15: //555
0N/A wsdo->pixelStride = 2;
0N/A break;
0N/A case 16: //565
0N/A wsdo->pixelStride = 2;
0N/A break;
0N/A case 24:
0N/A wsdo->pixelStride = 3;
0N/A break;
0N/A case 32: //888
0N/A wsdo->pixelStride = 4;
0N/A break;
0N/A }
430N/A // GDIWindowSurfaceData_GetWindow will throw NullPointerException
0N/A // if wsdo->window is NULL
430N/A wsdo->window = GDIWindowSurfaceData_GetWindow(env, wsdo);
0N/A J2dTraceLn2(J2D_TRACE_VERBOSE, " wsdo=0x%x wsdo->window=0x%x",
0N/A wsdo, wsdo->window);
0N/A
0N/A {
0N/A Devices::InstanceAccess devices;
0N/A wsdo->device = devices->GetDeviceReference(screen, FALSE);
0N/A }
0N/A if (wsdo->device == NULL ||
430N/A !SurfaceDepthsCompatible(depth, wsdo->device->GetBitDepth()))
0N/A {
0N/A if (wsdo->device != NULL) {
0N/A J2dTraceLn2(J2D_TRACE_WARNING,
430N/A "GDIWindowSurfaceData_initOps: Surface depth mismatch: "\
0N/A "wsdo->depth=%d device depth=%d. Surface invalidated.",
0N/A wsdo->depth, wsdo->device->GetBitDepth());
0N/A } else {
0N/A J2dTraceLn1(J2D_TRACE_WARNING,
430N/A "GDIWindowSurfaceData_initOps: Incorrect "\
0N/A "screen number (screen=%d). Surface invalidated.",
0N/A screen);
0N/A }
0N/A
0N/A wsdo->invalid = JNI_TRUE;
0N/A }
0N/A wsdo->surfaceLock = new CriticalSection();
0N/A wsdo->bitmap = NULL;
0N/A wsdo->bmdc = NULL;
0N/A wsdo->bmCopyToScreen = FALSE;
0N/A}
0N/A
430N/AJNIEXPORT GDIWinSDOps * JNICALL
430N/AGDIWindowSurfaceData_GetOps(JNIEnv *env, jobject sData)
0N/A{
0N/A SurfaceDataOps *ops = SurfaceData_GetOps(env, sData);
0N/A // REMIND: There was originally a condition check here to make sure
430N/A // that we were really dealing with a GDIWindowSurfaceData object, but
0N/A // it did not allow for the existence of other win32-accelerated
0N/A // surface data objects (e.g., Win32OffScreenSurfaceData). I've
0N/A // removed the check for now, but we should replace it with another,
0N/A // more general check against Win32-related surfaces.
430N/A return (GDIWinSDOps *) ops;
0N/A}
0N/A
430N/AJNIEXPORT GDIWinSDOps * JNICALL
430N/AGDIWindowSurfaceData_GetOpsNoSetup(JNIEnv *env, jobject sData)
0N/A{
0N/A // use the 'no setup' version of GetOps
0N/A SurfaceDataOps *ops = SurfaceData_GetOpsNoSetup(env, sData);
430N/A return (GDIWinSDOps *) ops;
0N/A}
0N/A
0N/AJNIEXPORT AwtComponent * JNICALL
430N/AGDIWindowSurfaceData_GetComp(JNIEnv *env, GDIWinSDOps *wsdo)
0N/A{
0N/A PDATA pData;
0N/A jobject localObj = env->NewLocalRef(wsdo->peer);
0N/A
0N/A if (localObj == NULL || (pData = JNI_GET_PDATA(localObj)) == NULL) {
0N/A J2dTraceLn1(J2D_TRACE_WARNING,
430N/A "GDIWindowSurfaceData_GetComp: Null pData? pData=0x%x",
0N/A pData);
0N/A if (beingShutdown == JNI_TRUE) {
0N/A wsdo->invalid = JNI_TRUE;
0N/A return (AwtComponent *) NULL;
0N/A }
0N/A try {
0N/A AwtToolkit::GetInstance().VerifyActive();
0N/A } catch (awt_toolkit_shutdown&) {
0N/A beingShutdown = JNI_TRUE;
0N/A wsdo->invalid = JNI_TRUE;
0N/A return (AwtComponent *) NULL;
0N/A }
0N/A if (wsdo->invalid == JNI_TRUE) {
0N/A SurfaceData_ThrowInvalidPipeException(env,
430N/A "GDIWindowSurfaceData: bounds changed");
0N/A } else {
0N/A JNU_ThrowNullPointerException(env, "component argument pData");
0N/A }
0N/A return (AwtComponent *) NULL;
0N/A }
0N/A return static_cast<AwtComponent*>(pData);
0N/A}
0N/A
0N/AJNIEXPORT HWND JNICALL
430N/AGDIWindowSurfaceData_GetWindow(JNIEnv *env, GDIWinSDOps *wsdo)
0N/A{
0N/A HWND window = wsdo->window;
0N/A
0N/A if (window == (HWND) NULL) {
430N/A AwtComponent *comp = GDIWindowSurfaceData_GetComp(env, wsdo);
0N/A if (comp == NULL) {
0N/A J2dTraceLn(J2D_TRACE_WARNING,
430N/A "GDIWindowSurfaceData_GetWindow: null component");
0N/A return (HWND) NULL;
0N/A }
0N/A comp->GetInsets(&wsdo->insets);
0N/A window = comp->GetHWnd();
0N/A if (::IsWindow(window) == FALSE) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
430N/A "GDIWindowSurfaceData_GetWindow: disposed component");
0N/A JNU_ThrowNullPointerException(env, "disposed component");
0N/A return (HWND) NULL;
0N/A }
0N/A wsdo->window = window;
0N/A }
0N/A
0N/A return window;
0N/A}
0N/A
0N/A} /* extern "C" */
0N/A
430N/Astatic jboolean GDIWinSD_SimpleClip(JNIEnv *env, GDIWinSDOps *wsdo,
0N/A SurfaceDataBounds *bounds,
0N/A HDC hDC)
0N/A{
0N/A RECT rClip;
0N/A
430N/A J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_SimpleClip");
0N/A if (hDC == NULL) {
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A int nComplexity = ::GetClipBox(hDC, &rClip);
0N/A
0N/A switch (nComplexity) {
0N/A case COMPLEXREGION:
0N/A {
0N/A J2dTraceLn(J2D_TRACE_VERBOSE,
0N/A " complex clipping region");
0N/A // if complex user/system clip, more detailed testing required
0N/A // check to see if the view itself has a complex clip.
0N/A // ::GetClipBox is only API which returns overlapped window status
0N/A // so we set the rView as our clip, and then see if resulting
0N/A // clip is complex.
0N/A // Only other way to figure this out would be to walk the
0N/A // overlapping windows (no API to get the actual visible clip
0N/A // list). Then we'd still have to merge that info with the
0N/A // clip region for the dc (if it exists).
0N/A // REMIND: we can cache the CreateRectRgnIndirect result,
0N/A // and only override with ::SetRectRgn
0N/A
0N/A // First, create a region handle (need existing HRGN for
0N/A // the following call).
0N/A HRGN rgnSave = ::CreateRectRgn(0, 0, 0, 0);
0N/A int clipStatus = ::GetClipRgn(hDC, rgnSave);
0N/A if (-1 == clipStatus) {
0N/A J2dTraceLn(J2D_TRACE_WARNING,
430N/A "GDIWinSD_SimpleClip: failed due to clip status");
0N/A ::DeleteObject(rgnSave);
0N/A return JNI_FALSE;
0N/A }
0N/A HRGN rgnBounds = ::CreateRectRgn(
0N/A bounds->x1 - wsdo->insets.left,
0N/A bounds->y1 - wsdo->insets.top,
0N/A bounds->x2 - wsdo->insets.left,
0N/A bounds->y2 - wsdo->insets.top);
0N/A ::SelectClipRgn(hDC, rgnBounds);
0N/A nComplexity = ::GetClipBox(hDC, &rClip);
0N/A ::SelectClipRgn(hDC, clipStatus? rgnSave: NULL);
0N/A ::DeleteObject(rgnSave);
0N/A ::DeleteObject(rgnBounds);
0N/A
0N/A // Now, test the new clip box. If it's still not a
0N/A // SIMPLE region, then our bounds must intersect part of
0N/A // the clipping article
0N/A if (SIMPLEREGION != nComplexity) {
0N/A J2dTraceLn(J2D_TRACE_WARNING,
430N/A "GDIWinSD_SimpleClip: failed due to complexity");
0N/A return JNI_FALSE;
0N/A }
0N/A }
0N/A // NOTE: No break here - we want to fall through into the
0N/A // SIMPLE case, adjust our bounds by the new rClip rect
0N/A // and make sure that our locking bounds are not empty.
0N/A case SIMPLEREGION:
0N/A J2dTraceLn(J2D_TRACE_VERBOSE, " simple clipping region");
0N/A // Constrain the bounds to the given clip box
0N/A if (bounds->x1 < rClip.left) {
0N/A bounds->x1 = rClip.left;
0N/A }
0N/A if (bounds->y1 < rClip.top) {
0N/A bounds->y1 = rClip.top;
0N/A }
0N/A if (bounds->x2 > rClip.right) {
0N/A bounds->x2 = rClip.right;
0N/A }
0N/A if (bounds->y2 > rClip.bottom) {
0N/A bounds->y2 = rClip.bottom;
0N/A }
0N/A // If the bounds are 0 or negative, then the bounds have
0N/A // been obscured by the clip box, so return FALSE
0N/A if ((bounds->x2 <= bounds->x1) ||
0N/A (bounds->y2 <= bounds->y1)) {
0N/A // REMIND: We should probably do something different here
0N/A // instead of simply returning FALSE. Since the bounds are
0N/A // empty we won't end up drawing anything, so why spend the
0N/A // effort of returning false and having GDI do a LOCK_BY_DIB?
0N/A // Perhaps we need a new lock code that will indicate that we
0N/A // shouldn't bother drawing?
0N/A J2dTraceLn(J2D_TRACE_WARNING,
430N/A "GDIWinSD_SimpleClip: failed due to empty bounds");
0N/A return JNI_FALSE;
0N/A }
0N/A break;
0N/A case NULLREGION:
0N/A case ERROR:
0N/A default:
0N/A J2dTraceLn1(J2D_TRACE_ERROR,
430N/A "GDIWinSD_SimpleClip: failed due to incorrect complexity=%d",
0N/A nComplexity);
0N/A return JNI_FALSE;
0N/A }
0N/A
0N/A return JNI_TRUE;
0N/A}
0N/A
430N/Astatic jint GDIWinSD_Lock(JNIEnv *env,
0N/A SurfaceDataOps *ops,
0N/A SurfaceDataRasInfo *pRasInfo,
0N/A jint lockflags)
0N/A{
430N/A GDIWinSDOps *wsdo = (GDIWinSDOps *) ops;
0N/A int ret = SD_SUCCESS;
0N/A HDC hDC;
430N/A J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_Lock");
0N/A
0N/A /* This surfaceLock replaces an earlier implementation which used a
0N/A monitor associated with the peer. That implementation was prone
0N/A to deadlock problems, so it was replaced by a lock that does not
0N/A have dependencies outside of this thread or object.
0N/A However, this lock doesn't necessarily do all that we want.
0N/A For example, a user may issue a call which results in a DIB lock
0N/A and another call which results in a DDraw Blt. We can't guarantee
0N/A what order these operations happen in (they are driver and
0N/A video-card dependent), so locking around the issue of either of
0N/A those calls won't necessarily guarantee a particular result.
0N/A The real solution might be to move away from mixing our
0N/A rendering API's. That is, if we only used DDraw, then we could
0N/A guarantee that all rendering operations would happen in a given
0N/A order. Similarly for GDI. But by mixing them, we leave our
0N/A code at the mercy of driver bugs.*/
0N/A wsdo->surfaceLock->Enter();
0N/A if (wsdo->invalid == JNI_TRUE) {
430N/A J2dTraceLn(J2D_TRACE_WARNING, "GDIWinSD_Lock: surface is invalid");
0N/A wsdo->surfaceLock->Leave();
0N/A if (beingShutdown != JNI_TRUE) {
0N/A SurfaceData_ThrowInvalidPipeException(env,
430N/A "GDIWindowSurfaceData: bounds changed");
0N/A }
0N/A return SD_FAILURE;
0N/A }
0N/A if (wsdo->lockType != WIN32SD_LOCK_UNLOCKED) {
0N/A wsdo->surfaceLock->Leave();
0N/A if (!safe_ExceptionOccurred(env)) {
0N/A JNU_ThrowInternalError(env, "Win32 LockRasData cannot nest locks");
0N/A }
0N/A return SD_FAILURE;
0N/A }
0N/A
0N/A hDC = wsdo->GetDC(env, wsdo, 0, NULL, NULL, NULL, 0);
0N/A if (hDC == NULL) {
0N/A wsdo->surfaceLock->Leave();
0N/A if (beingShutdown != JNI_TRUE) {
0N/A JNU_ThrowNullPointerException(env, "HDC for component");
0N/A }
0N/A return SD_FAILURE;
0N/A }
0N/A
0N/A if (lockflags & SD_LOCK_RD_WR) {
0N/A // Do an initial clip to the client region of the window
0N/A RECT crect;
0N/A ::GetClientRect(wsdo->window, &crect);
0N/A
0N/A // Translate to window coords
0N/A crect.left += wsdo->insets.left;
0N/A crect.top += wsdo->insets.top;
0N/A crect.right += wsdo->insets.left;
0N/A crect.bottom += wsdo->insets.top;
0N/A
0N/A SurfaceDataBounds *bounds = &pRasInfo->bounds;
0N/A
0N/A if (bounds->x1 < crect.left) {
0N/A bounds->x1 = crect.left;
0N/A }
0N/A if (bounds->y1 < crect.top) {
0N/A bounds->y1 = crect.top;
0N/A }
0N/A if (bounds->x2 > crect.right) {
0N/A bounds->x2 = crect.right;
0N/A }
0N/A if (bounds->y2 > crect.bottom) {
0N/A bounds->y2 = crect.bottom;
0N/A }
0N/A
430N/A if (bounds->x2 > bounds->x1 && bounds->y2 > bounds->y1) {
430N/A wsdo->lockType = WIN32SD_LOCK_BY_DIB;
430N/A if (lockflags & SD_LOCK_FASTEST) {
430N/A ret = SD_SLOWLOCK;
0N/A }
430N/A J2dTraceLn(J2D_TRACE_VERBOSE, " locked by DIB");
0N/A } else {
0N/A wsdo->ReleaseDC(env, wsdo, hDC);
430N/A wsdo->lockType = WIN32SD_LOCK_UNLOCKED;
430N/A wsdo->surfaceLock->Leave();
430N/A ret = SD_FAILURE;
430N/A J2dTraceLn(J2D_TRACE_ERROR,
430N/A "GDIWinSD_Lock: error locking by DIB");
0N/A }
0N/A } else {
430N/A J2dTraceLn(J2D_TRACE_VERBOSE, "GDIWinSD_Lock: surface wasn't locked");
0N/A /* They didn't lock for anything - we won't give them anything */
0N/A wsdo->ReleaseDC(env, wsdo, hDC);
0N/A wsdo->lockType = WIN32SD_LOCK_UNLOCKED;
0N/A wsdo->surfaceLock->Leave();
0N/A ret = SD_FAILURE;
0N/A }
0N/A
0N/A wsdo->lockFlags = lockflags;
0N/A return ret;
0N/A}
0N/A
430N/Astatic void GDIWinSD_GetRasInfo(JNIEnv *env,
0N/A SurfaceDataOps *ops,
0N/A SurfaceDataRasInfo *pRasInfo)
0N/A{
430N/A GDIWinSDOps *wsdo = (GDIWinSDOps *) ops;
0N/A jint lockflags = wsdo->lockFlags;
430N/A J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_GetRasInfo");
0N/A HDC hDC = GetThreadDC(env, wsdo);
0N/A
0N/A if (wsdo->lockType == WIN32SD_LOCK_UNLOCKED) {
0N/A memset(pRasInfo, 0, sizeof(*pRasInfo));
0N/A return;
0N/A }
0N/A
430N/A if (wsdo->lockType == WIN32SD_LOCK_BY_DIB) {
0N/A int x, y, w, h;
0N/A int pixelStride = wsdo->pixelStride;
0N/A // do not subtract insets from x,y as we take care of it in SD_GetDC
0N/A x = pRasInfo->bounds.x1;
0N/A y = pRasInfo->bounds.y1;
0N/A w = pRasInfo->bounds.x2 - x;
0N/A h = pRasInfo->bounds.y2 - y;
0N/A
0N/A struct tagBitmapheader {
0N/A BITMAPINFOHEADER bmiHeader;
0N/A union {
0N/A DWORD dwMasks[3];
0N/A RGBQUAD palette[256];
0N/A } colors;
0N/A } bmi;
0N/A
0N/A // Need to create bitmap if we don't have one already or
0N/A // if the existing one is not large enough for this operation
0N/A // or if we are in 8 bpp display mode (because we need to
0N/A // make sure that the latest palette info gets loaded into
0N/A // the bitmap)
0N/A // REMIND: we should find some way to dynamically force bitmap
0N/A // recreation only when the palette changes
0N/A if (pixelStride == 1 || !wsdo->bitmap || (w > wsdo->bmWidth) ||
0N/A (h > wsdo->bmHeight))
0N/A {
0N/A if (wsdo->bitmap) {
0N/A // delete old objects
0N/A J2dTraceLn(J2D_TRACE_VERBOSE,
430N/A "GDIWinSD_GetRasInfo: recreating GDI bitmap");
0N/A if (wsdo->bmdc) { // should not be null
0N/A ::SelectObject(wsdo->bmdc, wsdo->oldmap);
0N/A ::DeleteDC(wsdo->bmdc);
0N/A wsdo->bmdc = 0;
0N/A }
0N/A ::DeleteObject(wsdo->bitmap);
0N/A wsdo->bitmap = 0;
0N/A }
0N/A bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
0N/A bmi.bmiHeader.biWidth = w;
0N/A bmi.bmiHeader.biHeight = -h;
0N/A wsdo->bmWidth = w;
0N/A wsdo->bmHeight = h;
0N/A bmi.bmiHeader.biPlanes = 1;
0N/A bmi.bmiHeader.biBitCount = pixelStride * 8;
0N/A // 1,3 byte use BI_RGB, 2,4 byte use BI_BITFIELD...
0N/A bmi.bmiHeader.biCompression =
0N/A (pixelStride & 1)
0N/A ? BI_RGB
0N/A : BI_BITFIELDS;
0N/A bmi.bmiHeader.biSizeImage = 0;
0N/A bmi.bmiHeader.biXPelsPerMeter = 0;
0N/A bmi.bmiHeader.biYPelsPerMeter = 0;
0N/A bmi.bmiHeader.biClrUsed = 0;
0N/A bmi.bmiHeader.biClrImportant = 0;
0N/A if (pixelStride == 1) {
0N/A // we can use systemEntries here because
0N/A // RGBQUAD is xRGB and systemEntries are stored as xRGB
0N/A memcpy(bmi.colors.palette, wsdo->device->GetSystemPaletteEntries(),
0N/A sizeof(bmi.colors.palette));
0N/A } else {
0N/A // For non-index cases, init the masks for the pixel depth
0N/A for (int i = 0; i < 3; i++) {
0N/A bmi.colors.dwMasks[i] = wsdo->pixelMasks[i];
0N/A }
0N/A }
0N/A
0N/A // REMIND: This would be better if moved to the Lock function
0N/A // so that errors could be dealt with.
0N/A wsdo->bitmap = ::CreateDIBSection(hDC, (BITMAPINFO *) &bmi,
0N/A DIB_RGB_COLORS, &wsdo->bmBuffer, NULL, 0);
0N/A if (wsdo->bitmap != 0) {
0N/A // scanStride is cached along with reuseable bitmap
0N/A // Round up to the next DWORD boundary
0N/A wsdo->bmScanStride = (wsdo->bmWidth * pixelStride + 3) & ~3;
0N/A wsdo->bmdc = ::CreateCompatibleDC(hDC);
0N/A if (wsdo->bmdc == 0) {
0N/A ::DeleteObject(wsdo->bitmap);
0N/A wsdo->bitmap = 0;
0N/A } else {
0N/A wsdo->oldmap = (HBITMAP) ::SelectObject(wsdo->bmdc,
0N/A wsdo->bitmap);
0N/A }
0N/A }
0N/A }
0N/A if (wsdo->bitmap != 0) {
0N/A if (lockflags & SD_LOCK_NEED_PIXELS) {
0N/A int ret = ::BitBlt(wsdo->bmdc, 0, 0, w, h,
0N/A hDC, x, y, SRCCOPY);
0N/A ::GdiFlush();
0N/A }
0N/A wsdo->x = x;
0N/A wsdo->y = y;
0N/A wsdo->w = w;
0N/A wsdo->h = h;
0N/A pRasInfo->rasBase = (char *)wsdo->bmBuffer - (x*pixelStride +
0N/A y*wsdo->bmScanStride);
0N/A pRasInfo->pixelStride = pixelStride;
0N/A pRasInfo->pixelBitOffset = 0;
0N/A pRasInfo->scanStride = wsdo->bmScanStride;
0N/A if (lockflags & SD_LOCK_WRITE) {
0N/A // If the user writes to the bitmap then we should
0N/A // copy the bitmap to the screen during Unlock
0N/A wsdo->bmCopyToScreen = TRUE;
0N/A }
0N/A } else {
0N/A pRasInfo->rasBase = NULL;
0N/A pRasInfo->pixelStride = 0;
0N/A pRasInfo->pixelBitOffset = 0;
0N/A pRasInfo->scanStride = 0;
0N/A }
0N/A } else {
0N/A /* They didn't lock for anything - we won't give them anything */
0N/A pRasInfo->rasBase = NULL;
0N/A pRasInfo->pixelStride = 0;
0N/A pRasInfo->pixelBitOffset = 0;
0N/A pRasInfo->scanStride = 0;
0N/A }
0N/A if (wsdo->lockFlags & SD_LOCK_LUT) {
0N/A pRasInfo->lutBase =
0N/A (long *) wsdo->device->GetSystemPaletteEntries();
0N/A pRasInfo->lutSize = 256;
0N/A } else {
0N/A pRasInfo->lutBase = NULL;
0N/A pRasInfo->lutSize = 0;
0N/A }
0N/A if (wsdo->lockFlags & SD_LOCK_INVCOLOR) {
0N/A pRasInfo->invColorTable = wsdo->device->GetSystemInverseLUT();
0N/A ColorData *cData = wsdo->device->GetColorData();
0N/A pRasInfo->redErrTable = cData->img_oda_red;
0N/A pRasInfo->grnErrTable = cData->img_oda_green;
0N/A pRasInfo->bluErrTable = cData->img_oda_blue;
0N/A } else {
0N/A pRasInfo->invColorTable = NULL;
0N/A pRasInfo->redErrTable = NULL;
0N/A pRasInfo->grnErrTable = NULL;
0N/A pRasInfo->bluErrTable = NULL;
0N/A }
0N/A if (wsdo->lockFlags & SD_LOCK_INVGRAY) {
0N/A pRasInfo->invGrayTable =
0N/A wsdo->device->GetColorData()->pGrayInverseLutData;
0N/A } else {
0N/A pRasInfo->invGrayTable = NULL;
0N/A }
0N/A}
0N/A
430N/Astatic void GDIWinSD_Setup(JNIEnv *env,
0N/A SurfaceDataOps *ops)
0N/A{
0N/A // Call SetupTGI to ensure that this thread already has a DC that is
0N/A // compatible with this window. This means that we won't be calling
0N/A // ::SendMessage(GETDC) in the middle of a lock procedure, which creates
0N/A // a potential deadlock situation.
0N/A // Note that calling SetupTGI here means that anybody needing a DC
0N/A // later in this rendering process need only call GetTGI, which
0N/A // assumes that the TGI structure is valid for this thread/window.
430N/A SetupThreadGraphicsInfo(env, (GDIWinSDOps*)ops);
0N/A}
0N/A
0N/A
430N/Astatic void GDIWinSD_Unlock(JNIEnv *env,
0N/A SurfaceDataOps *ops,
0N/A SurfaceDataRasInfo *pRasInfo)
0N/A{
430N/A GDIWinSDOps *wsdo = (GDIWinSDOps *) ops;
430N/A J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_Unlock");
0N/A HDC hDC = GetThreadDC(env, wsdo);
0N/A
0N/A if (wsdo->lockType == WIN32SD_LOCK_UNLOCKED) {
0N/A if (!safe_ExceptionOccurred(env)) {
0N/A JNU_ThrowInternalError(env,
0N/A "Unmatched unlock on Win32 SurfaceData");
0N/A }
0N/A return;
0N/A }
0N/A
430N/A if (wsdo->lockType == WIN32SD_LOCK_BY_DIB) {
0N/A if (wsdo->lockFlags & SD_LOCK_WRITE) {
0N/A J2dTraceLn(J2D_TRACE_VERBOSE,
430N/A "GDIWinSD_Unlock: do Blt of the bitmap");
0N/A if (wsdo->bmCopyToScreen && ::IsWindowVisible(wsdo->window)) {
0N/A // Don't bother copying to screen if our window has gone away
0N/A // or if the bitmap was not actually written to during this
0N/A // Lock/Unlock procedure.
0N/A ::BitBlt(hDC, wsdo->x, wsdo->y, wsdo->w, wsdo->h,
0N/A wsdo->bmdc, 0, 0, SRCCOPY);
0N/A ::GdiFlush();
0N/A }
0N/A wsdo->bmCopyToScreen = FALSE;
0N/A }
0N/A wsdo->lockType = WIN32SD_LOCK_UNLOCKED;
0N/A wsdo->ReleaseDC(env, wsdo, hDC);
0N/A }
0N/A wsdo->surfaceLock->Leave();
0N/A}
0N/A
0N/A/*
0N/A * REMIND: This mechanism is just a prototype of a way to manage a
0N/A * small cache of DC objects. It is incomplete in the following ways:
0N/A *
0N/A * - It is not thread-safe! It needs appropriate locking and release calls
0N/A * (perhaps the AutoDC mechanisms from Kestrel)
0N/A * - It does hardly any error checking (What if GetDCEx returns NULL?)
0N/A * - It cannot handle printer DCs and their resolution
0N/A * - It should probably "live" in the native SurfaceData object to allow
0N/A * alternate implementations for printing and embedding
0N/A * - It doesn't handle XOR
0N/A * - It caches the client bounds to determine if clipping is really needed
0N/A * (no way to invalidate the cached bounds and there is probably a better
0N/A * way to manage clip validation in any case)
0N/A */
0N/A
0N/A#define COLORFOR(c) (PALETTERGB(((c)>>16)&0xff,((c)>>8)&0xff,((c)&0xff)))
0N/A
430N/ACOLORREF CheckGrayColor(GDIWinSDOps *wsdo, int c) {
0N/A if (wsdo->device->GetGrayness() != GS_NOTGRAY) {
0N/A int g = (77 *(c & 0xFF) +
0N/A 150*((c >> 8) & 0xFF) +
0N/A 29 *((c >> 16) & 0xFF) + 128) / 256;
0N/A c = g | (g << 8) | (g << 16);
0N/A }
0N/A return COLORFOR(c);
0N/A}
0N/A
430N/Astatic HDC GDIWinSD_GetDC(JNIEnv *env, GDIWinSDOps *wsdo,
0N/A jint type, jint *patrop,
0N/A jobject clip, jobject comp, jint color)
0N/A{
430N/A J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_GetDC");
0N/A
0N/A if (wsdo->invalid == JNI_TRUE) {
0N/A if (beingShutdown != JNI_TRUE) {
0N/A SurfaceData_ThrowInvalidPipeException(env, "bounds changed");
0N/A }
0N/A return (HDC) NULL;
0N/A }
0N/A
0N/A ThreadGraphicsInfo *info = GetThreadGraphicsInfo(env, wsdo);
430N/A GDIWinSD_InitDC(env, wsdo, info, type, patrop, clip, comp, color);
0N/A return info->hDC;
0N/A}
0N/A
0N/AJNIEXPORT void JNICALL
430N/AGDIWinSD_InitDC(JNIEnv *env, GDIWinSDOps *wsdo, ThreadGraphicsInfo *info,
0N/A jint type, jint *patrop,
0N/A jobject clip, jobject comp, jint color)
0N/A{
430N/A J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_InitDC");
0N/A
0N/A // init clip
0N/A if (clip == NULL) {
0N/A if (info->type & CLIP) {
0N/A ::SelectClipRgn(info->hDC, (HRGN) NULL);
0N/A info->type ^= CLIP;
0N/A }
0N/A if (info->clip != NULL) {
0N/A env->DeleteWeakGlobalRef(info->clip);
0N/A info->clip = NULL;
0N/A }
0N/A } else if (!env->IsSameObject(clip, info->clip)) {
0N/A SurfaceDataBounds span;
0N/A RegionData clipInfo;
0N/A if (Region_GetInfo(env, clip, &clipInfo)) {
0N/A // return; // REMIND: What to do here?
0N/A }
0N/A
0N/A if (Region_IsEmpty(&clipInfo)) {
0N/A HRGN hrgn = ::CreateRectRgn(0, 0, 0, 0);
0N/A ::SelectClipRgn(info->hDC, hrgn);
0N/A ::DeleteObject(hrgn);
0N/A info->type |= CLIP;
0N/A } else if (Region_IsRectangular(&clipInfo)) {
0N/A if (clipInfo.bounds.x1 <= info->bounds.left &&
0N/A clipInfo.bounds.y1 <= info->bounds.top &&
0N/A clipInfo.bounds.x2 >= info->bounds.right &&
0N/A clipInfo.bounds.y2 >= info->bounds.bottom)
0N/A {
0N/A if (info->type & CLIP) {
0N/A ::SelectClipRgn(info->hDC, (HRGN) NULL);
0N/A info->type ^= CLIP;
0N/A }
0N/A } else {
0N/A // Make the window-relative rect a client-relative
0N/A // one for Windows
0N/A HRGN hrgn =
0N/A ::CreateRectRgn(clipInfo.bounds.x1 - wsdo->insets.left,
0N/A clipInfo.bounds.y1 - wsdo->insets.top,
0N/A clipInfo.bounds.x2 - wsdo->insets.left,
0N/A clipInfo.bounds.y2 - wsdo->insets.top);
0N/A ::SelectClipRgn(info->hDC, hrgn);
0N/A ::DeleteObject(hrgn);
0N/A info->type |= CLIP;
0N/A }
0N/A } else {
0N/A int leftInset = wsdo->insets.left;
0N/A int topInset = wsdo->insets.top;
0N/A Region_StartIteration(env, &clipInfo);
0N/A jint numrects = Region_CountIterationRects(&clipInfo);
6295N/A RGNDATA *lpRgnData = (RGNDATA *) SAFE_SIZE_STRUCT_ALLOC(safe_Malloc,
6295N/A sizeof(RGNDATAHEADER), numrects, sizeof(RECT));
6295N/A const DWORD nCount = sizeof(RGNDATAHEADER) + numrects * sizeof(RECT);
0N/A lpRgnData->rdh.dwSize = sizeof(RGNDATAHEADER);
0N/A lpRgnData->rdh.iType = RDH_RECTANGLES;
0N/A lpRgnData->rdh.nCount = numrects;
0N/A lpRgnData->rdh.nRgnSize = 0;
0N/A lpRgnData->rdh.rcBound.left = clipInfo.bounds.x1 - leftInset;
0N/A lpRgnData->rdh.rcBound.top = clipInfo.bounds.y1 - topInset;
0N/A lpRgnData->rdh.rcBound.right = clipInfo.bounds.x2 - leftInset;
0N/A lpRgnData->rdh.rcBound.bottom = clipInfo.bounds.y2 - topInset;
0N/A RECT *pRect = (RECT *) &(((RGNDATA *)lpRgnData)->Buffer);
0N/A while (Region_NextIteration(&clipInfo, &span)) {
0N/A pRect->left = span.x1 - leftInset;
0N/A pRect->top = span.y1 - topInset;
0N/A pRect->right = span.x2 - leftInset;
0N/A pRect->bottom = span.y2 - topInset;
0N/A pRect++;
0N/A }
0N/A Region_EndIteration(env, &clipInfo);
0N/A HRGN hrgn = ::ExtCreateRegion(NULL, nCount, lpRgnData);
0N/A free(lpRgnData);
0N/A ::SelectClipRgn(info->hDC, hrgn);
0N/A ::DeleteObject(hrgn);
0N/A info->type |= CLIP;
0N/A }
0N/A if (info->clip != NULL) {
0N/A env->DeleteWeakGlobalRef(info->clip);
0N/A }
0N/A info->clip = env->NewWeakGlobalRef(clip);
0N/A }
0N/A
0N/A // init composite
0N/A if ((comp == NULL) || !env->IsInstanceOf(comp, xorCompClass)) {
0N/A if (info->comp != NULL) {
0N/A env->DeleteWeakGlobalRef(info->comp);
0N/A info->comp = NULL;
0N/A info->patrop = PATCOPY;
0N/A ::SetROP2(info->hDC, R2_COPYPEN);
0N/A }
0N/A } else {
0N/A if (!env->IsSameObject(comp, info->comp)) {
0N/A info->xorcolor = GrPrim_CompGetXorColor(env, comp);
0N/A if (info->comp != NULL) {
0N/A env->DeleteWeakGlobalRef(info->comp);
0N/A }
0N/A info->comp = env->NewWeakGlobalRef(comp);
0N/A info->patrop = PATINVERT;
0N/A ::SetROP2(info->hDC, R2_XORPEN);
0N/A }
0N/A color ^= info->xorcolor;
0N/A }
0N/A
0N/A if (patrop != NULL) {
0N/A *patrop = info->patrop;
0N/A }
0N/A
0N/A // init brush and pen
0N/A if (type & BRUSH) {
0N/A if (info->brushclr != color || (info->brush == NULL)) {
0N/A if (info->type & BRUSH) {
0N/A ::SelectObject(info->hDC, nullbrush);
0N/A info->type ^= BRUSH;
0N/A }
0N/A if (info->brush != NULL) {
0N/A info->brush->Release();
0N/A }
0N/A info->brush = AwtBrush::Get(CheckGrayColor(wsdo, color));
0N/A info->brushclr = color;
0N/A }
0N/A if ((info->type & BRUSH) == 0) {
0N/A ::SelectObject(info->hDC, info->brush->GetHandle());
0N/A info->type ^= BRUSH;
0N/A }
0N/A } else if (type & NOBRUSH) {
0N/A if (info->type & BRUSH) {
0N/A ::SelectObject(info->hDC, nullbrush);
0N/A info->type ^= BRUSH;
0N/A }
0N/A }
0N/A if (type & PEN) {
0N/A if (info->penclr != color || (info->pen == NULL)) {
0N/A if (info->type & PEN) {
0N/A ::SelectObject(info->hDC, nullpen);
0N/A info->type ^= PEN;
0N/A }
0N/A if (info->pen != NULL) {
0N/A info->pen->Release();
0N/A }
0N/A info->pen = AwtPen::Get(CheckGrayColor(wsdo, color));
0N/A info->penclr = color;
0N/A }
0N/A if ((info->type & PEN) == 0) {
0N/A ::SelectObject(info->hDC, info->pen->GetHandle());
0N/A info->type ^= PEN;
0N/A }
0N/A } else if (type & NOPEN) {
0N/A if (info->type & PEN) {
0N/A ::SelectObject(info->hDC, nullpen);
0N/A info->type ^= PEN;
0N/A }
0N/A }
0N/A}
0N/A
430N/Astatic void GDIWinSD_ReleaseDC(JNIEnv *env, GDIWinSDOps *wsdo, HDC hDC)
0N/A{
430N/A J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_ReleaseDC");
0N/A // Don't actually do anything here: every thread holds its own
0N/A // wsdo-specific DC until the thread goes away or the wsdo
0N/A // is disposed.
0N/A}
0N/A
0N/A
430N/Astatic void GDIWinSD_InvalidateSD(JNIEnv *env, GDIWinSDOps *wsdo)
0N/A{
430N/A J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_InvalidateSD");
0N/A J2dTraceLn2(J2D_TRACE_VERBOSE, " wsdo=0x%x wsdo->window=0x%x",
0N/A wsdo, wsdo->window);
0N/A
0N/A wsdo->invalid = JNI_TRUE;
0N/A}
0N/A
0N/A
0N/A
0N/A/*
430N/A * Method: GDIWinSD_Dispose
0N/A */
0N/Astatic void
430N/AGDIWinSD_Dispose(JNIEnv *env, SurfaceDataOps *ops)
0N/A{
430N/A J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_Dispose");
0N/A // ops is assumed non-null as it is checked in SurfaceData_DisposeOps
430N/A GDIWinSDOps *wsdo = (GDIWinSDOps*)ops;
0N/A if (wsdo->bitmap) {
0N/A // delete old objects
0N/A J2dTraceLn(J2D_TRACE_VERBOSE, " disposing the GDI bitmap");
0N/A if (wsdo->bmdc) { // should not be null
0N/A ::SelectObject(wsdo->bmdc, wsdo->oldmap);
0N/A ::DeleteDC(wsdo->bmdc);
0N/A wsdo->bmdc = 0;
0N/A }
0N/A ::DeleteObject(wsdo->bitmap);
0N/A wsdo->bitmap = 0;
0N/A }
0N/A env->DeleteWeakGlobalRef(wsdo->peer);
0N/A if (wsdo->device != NULL) {
0N/A wsdo->device->Release();
0N/A wsdo->device = NULL;
0N/A }
0N/A delete wsdo->surfaceLock;
0N/A}
0N/A
0N/A
0N/A/*
430N/A * Class: sun_java2d_windows_GDIWindowSurfaceData
0N/A * Method: invalidateSD
0N/A * Signature: ()V
0N/A */
0N/AJNIEXPORT void JNICALL
430N/AJava_sun_java2d_windows_GDIWindowSurfaceData_invalidateSD(JNIEnv *env, jobject wsd)
0N/A{
430N/A J2dTraceLn(J2D_TRACE_INFO, "GDIWindowSurfaceData_invalidateSD");
430N/A GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOpsNoSetup(env, wsd);
0N/A if (wsdo != NULL) {
0N/A wsdo->InvalidateSD(env, wsdo);
0N/A }
0N/A}