-----------------------------------------------------------------------------
-- |
-- Module      :  Graphics.Win32.GDI.Graphics2D
-- Copyright   :  (c) Alastair Reid, 1997-2003
-- License     :  BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer  :  Esa Ilari Vuokko <ei@vuokko.info>
-- Stability   :  provisional
-- Portability :  portable
--
-- 2D graphics operations
--
-----------------------------------------------------------------------------

module Graphics.Win32.GDI.Graphics2D
	where

import System.Win32.Types
import Graphics.Win32.GDI.Types
import Graphics.Win32.GDI.Bitmap

import Foreign

----------------------------------------------------------------
-- Lines and Curves
----------------------------------------------------------------

moveToEx :: HDC -> Int32 -> Int32 -> IO POINT
moveToEx dc x y =
  allocaPOINT $ \ p_point -> do
  failIfFalse_ "MoveToEx" $ c_MoveToEx dc x y p_point
  peekPOINT p_point
foreign import stdcall unsafe "windows.h MoveToEx"
  c_MoveToEx :: HDC -> Int32 -> Int32 -> Ptr POINT -> IO Bool

lineTo :: HDC -> Int32 -> Int32 -> IO ()
lineTo dc x y =
  failIfFalse_ "LineTo" $ c_LineTo dc x y
foreign import stdcall unsafe "windows.h LineTo"
  c_LineTo :: HDC -> Int32 -> Int32 -> IO Bool

polyline :: HDC -> [POINT] -> IO ()
polyline dc points =
  withPOINTArray points $ \ pount_array npoints ->
  failIfFalse_ "Polyline" $ c_Polyline dc pount_array npoints
foreign import stdcall unsafe "windows.h Polyline"
  c_Polyline :: HDC -> Ptr POINT -> Int -> IO Bool

polylineTo :: HDC -> [POINT] -> IO ()
polylineTo dc points =
  withPOINTArray points $ \ pount_array npoints ->
  failIfFalse_ "PolylineTo" $ c_PolylineTo dc pount_array npoints
foreign import stdcall unsafe "windows.h PolylineTo"
  c_PolylineTo :: HDC -> Ptr POINT -> Int -> IO Bool

polygon :: HDC -> [POINT] -> IO ()
polygon dc points =
  withPOINTArray points $ \ pount_array npoints ->
  failIfFalse_ "Polygon" $ c_Polygon dc pount_array npoints
foreign import stdcall unsafe "windows.h Polygon"
  c_Polygon :: HDC -> Ptr POINT -> Int -> IO Bool

polyBezier :: HDC -> [POINT] -> IO ()
polyBezier dc points =
  withPOINTArray points $ \ pount_array npoints ->
  failIfFalse_ "PolyBezier" $ c_PolyBezier dc pount_array npoints
foreign import stdcall unsafe "windows.h PolyBezier"
  c_PolyBezier :: HDC -> Ptr POINT -> Int -> IO Bool

polyBezierTo :: HDC -> [POINT] -> IO ()
polyBezierTo dc points =
  withPOINTArray points $ \ pount_array npoints ->
  failIfFalse_ "PolyBezierTo" $ c_PolyBezierTo dc pount_array npoints
foreign import stdcall unsafe "windows.h PolyBezierTo"
  c_PolyBezierTo :: HDC -> Ptr POINT -> Int -> IO Bool

arc :: HDC -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> IO ()
arc dc left top right bottom x1 y1 x2 y2 =
  failIfFalse_ "Arc" $ c_Arc dc left top right bottom x1 y1 x2 y2
foreign import stdcall unsafe "windows.h Arc"
  c_Arc :: HDC -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> IO Bool

arcTo :: HDC -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> IO ()
arcTo dc left top right bottom x1 y1 x2 y2 =
  failIfFalse_ "ArcTo" $ c_ArcTo dc left top right bottom x1 y1 x2 y2
