module GraphicsRegion
	( Region
	, intersectRegion, unionRegion, xorRegion, subtractRegion
	, rectangleRegion, ellipseRegion, polygonRegion
	, regionToGraphic
	) where

import qualified Win32
import GraphicsTypes hiding (bracket)
import GraphicsUtilities( bracket )
import IOExts(unsafePerformIO)

----------------------------------------------------------------
-- The Interface
----------------------------------------------------------------

newtype Region = MkRegion Win32.HRGN

intersectRegion :: Region -> Region -> Region
unionRegion     :: Region -> Region -> Region
xorRegion       :: Region -> Region -> Region
subtractRegion  :: Region -> Region -> Region
	        
rectangleRegion :: Point -> Point -> Region
ellipseRegion   :: Point -> Point -> Region
polygonRegion   :: [Point] -> Region

regionToGraphic :: Region -> Draw ()

----------------------------------------------------------------
-- The Implementation
----------------------------------------------------------------

rectangleRegion pt0 pt1 = unsafePerformIO $ do
  r <- Win32.createRectRgn x0 y0 x1 y1
  return (MkRegion r)
 where
  (x0,y0) = fromPoint pt0
  (x1,y1) = fromPoint pt1

-- Sigh! createEllipticRgn raises an exception if either dimension
-- of the ellipse is empty.  We hack around this by using rectangleRegion
-- in the problematic case (since createRectRgn behaves sensibly).
ellipseRegion pt0 pt1 
  | x0 /= x1 && y0 /= y1
  = unsafePerformIO $ do
      r <- Win32.createEllipticRgn x0 y0 x1 y1
      return (MkRegion r)
  | otherwise
  = rectangleRegion pt0 pt1
 where
  (x0,y0) = fromPoint pt0
  (x1,y1) = fromPoint pt1

polygonRegion pts = unsafePerformIO $ do
  r <- Win32.createPolygonRgn (map fromPoint pts) Win32.wINDING
  return (MkRegion r)

-- combine :: Win32.ClippingMode -> Region -> Region -> Region -> IO ()
-- combine mode (MkRegion r1) (MkRegion r2) (MkRegion result) = do
--   Win32.combineRgn result r1 r2 mode
--   return ()

combine :: Win32.ClippingMode -> Region -> Region -> Region
combine mode (MkRegion r1) (MkRegion r2) = unsafePerformIO $ do
  r <- Win32.createRectRgn 0 0 0 0
  Win32.combineRgn r r1 r2 mode
  return (MkRegion r)

regionToGraphic (MkRegion r) = mkDraw (\hdc -> Win32.paintRgn hdc r)

intersectRegion = combine Win32.rGN_AND
unionRegion     = combine Win32.rGN_OR
xorRegion       = combine Win32.rGN_XOR
subtractRegion  = combine Win32.rGN_DIFF

----------------------------------------------------------------
-- End
----------------------------------------------------------------

