/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ /* * region.cpp --- FE specific region operations */ #include "stdafx.h" //mwh don't use MFC on Nav 4.0 //#define RGN_USE_MFC /* Creates an empty region. Returns NULL if region can't be created */ FE_Region FE_CreateRegion() { #ifdef FE_RGN_USE_MFC CRgn *pRgn = new CRgn; pRgn->CreateRectRgn(0, 0, 0, 0); return (FE_Region)pRgn; #else return (FE_Region)CreateRectRgn(0, 0, 0, 0); #endif } /* Creates a region from a rectangle. Returns NULL if region can't be created */ FE_Region FE_CreateRectRegion(XP_Rect *rect) { #ifdef FE_RGN_USE_MFC CRgn *pRgn = new CRgn; pRgn->CreateRectRgn(rect->left, rect->top, rect->right, rect->bottom); return (FE_Region)pRgn; #else // return (FE_Region)CreateRectRgn(rect->left, rect->top, // rect->right, rect->bottom); HRGN rgn = CreateRectRgn(CASTINT(rect->left), CASTINT(rect->top), CASTINT(rect->right), CASTINT(rect->bottom)); if (rgn) return (FE_Region)rgn; else return (FE_Region)CreateRectRgn(0, 0, 0, 0); #endif } /* Set an existing region to a rectangle */ FE_Region FE_SetRectRegion(FE_Region region, XP_Rect *rect) { XP_ASSERT(region); #ifdef FE_RGN_USE_MFC ((CRgn *)region)->SetRectRgn(rect->left, rect->top, rect->right, rect->bottom); return region; #else ::SetRectRgn((HRGN)region, CASTINT(rect->left), CASTINT(rect->top), CASTINT(rect->right), CASTINT(rect->bottom)); return region; #endif } /* Destroys region */ void FE_DestroyRegion(FE_Region region) { #ifndef FE_RGN_USE_MFC BOOL result; #endif XP_ASSERT(region); #ifdef FE_RGN_USE_MFC ((CRgn *)region)->DeleteObject(); delete ((CRgn *)region); #else result = DeleteObject((HRGN)region); XP_ASSERT(result); #endif } /* Make a copy of a region */ FE_Region FE_CopyRegion(FE_Region src, FE_Region dst) { #ifdef FE_RGN_USE_MFC CRgn * pCopyRgn; XP_ASSERT(src); if (dst != NULL) pCopyRgn = (CRgn *)dst; else { pCopyRgn = new CRgn; pCopyRgn->CreateRectRgn(0, 0, 0, 0); } pCopyRgn->CopyRgn((CRgn *)src); return pCopyRgn; #else HRGN copyRegion; XP_ASSERT(src); if (dst != NULL) copyRegion = (HRGN)dst; else { /* Create an empty region */ copyRegion = CreateRectRgn(0, 0, 0, 0); if (copyRegion == NULL) return NULL; } /* Copy the region */ if (CombineRgn(copyRegion, (HRGN)src, (HRGN)src, RGN_COPY) == ERROR) { DeleteObject(copyRegion); return NULL; } return (FE_Region)copyRegion; #endif } /* dst = src1 intersect sr2 */ /* dst can be one of src1 or src2 */ void FE_IntersectRegion(FE_Region src1, FE_Region src2, FE_Region dst) { XP_ASSERT(src1); XP_ASSERT(src2); XP_ASSERT(dst); #ifdef FE_RGN_USE_MFC ((CRgn *)dst)->CombineRgn((CRgn *)src1, (CRgn *)src2, RGN_AND); #else CombineRgn((HRGN)dst, (HRGN)src1, (HRGN)src2, RGN_AND); #endif } /* dst = src1 union src2 */ /* dst can be one of src1 or src2 */ void FE_UnionRegion(FE_Region src1, FE_Region src2, FE_Region dst) { XP_ASSERT(src1); XP_ASSERT(src2); XP_ASSERT(dst); #ifdef FE_RGN_USE_MFC ((CRgn *)dst)->CombineRgn((CRgn *)src1, (CRgn *)src2, RGN_OR); #else CombineRgn((HRGN)dst, (HRGN)src1, (HRGN)src2, RGN_OR); #endif } /* dst = src1 - src2 */ /* dst can be one of src1 or src2 */ void FE_SubtractRegion(FE_Region src1, FE_Region src2, FE_Region dst) { XP_ASSERT(src1); XP_ASSERT(src2); XP_ASSERT(dst); #ifdef FE_RGN_USE_MFC ((CRgn *)dst)->CombineRgn((CRgn *)src1, (CRgn *)src2, RGN_DIFF); #else CombineRgn((HRGN)dst, (HRGN)src1, (HRGN)src2, RGN_DIFF); #endif } /* Returns TRUE if the region contains no pixels */ XP_Bool FE_IsEmptyRegion(FE_Region region) { int result; XP_ASSERT(region); #ifdef FE_RGN_USE_MFC result = ((CRgn *)region)->OffsetRgn(0, 0); #else /* This might not be the best way to find out, but it's one of them */ result = OffsetRgn((HRGN)region, 0, 0); #endif if (result == NULLREGION) return TRUE; else return FALSE; } /* Returns the bounding rectangle of the region */ void FE_GetRegionBoundingBox(FE_Region region, XP_Rect *bbox) { RECT rect; XP_ASSERT(region); XP_ASSERT(bbox); #ifdef FE_RGN_USE_MFC ((CRgn *)region)->GetRgnBox((LPRECT)&rect); #else GetRgnBox((HRGN)region, (LPRECT)&rect); #endif bbox->left = rect.left; bbox->top = rect.top; bbox->right = rect.right; bbox->bottom = rect.bottom; } /* TRUE if rgn1 == rgn2 */ XP_Bool FE_IsEqualRegion(FE_Region rgn1, FE_Region rgn2) { XP_ASSERT(rgn1); XP_ASSERT(rgn2); #ifdef FE_RGN_USE_MFC return ((CRgn *)rgn1)->EqualRgn((CRgn *)rgn2); #else return (EqualRgn((HRGN)rgn1, (HRGN)rgn2)); #endif } /* Moves a region by the specified offsets */ void FE_OffsetRegion(FE_Region region, int32 x_offset, int32 y_offset) { int result; #ifdef FE_RGN_USE_MFC result = ((CRgn *)region)->OffsetRgn(x_offset, y_offset); #else result = OffsetRgn((HRGN)region, CASTINT(x_offset), CASTINT(y_offset)); #endif XP_ASSERT(result != ERROR); } /* Returns TRUE if any part of the rectangle is in the specified region */ XP_Bool FE_RectInRegion(FE_Region region, XP_Rect *rect) { RECT box; XP_ASSERT(region); XP_ASSERT(rect); box.left = CASTINT(rect->left); box.top = CASTINT(rect->top); box.right = CASTINT(rect->right); box.bottom = CASTINT(rect->bottom); #ifdef FE_RGN_USE_MFC return ((CRgn *)region)->RectInRegion(&box); #else return RectInRegion((HRGN)region, &box); #endif } /* Calls the specified function for each rectangle that makes up the region */ void FE_ForEachRectInRegion(FE_Region region, FE_RectInRegionFunc func, void *closure) { #ifndef _WIN32 /* * For 16-bit Windows, we can't get at the rectangles that make up a region, * so we just call the function with the bounding box of the entire region. */ RECT rect; XP_Rect xprect; #ifdef FE_RGN_USE_MFC ((CRgn *)region)->GetRgnBox((LPRECT)&rect); #else GetRgnBox((HRGN)region, (LPRECT)&rect); #endif xprect.left = rect.left; xprect.top = rect.top; xprect.right = rect.right; xprect.bottom = rect.bottom; (*func)(closure, &xprect); #else LPRGNDATA pRgnData; LPRECT pRects; DWORD dwCount, dwResult; unsigned int num_rects; XP_Rect rect; #ifdef FE_RGN_USE_MFC CRgn *pRgn = (CRgn *)region; #endif XP_ASSERT(region); XP_ASSERT(func); /* Get the size of the region data */ #ifdef FE_RGN_USE_MFC dwCount = pRgn->GetRegionData(NULL, 0); #else dwCount = GetRegionData((HRGN)region, 0, NULL); #endif XP_ASSERT(dwCount != 0); if (dwCount == 0) return; pRgnData = (LPRGNDATA)XP_ALLOC(dwCount); XP_ASSERT(pRgnData != NULL); if (pRgnData == NULL) return; #ifdef FE_RGN_USE_MFC dwResult = pRgn->GetRegionData(pRgnData, dwCount); #else dwResult = GetRegionData((HRGN)region, dwCount, pRgnData); #endif XP_ASSERT(dwResult != 0); if (dwResult == 0) { XP_FREE(pRgnData); return; } for (pRects = (LPRECT)pRgnData->Buffer, num_rects = 0; num_rects < pRgnData->rdh.nCount; num_rects++, pRects++) { rect.left = pRects->left; rect.top = pRects->top; rect.right = pRects->right; rect.bottom = pRects->bottom; (*func)(closure, &rect); } XP_FREE(pRgnData); #endif /* XP_WIN32 */ } void FE_HighlightRegion(void *pC, FE_Region region, int how_much) { #if defined(DEBUG) && defined(_WIN32) MWContext *pContext = (MWContext *)pC; HDC hdc = ::GetDC(PANECX(pContext)->GetPane()); InvertRgn(hdc, (HRGN)region); Sleep(how_much * 2 / 3); InvertRgn(hdc, (HRGN)region); Sleep(how_much / 3); ::ReleaseDC(PANECX(pContext)->GetPane(), hdc); #else XP_ASSERT(0); /* Not supported on Win16 */ #endif }