foreign import stdcall unsafe "windows.h ArcTo"
  c_ArcTo :: HDC -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> IO Bool

angleArc :: HDC -> Int32 -> Int32 -> WORD -> Float -> Float -> IO ()
angleArc dc x y r start sweep =
  failIfFalse_ "AngleArc" $ c_AngleArc dc x y r start sweep
foreign import stdcall unsafe "windows.h AngleArc"
  c_AngleArc :: HDC -> Int32 -> Int32 -> WORD -> Float -> Float -> IO Bool

----------------------------------------------------------------
-- Filled Shapes
----------------------------------------------------------------

-- ToDo: We ought to be able to specify a colour instead of the
-- Brush by adding 1 to colour number.

fillRect :: HDC -> RECT -> HBRUSH -> IO ()
fillRect dc rect brush =
  withRECT rect $ \ c_rect ->
  failIfFalse_ "FillRect" $ c_FillRect dc c_rect brush
foreign import stdcall unsafe "windows.h FillRect"
  c_FillRect :: HDC -> Ptr RECT -> HBRUSH -> IO Bool

frameRect :: HDC -> RECT -> HBRUSH -> IO ()
frameRect dc rect brush =
  withRECT rect $ \ c_rect ->
  failIfFalse_ "FrameRect" $ c_FrameRect dc c_rect brush
foreign import stdcall unsafe "windows.h FrameRect"
  c_FrameRect :: HDC -> Ptr RECT -> HBRUSH -> IO Bool

invertRect :: HDC -> RECT -> IO ()
invertRect dc rect =
  withRECT rect $ \ c_rect ->
  failIfFalse_ "InvertRect" $ c_InvertRect dc c_rect
foreign import stdcall unsafe "windows.h InvertRect"
  c_InvertRect :: HDC -> Ptr RECT -> IO Bool

rectangle :: HDC -> Int32 -> Int32 -> Int32 -> Int32 -> IO ()
rectangle dc left top right bottom =
  failIfFalse_ "Rectangle" $ c_Rectangle dc left top right bottom
foreign import stdcall unsafe "windows.h Rectangle"
  c_Rectangle :: HDC -> Int32 -> Int32 -> Int32 -> Int32 -> IO Bool

roundRect :: HDC -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> IO ()
roundRect dc left top right bottom w h =
  failIfFalse_ "RoundRect" $ c_RoundRect dc left top right bottom w h
foreign import stdcall unsafe "windows.h RoundRect"
  c_RoundRect :: HDC -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> IO Bool

ellipse :: HDC -> Int32 -> Int32 -> Int32 -> Int32 -> IO ()
ellipse dc left top right bottom =
  failIfFalse_ "Ellipse" $ c_Ellipse dc left top right bottom
foreign import stdcall unsafe "windows.h Ellipse"
  c_Ellipse :: HDC -> Int32 -> Int32 -> Int32 -> Int32 -> IO Bool

chord :: HDC -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> IO ()
chord dc left top right bottom x1 y1 x2 y2 =
  failIfFalse_ "Chord" $ c_Chord dc left top right bottom x1 y1 x2 y2
foreign import stdcall unsafe "windows.h Chord"
  c_Chord :: HDC -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> IO Bool

pie :: HDC -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> IO ()
pie dc left top right bottom x1 y1 x2 y2 =
  failIfFalse_ "Pie" $ c_Pie dc left top right bottom x1 y1 x2 y2
foreign import stdcall unsafe "windows.h Pie"
  c_Pie :: HDC -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> Int32 -> IO Bool

----------------------------------------------------------------
-- Bitmaps
----------------------------------------------------------------

bitBlt :: HDC -> INT -> INT -> INT -> INT -> HDC -> INT -> INT -> RasterOp3 -> IO ()
bitBlt dcDest xDest yDest w h dcSrc xSrc ySrc rop =
  failIfFalse_ "BitBlt" $ c_BitBlt dcDest xDest yDest w h dcSrc xSrc ySrc rop
