зеркало из https://github.com/mozilla/gecko-dev.git
384 строки
8.1 KiB
C++
384 строки
8.1 KiB
C++
/* -*- 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
|
|
}
|
|
|