1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
|
{-# LANGUAGE CPP, ScopedTypeVariables #-}
-- -*-haskell-*-
-- GIMP Toolkit (GTK) Drawable
--
-- Author : Axel Simon
--
-- Created: 22 September 2002
--
-- Copyright (C) 2002-2005 Axel Simon
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2.1 of the License, or (at your option) any later version.
--
-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- Lesser General Public License for more details.
--
-- TODO
--
-- if gdk_visuals are implemented, do: get_visual
--
-- if gdk_colormaps are implemented, do: set_colormap, get_colormap
--
-- |
-- Maintainer : gtk2hs-users@lists.sourceforge.net
-- Stability : provisional
-- Portability : portable (depends on GHC)
--
-- Drawing primitives.
--
-- This module defines drawing primitives that can operate on 'DrawWindow's
-- and 'Pixmap's.
--
module Graphics.UI.Gtk.Gdk.Drawable (
Drawable,
DrawableClass,
castToDrawable, gTypeDrawable,
toDrawable,
drawableGetDepth,
drawableGetSize,
drawableGetClipRegion,
drawableGetVisibleRegion,
Point,
drawPoint,
drawPoints,
drawLine,
drawLines,
#if GTK_CHECK_VERSION(2,2,0)
Dither(..),
drawPixbuf,
#endif
drawSegments,
drawRectangle,
drawArc,
drawPolygon,
drawGlyphs,
drawLayoutLine,
drawLayoutLineWithColors,
drawLayout,
drawLayoutWithColors,
drawDrawable) where
import Control.Monad (liftM)
import System.Glib.FFI
import Graphics.UI.Gtk.General.Structs (Point, Color)
import Graphics.Rendering.Pango.Structs
{#import Graphics.Rendering.Pango.Types#}
{#import Graphics.Rendering.Pango.BasicTypes#}
{#import Graphics.UI.Gtk.Types#}
{#import Graphics.UI.Gtk.Gdk.Region#} (Region, makeNewRegion)
import Graphics.UI.Gtk.Gdk.Enums (Dither(..))
{# context lib="gtk" prefix="gdk" #}
-- methods
-- | Get the size of pixels.
--
-- * Returns the number of bits which are use to store information on each
-- pixels in this 'Drawable'.
--
drawableGetDepth :: DrawableClass d => d -> IO Int
drawableGetDepth d = liftM fromIntegral $
{#call unsafe drawable_get_depth#} (toDrawable d)
-- | Retrieve the size of the 'Drawable'.
--
-- * The result might not be up-to-date if there are still resizing messages
-- to be processed.
--
drawableGetSize :: DrawableClass d => d -> IO (Int, Int)
drawableGetSize d = alloca $ \wPtr -> alloca $ \hPtr -> do
{#call unsafe drawable_get_size#} (toDrawable d) wPtr hPtr
(w::{#type gint#}) <- peek wPtr
(h::{#type gint#}) <- peek hPtr
return (fromIntegral w, fromIntegral h)
-- | Determine where not to draw.
--
-- * Computes the region of a drawable that potentially can be written
-- to by drawing primitives. This region will not take into account the
-- clip region for the GC, and may also not take into account other
-- factors such as if the window is obscured by other windows, but no
-- area outside of this region will be affected by drawing primitives.
--
drawableGetClipRegion :: DrawableClass d => d -> IO Region
drawableGetClipRegion d = do
rPtr <- {#call unsafe drawable_get_clip_region#} (toDrawable d)
makeNewRegion rPtr
-- | Determine what not to redraw.
--
-- * Computes the region of a drawable that is potentially visible.
-- This does not necessarily take into account if the window is obscured
-- by other windows, but no area outside of this region is visible.
--
drawableGetVisibleRegion :: DrawableClass d => d -> IO Region
drawableGetVisibleRegion d = do
rPtr <- {#call unsafe drawable_get_visible_region#} (toDrawable d)
makeNewRegion rPtr
-- | Draw a point into a 'Drawable'.
--
drawPoint :: DrawableClass d => d -> GC -> Point -> IO ()
drawPoint d gc (x,y) = {#call unsafe draw_point#} (toDrawable d)
(toGC gc) (fromIntegral x) (fromIntegral y)
-- | Draw several points into a 'Drawable'.
--
-- * This function is more efficient than calling 'drawPoint' on
-- several points.
--
drawPoints :: DrawableClass d => d -> GC -> [Point] -> IO ()
drawPoints d gc [] = return ()
drawPoints d gc points =
withArray (concatMap (\(x,y) -> [fromIntegral x, fromIntegral y]) points) $
\(aPtr :: Ptr {#type gint#}) -> {#call unsafe draw_points#} (toDrawable d)
(toGC gc) (castPtr aPtr) (fromIntegral (length points))
-- | Draw a line into a 'Drawable'.
--
-- * The parameters are x1, y1, x2, y2.
--
-- * Drawing several separate lines can be done more efficiently by
-- 'drawSegments'.
--
drawLine :: DrawableClass d => d -> GC -> Point -> Point -> IO ()
drawLine d gc (x1,y1) (x2,y2) = {#call unsafe draw_line#} (toDrawable d)
(toGC gc) (fromIntegral x1) (fromIntegral y1) (fromIntegral x2)
(fromIntegral y2)
-- | Draw several lines.
--
-- * The function uses the current line width, dashing and especially the
-- joining specification in the graphics context (in contrast to
-- 'drawSegments'.
--
drawLines :: DrawableClass d => d -> GC -> [Point] -> IO ()
drawLines d gc [] = return ()
drawLines d gc points =
withArray (concatMap (\(x,y) -> [fromIntegral x, fromIntegral y]) points) $
\(aPtr :: Ptr {#type gint#}) -> {#call unsafe draw_lines#} (toDrawable d)
(toGC gc) (castPtr aPtr) (fromIntegral (length points))
#if GTK_CHECK_VERSION(2,2,0)
-- | Render a 'Pixbuf'.
--
-- * Usage:
-- @drawPixbuf d gc pb srcX srcY destX destY srcWidth srcHeight dither@
-- Renders a rectangular portion of a 'Pixbuf' to a
-- 'Drawable'. The @srcX@, @srcY@,
-- @srcWidth@ and @srcHeight@ specify what part of the
-- 'Pixbuf' should be rendered. The latter two values may be
-- @-1@ in which case the width and height are taken from
-- @pb@. The image is placed at @destX@, @destY@.
-- If you render parts of an image at a time, set @ditherX@ and
-- @ditherY@ to the origin of the image you are rendering.
--
-- * Since 2.2.
--
drawPixbuf :: DrawableClass d => d -> GC -> Pixbuf -> Int -> Int ->
Int -> Int -> Int -> Int -> Dither ->
Int -> Int -> IO ()
drawPixbuf d gc pb srcX srcY destX destY srcWidth srcHeight dither
xDither yDither = {#call unsafe draw_pixbuf#} (toDrawable d)
gc pb (fromIntegral srcX) (fromIntegral srcY) (fromIntegral destX)
(fromIntegral destY) (fromIntegral srcWidth) (fromIntegral srcHeight)
((fromIntegral . fromEnum) dither) (fromIntegral xDither)
(fromIntegral yDither)
#endif
-- | Draw several unconnected lines.
--
-- * This method draws several unrelated lines.
--
drawSegments :: DrawableClass d => d -> GC -> [(Point,Point)] -> IO ()
drawSegments d gc [] = return ()
drawSegments d gc pps = withArray (concatMap (\((x1,y1),(x2,y2)) ->
[fromIntegral x1, fromIntegral y1, fromIntegral x2, fromIntegral y2])
pps) $ \(aPtr :: Ptr {#type gint#}) ->
{#call unsafe draw_segments#} (toDrawable d) (toGC gc)
(castPtr aPtr) (fromIntegral (length pps))
-- | Draw a rectangular object.
--
-- * Draws a rectangular outline or filled rectangle, using the
-- foreground color and other attributes of the 'GC'.
--
-- * A rectangle drawn filled is 1 pixel smaller in both dimensions
-- than a rectangle outlined. Calling 'drawRectangle' w gc
-- True 0 0 20 20 results in a filled rectangle 20 pixels wide and 20
-- pixels high. Calling 'drawRectangle' d gc False 0 0 20 20
-- results in an outlined rectangle with corners at (0, 0), (0, 20), (20,
-- 20), and (20, 0), which makes it 21 pixels wide and 21 pixels high.
--
drawRectangle :: DrawableClass d => d -> GC -> Bool -> Int -> Int ->
Int -> Int -> IO ()
drawRectangle d gc filled x y width height = {#call unsafe draw_rectangle#}
(toDrawable d) (toGC gc) (fromBool filled) (fromIntegral x)
(fromIntegral y) (fromIntegral width) (fromIntegral height)
-- | Draws an arc or a filled 'pie slice'.
--
-- * The arc is defined by the bounding rectangle of the entire
-- ellipse, and the start and end angles of the part of the ellipse to be
-- drawn.
--
-- * The starting angle @aStart@ is relative to the 3 o'clock
-- position, counter-clockwise, in 1\/64ths of a degree. @aEnd@
-- is measured similarly, but relative to @aStart@.
--
drawArc :: DrawableClass d => d -> GC -> Bool -> Int -> Int ->
Int -> Int -> Int -> Int -> IO ()
drawArc d gc filled x y width height aStart aEnd =
{#call unsafe draw_arc#} (toDrawable d) (toGC gc) (fromBool filled)
(fromIntegral x) (fromIntegral y) (fromIntegral width) (fromIntegral height)
(fromIntegral aStart) (fromIntegral aEnd)
-- | Draws an outlined or filled polygon.
--
-- * The polygon is closed automatically, connecting the last point to
-- the first point if necessary.
--
drawPolygon :: DrawableClass d => d -> GC -> Bool -> [Point] -> IO ()
drawPolygon _ _ _ [] = return ()
drawPolygon d gc filled points =
withArray (concatMap (\(x,y) -> [fromIntegral x, fromIntegral y]) points) $
\(aPtr::Ptr {#type gint#}) -> {#call unsafe draw_polygon#} (toDrawable d)
(toGC gc) (fromBool filled) (castPtr aPtr) (fromIntegral (length points))
-- | Draw a segment of text.
--
-- * This function draws a segment of text. These segements are the result
-- of itemizing a string into segments with the same characteristics
-- (font, text direction, etc.) using
-- 'Graphics.Rendering.Pango.Rendering.itemize'. Each item is then turned
-- into a shapes by calling 'Graphics.Rendering.Pango.Rendering.shape'.
-- These shapes can then be drawn onto screen using this function.
-- A simpler interface, that also takes care of breaking a paragraph
-- into several lines is a 'Graphics.Rendering.Pango.Layout.LayoutLine'.
--
drawGlyphs :: DrawableClass d => d -> GC -> Int -> Int -> GlyphItem -> IO ()
drawGlyphs d gc x y (GlyphItem pi gs) = do
font <- pangoItemGetFont pi
{#call unsafe draw_glyphs#} (toDrawable d) (toGC gc) font
(fromIntegral x) (fromIntegral y) gs
--
-- | Draw a single line of text.
--
-- * The @x@ coordinate specifies the start of the string,
-- the @y@ coordinate specifies the base line.
--
drawLayoutLine :: DrawableClass d => d -> GC -> Int -> Int -> LayoutLine ->
IO ()
drawLayoutLine d gc x y (LayoutLine _ ll) =
{#call unsafe draw_layout_line#} (toDrawable d) (toGC gc)
(fromIntegral x) (fromIntegral y) ll
-- | Draw a single line of text.
--
-- * The @x@ coordinate specifies the start of the string,
-- the @y@ coordinate specifies the base line.
--
-- * If both colors are @Nothing@ this function will behave like
-- 'drawLayoutLine' in that it uses the default colors from
-- the graphics context.
--
drawLayoutLineWithColors :: DrawableClass d => d -> GC -> Int -> Int ->
LayoutLine -> Maybe Color -> Maybe Color -> IO ()
drawLayoutLineWithColors d gc x y (LayoutLine _ ll) foreground background = let
withMB :: Storable a => Maybe a -> (Ptr a -> IO b) -> IO b
withMB Nothing f = f nullPtr
withMB (Just x) f = with x f
in
withMB foreground $ \fPtr -> withMB background $ \bPtr ->
{#call unsafe draw_layout_line_with_colors#} (toDrawable d) (toGC gc)
(fromIntegral x) (fromIntegral y) ll (castPtr fPtr) (castPtr bPtr)
-- | Draw a paragraph of text.
--
-- * The @x@ and @y@ values specify the upper left
-- point of the layout.
--
drawLayout :: DrawableClass d => d -> GC -> Int -> Int -> PangoLayout -> IO ()
drawLayout d gc x y (PangoLayout _ pl) =
{#call unsafe draw_layout#} (toDrawable d) (toGC gc)
(fromIntegral x) (fromIntegral y) pl
-- | Draw a paragraph of text.
--
-- * The @x@ and @y@ values specify the upper left
-- point of the layout.
--
-- * If both colors are @Nothing@ this function will behave like
-- 'drawLayout' in that it uses the default colors from
-- the graphics context.
--
drawLayoutWithColors :: DrawableClass d => d -> GC -> Int -> Int ->
PangoLayout -> Maybe Color -> Maybe Color -> IO ()
drawLayoutWithColors d gc x y (PangoLayout _ pl) foreground background = let
withMB :: Storable a => Maybe a -> (Ptr a -> IO b) -> IO b
withMB Nothing f = f nullPtr
withMB (Just x) f = with x f
in
withMB foreground $ \fPtr -> withMB background $ \bPtr ->
{#call unsafe draw_layout_with_colors#} (toDrawable d) (toGC gc)
(fromIntegral x) (fromIntegral y) pl (castPtr fPtr) (castPtr bPtr)
-- | Copies another 'Drawable'.
--
-- * Copies the (width,height) region of the @src@ at coordinates
-- (@xSrc@, @ySrc@) to coordinates (@xDest@,
-- @yDest@) in the @dest@. The @width@ and\/or
-- @height@ may be given as -1, in which case the entire source
-- drawable will be copied.
--
-- * Most fields in @gc@ are not used for this operation, but
-- notably the clip mask or clip region will be honored. The source and
-- destination drawables must have the same visual and colormap, or
-- errors will result. (On X11, failure to match visual\/colormap results
-- in a BadMatch error from the X server.) A common cause of this
-- problem is an attempt to draw a bitmap to a color drawable. The way to
-- draw a bitmap is to set the bitmap as a clip mask on your
-- 'GC', then use 'drawRectangle' to draw a
-- rectangle clipped to the bitmap.
--
drawDrawable :: (DrawableClass src, DrawableClass dest) =>
dest -> GC -> src -> Int -> Int -> Int -> Int ->
Int -> Int -> IO ()
drawDrawable dest gc src xSrc ySrc xDest yDest width height =
{#call unsafe draw_drawable#} (toDrawable dest) (toGC gc)
(toDrawable src)
(fromIntegral xSrc) (fromIntegral ySrc) (fromIntegral xDest)
(fromIntegral yDest) (fromIntegral width) (fromIntegral height)
|