foreign import stdcall unsafe "windows.h BitBlt"
  c_BitBlt :: HDC -> INT -> INT -> INT -> INT -> HDC -> INT -> INT -> RasterOp3 -> IO Bool

maskBlt :: HDC -> INT -> INT -> INT -> INT -> HDC -> INT -> INT -> HBITMAP -> INT -> INT -> RasterOp4 -> IO ()
maskBlt dcDest xDest yDest w h dcSrc xSrc ySrc bm xMask yMask rop =
  failIfFalse_ "MaskBlt" $
    c_MaskBlt dcDest xDest yDest w h dcSrc xSrc ySrc bm xMask yMask rop
foreign import stdcall unsafe "windows.h MaskBlt"
  c_MaskBlt :: HDC -> INT -> INT -> INT -> INT -> HDC -> INT -> INT -> HBITMAP -> INT -> INT -> RasterOp4 -> IO Bool

stretchBlt :: HDC -> INT -> INT -> INT -> INT -> HDC -> INT -> INT -> INT -> INT -> RasterOp3 -> IO ()
stretchBlt dcDest xDest yDest wDest hDest hdcSrc xSrc ySrc wSrc hSrc rop =
  failIfFalse_ "StretchBlt" $
    c_StretchBlt dcDest xDest yDest wDest hDest hdcSrc xSrc ySrc wSrc hSrc rop
foreign import stdcall unsafe "windows.h StretchBlt"
  c_StretchBlt :: HDC -> INT -> INT -> INT -> INT -> HDC -> INT -> INT -> INT -> INT -> RasterOp3 -> IO Bool

-- We deviate slightly from the Win32 interface

-- %C typedef POINT ThreePts[3];

-- Old 2nd line:
-- %start POINT vertices[3];

plgBlt :: HDC -> POINT -> POINT -> POINT -> HDC -> INT -> INT -> INT -> INT -> MbHBITMAP -> INT -> INT -> IO ()
plgBlt hdDest p1 p2 p3 hdSrc x y w h mb_bm xMask yMask =
  withPOINTArray [p1,p2,p3] $ \ vertices _ ->
  failIfFalse_ "PlgBlt" $
    c_PlgBlt hdDest vertices hdSrc x y w h (maybePtr mb_bm) xMask yMask
foreign import stdcall unsafe "windows.h PlgBlt"
  c_PlgBlt :: HDC -> Ptr POINT -> HDC -> INT -> INT -> INT -> INT -> HBITMAP -> INT -> INT -> IO Bool

----------------------------------------------------------------
-- Fonts and Text
----------------------------------------------------------------

textOut :: HDC -> INT -> INT -> String -> IO ()
textOut dc x y str =
  withTStringLen str $ \ (c_str, len) ->
  failIfFalse_ "TextOut" $ c_TextOut dc x y c_str len
foreign import stdcall unsafe "windows.h TextOutW"
  c_TextOut :: HDC -> INT -> INT -> LPCTSTR -> Int -> IO Bool

-- missing TabbedTextOut from WinFonts.ss; GSL ???

getTextExtentPoint32 :: HDC -> String -> IO SIZE
getTextExtentPoint32 dc str =
  withTStringLen str $ \ (c_str, len) ->
  allocaSIZE $ \ p_size -> do
  failIfFalse_ "GetTextExtentPoint32" $
    c_GetTextExtentPoint32 dc c_str len p_size
  peekSIZE p_size
foreign import stdcall unsafe "windows.h GetTextExtentPoint32W"
  c_GetTextExtentPoint32 :: HDC -> LPCTSTR -> Int -> Ptr SIZE -> IO Bool

-- missing getTabbedTextExtent from WinFonts.ss; GSL ???
-- missing SetTextJustification from WinFonts.ss; GSL ???
-- missing a whole family of techandfamily functionality; GSL ???
-- missing DrawText and DrawTextFormat in WinFonts.ss; GSL ???

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