{- |
Copyright  : Will Thompson, Iñaki García Etxebarria and Jonas Platte
License    : LGPL-2.1
Maintainer : Iñaki García Etxebarria (garetxe@gmail.com)

The 'GI.Pango.Objects.Font.Font' structure is used to represent
a font in a rendering-system-independent matter.
To create an implementation of a 'GI.Pango.Objects.Font.Font',
the rendering-system specific code should allocate
a larger structure that contains a nested
'GI.Pango.Objects.Font.Font', fill in the \<structfield>klass\<\/structfield> member of
the nested 'GI.Pango.Objects.Font.Font' with a pointer to
a appropriate 'GI.Pango.Structs.FontClass.FontClass', then call
@/pango_font_init()/@ on the structure.

The 'GI.Pango.Objects.Font.Font' structure contains one member
which the implementation fills in.
-}

module GI.Pango.Objects.Font
    ( 

-- * Exported types
    Font(..)                                ,
    IsFont                                  ,
    toFont                                  ,
    noFont                                  ,


 -- * Methods
-- ** describe #method:describe#
    FontDescribeMethodInfo                  ,
    fontDescribe                            ,


-- ** describeWithAbsoluteSize #method:describeWithAbsoluteSize#
    FontDescribeWithAbsoluteSizeMethodInfo  ,
    fontDescribeWithAbsoluteSize            ,


-- ** descriptionsFree #method:descriptionsFree#
    fontDescriptionsFree                    ,


-- ** getFontMap #method:getFontMap#
    FontGetFontMapMethodInfo                ,
    fontGetFontMap                          ,


-- ** getGlyphExtents #method:getGlyphExtents#
    FontGetGlyphExtentsMethodInfo           ,
    fontGetGlyphExtents                     ,


-- ** getMetrics #method:getMetrics#
    FontGetMetricsMethodInfo                ,
    fontGetMetrics                          ,




    ) where

import Data.GI.Base.ShortPrelude
import qualified Data.GI.Base.ShortPrelude as SP
import qualified Data.GI.Base.Overloading as O
import qualified Prelude as P

import qualified Data.GI.Base.Attributes as GI.Attributes
import qualified Data.GI.Base.ManagedPtr as B.ManagedPtr
import qualified Data.GI.Base.GError as B.GError
import qualified Data.GI.Base.GVariant as B.GVariant
import qualified Data.GI.Base.GParamSpec as B.GParamSpec
import qualified Data.GI.Base.CallStack as B.CallStack
import qualified Data.Text as T
import qualified Data.ByteString.Char8 as B
import qualified Data.Map as Map
import qualified Foreign.Ptr as FP

import qualified GI.GObject.Objects.Object as GObject.Object
import {-# SOURCE #-} qualified GI.Pango.Objects.FontMap as Pango.FontMap
import {-# SOURCE #-} qualified GI.Pango.Structs.FontDescription as Pango.FontDescription
import {-# SOURCE #-} qualified GI.Pango.Structs.FontMetrics as Pango.FontMetrics
import {-# SOURCE #-} qualified GI.Pango.Structs.Language as Pango.Language
import {-# SOURCE #-} qualified GI.Pango.Structs.Rectangle as Pango.Rectangle

newtype Font = Font (ManagedPtr Font)
foreign import ccall "pango_font_get_type"
    c_pango_font_get_type :: IO GType

instance GObject Font where
    gobjectType _ = c_pango_font_get_type
    

class GObject o => IsFont o
#if MIN_VERSION_base(4,9,0)
instance {-# OVERLAPPABLE #-} (GObject a, O.UnknownAncestorError Font a) =>
    IsFont a
#endif
instance IsFont Font
instance GObject.Object.IsObject Font

toFont :: IsFont o => o -> IO Font
toFont = unsafeCastTo Font

noFont :: Maybe Font
noFont = Nothing

type family ResolveFontMethod (t :: Symbol) (o :: *) :: * where
    ResolveFontMethod "bindProperty" o = GObject.Object.ObjectBindPropertyMethodInfo
    ResolveFontMethod "bindPropertyFull" o = GObject.Object.ObjectBindPropertyFullMethodInfo
    ResolveFontMethod "describe" o = FontDescribeMethodInfo
    ResolveFontMethod "describeWithAbsoluteSize" o = FontDescribeWithAbsoluteSizeMethodInfo
    ResolveFontMethod "forceFloating" o = GObject.Object.ObjectForceFloatingMethodInfo
    ResolveFontMethod "freezeNotify" o = GObject.Object.ObjectFreezeNotifyMethodInfo
    ResolveFontMethod "isFloating" o = GObject.Object.ObjectIsFloatingMethodInfo
    ResolveFontMethod "notify" o = GObject.Object.ObjectNotifyMethodInfo
    ResolveFontMethod "notifyByPspec" o = GObject.Object.ObjectNotifyByPspecMethodInfo
    ResolveFontMethod "ref" o = GObject.Object.ObjectRefMethodInfo
    ResolveFontMethod "refSink" o = GObject.Object.ObjectRefSinkMethodInfo
    ResolveFontMethod "replaceData" o = GObject.Object.ObjectReplaceDataMethodInfo
    ResolveFontMethod "replaceQdata" o = GObject.Object.ObjectReplaceQdataMethodInfo
    ResolveFontMethod "runDispose" o = GObject.Object.ObjectRunDisposeMethodInfo
    ResolveFontMethod "stealData" o = GObject.Object.ObjectStealDataMethodInfo
    ResolveFontMethod "stealQdata" o = GObject.Object.ObjectStealQdataMethodInfo
    ResolveFontMethod "thawNotify" o = GObject.Object.ObjectThawNotifyMethodInfo
    ResolveFontMethod "unref" o = GObject.Object.ObjectUnrefMethodInfo
    ResolveFontMethod "watchClosure" o = GObject.Object.ObjectWatchClosureMethodInfo
    ResolveFontMethod "getData" o = GObject.Object.ObjectGetDataMethodInfo
    ResolveFontMethod "getFontMap" o = FontGetFontMapMethodInfo
    ResolveFontMethod "getGlyphExtents" o = FontGetGlyphExtentsMethodInfo
    ResolveFontMethod "getMetrics" o = FontGetMetricsMethodInfo
    ResolveFontMethod "getProperty" o = GObject.Object.ObjectGetPropertyMethodInfo
    ResolveFontMethod "getQdata" o = GObject.Object.ObjectGetQdataMethodInfo
    ResolveFontMethod "setData" o = GObject.Object.ObjectSetDataMethodInfo
    ResolveFontMethod "setProperty" o = GObject.Object.ObjectSetPropertyMethodInfo
    ResolveFontMethod l o = O.MethodResolutionFailed l o

instance (info ~ ResolveFontMethod t Font, O.MethodInfo info Font p) => O.IsLabelProxy t (Font -> p) where
    fromLabelProxy _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)

#if MIN_VERSION_base(4,9,0)
instance (info ~ ResolveFontMethod t Font, O.MethodInfo info Font p) => O.IsLabel t (Font -> p) where
    fromLabel _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)
#endif

instance O.HasAttributeList Font
type instance O.AttributeList Font = FontAttributeList
type FontAttributeList = ('[ ] :: [(Symbol, *)])

type instance O.SignalList Font = FontSignalList
type FontSignalList = ('[ '("notify", GObject.Object.ObjectNotifySignalInfo)] :: [(Symbol, *)])

-- method Font::describe
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "font", argType = TInterface (Name {namespace = "Pango", name = "Font"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #PangoFont", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Pango", name = "FontDescription"}))
-- throws : False
-- Skip return : False

foreign import ccall "pango_font_describe" pango_font_describe :: 
    Ptr Font ->                             -- font : TInterface (Name {namespace = "Pango", name = "Font"})
    IO (Ptr Pango.FontDescription.FontDescription)

{- |
Returns a description of the font, with font size set in points.
Use 'GI.Pango.Objects.Font.fontDescribeWithAbsoluteSize' if you want the font
size in device units.
-}
fontDescribe ::
    (B.CallStack.HasCallStack, MonadIO m, IsFont a) =>
    a
    {- ^ /@font@/: a 'GI.Pango.Objects.Font.Font' -}
    -> m Pango.FontDescription.FontDescription
    {- ^ __Returns:__ a newly-allocated 'GI.Pango.Structs.FontDescription.FontDescription' object. -}
fontDescribe font = liftIO $ do
    font' <- unsafeManagedPtrCastPtr font
    result <- pango_font_describe font'
    checkUnexpectedReturnNULL "fontDescribe" result
    result' <- (wrapBoxed Pango.FontDescription.FontDescription) result
    touchManagedPtr font
    return result'

data FontDescribeMethodInfo
instance (signature ~ (m Pango.FontDescription.FontDescription), MonadIO m, IsFont a) => O.MethodInfo FontDescribeMethodInfo a signature where
    overloadedMethod _ = fontDescribe

-- method Font::describe_with_absolute_size
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "font", argType = TInterface (Name {namespace = "Pango", name = "Font"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #PangoFont", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Pango", name = "FontDescription"}))
-- throws : False
-- Skip return : False

foreign import ccall "pango_font_describe_with_absolute_size" pango_font_describe_with_absolute_size :: 
    Ptr Font ->                             -- font : TInterface (Name {namespace = "Pango", name = "Font"})
    IO (Ptr Pango.FontDescription.FontDescription)

{- |
Returns a description of the font, with absolute font size set
(in device units). Use 'GI.Pango.Objects.Font.fontDescribe' if you want the font
size in points.

@since 1.14
-}
fontDescribeWithAbsoluteSize ::
    (B.CallStack.HasCallStack, MonadIO m, IsFont a) =>
    a
    {- ^ /@font@/: a 'GI.Pango.Objects.Font.Font' -}
    -> m Pango.FontDescription.FontDescription
    {- ^ __Returns:__ a newly-allocated 'GI.Pango.Structs.FontDescription.FontDescription' object. -}
fontDescribeWithAbsoluteSize font = liftIO $ do
    font' <- unsafeManagedPtrCastPtr font
    result <- pango_font_describe_with_absolute_size font'
    checkUnexpectedReturnNULL "fontDescribeWithAbsoluteSize" result
    result' <- (wrapBoxed Pango.FontDescription.FontDescription) result
    touchManagedPtr font
    return result'

data FontDescribeWithAbsoluteSizeMethodInfo
instance (signature ~ (m Pango.FontDescription.FontDescription), MonadIO m, IsFont a) => O.MethodInfo FontDescribeWithAbsoluteSizeMethodInfo a signature where
    overloadedMethod _ = fontDescribeWithAbsoluteSize

-- method Font::get_font_map
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "font", argType = TInterface (Name {namespace = "Pango", name = "Font"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #PangoFont, or %NULL", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Pango", name = "FontMap"}))
-- throws : False
-- Skip return : False

foreign import ccall "pango_font_get_font_map" pango_font_get_font_map :: 
    Ptr Font ->                             -- font : TInterface (Name {namespace = "Pango", name = "Font"})
    IO (Ptr Pango.FontMap.FontMap)

{- |
Gets the font map for which the font was created.

Note that the font maintains a \<firstterm>weak\<\/firstterm> reference
to the font map, so if all references to font map are dropped, the font
map will be finalized even if there are fonts created with the font
map that are still alive.  In that case this function will return 'Nothing'.
It is the responsibility of the user to ensure that the font map is kept
alive.  In most uses this is not an issue as a 'GI.Pango.Objects.Context.Context' holds
a reference to the font map.

@since 1.10
-}
fontGetFontMap ::
    (B.CallStack.HasCallStack, MonadIO m, IsFont a) =>
    a
    {- ^ /@font@/: a 'GI.Pango.Objects.Font.Font', or 'Nothing' -}
    -> m (Maybe Pango.FontMap.FontMap)
    {- ^ __Returns:__ the 'GI.Pango.Objects.FontMap.FontMap' for the
              font, or 'Nothing' if /@font@/ is 'Nothing'. -}
fontGetFontMap font = liftIO $ do
    font' <- unsafeManagedPtrCastPtr font
    result <- pango_font_get_font_map font'
    maybeResult <- convertIfNonNull result $ \result' -> do
        result'' <- (newObject Pango.FontMap.FontMap) result'
        return result''
    touchManagedPtr font
    return maybeResult

data FontGetFontMapMethodInfo
instance (signature ~ (m (Maybe Pango.FontMap.FontMap)), MonadIO m, IsFont a) => O.MethodInfo FontGetFontMapMethodInfo a signature where
    overloadedMethod _ = fontGetFontMap

-- method Font::get_glyph_extents
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "font", argType = TInterface (Name {namespace = "Pango", name = "Font"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #PangoFont", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "glyph", argType = TBasicType TUInt32, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "the glyph index", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "ink_rect", argType = TInterface (Name {namespace = "Pango", name = "Rectangle"}), direction = DirectionOut, mayBeNull = False, argDoc = Documentation {rawDocText = Just "rectangle used to store the extents of the glyph\n           as drawn or %NULL to indicate that the result is not needed.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = True, transfer = TransferNothing},Arg {argCName = "logical_rect", argType = TInterface (Name {namespace = "Pango", name = "Rectangle"}), direction = DirectionOut, mayBeNull = False, argDoc = Documentation {rawDocText = Just "rectangle used to store the logical extents of\n           the glyph or %NULL to indicate that the result is not needed.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = True, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "pango_font_get_glyph_extents" pango_font_get_glyph_extents :: 
    Ptr Font ->                             -- font : TInterface (Name {namespace = "Pango", name = "Font"})
    Word32 ->                               -- glyph : TBasicType TUInt32
    Ptr Pango.Rectangle.Rectangle ->        -- ink_rect : TInterface (Name {namespace = "Pango", name = "Rectangle"})
    Ptr Pango.Rectangle.Rectangle ->        -- logical_rect : TInterface (Name {namespace = "Pango", name = "Rectangle"})
    IO ()

{- |
Gets the logical and ink extents of a glyph within a font. The
coordinate system for each rectangle has its origin at the
base line and horizontal origin of the character with increasing
coordinates extending to the right and down. The macros @/PANGO_ASCENT()/@,
@/PANGO_DESCENT()/@, @/PANGO_LBEARING()/@, and @/PANGO_RBEARING()/@ can be used to convert
from the extents rectangle to more traditional font metrics. The units
of the rectangles are in 1\/PANGO_SCALE of a device unit.

If /@font@/ is 'Nothing', this function gracefully sets some sane values in the
output variables and returns.
-}
fontGetGlyphExtents ::
    (B.CallStack.HasCallStack, MonadIO m, IsFont a) =>
    a
    {- ^ /@font@/: a 'GI.Pango.Objects.Font.Font' -}
    -> Word32
    {- ^ /@glyph@/: the glyph index -}
    -> m (Pango.Rectangle.Rectangle,Pango.Rectangle.Rectangle)
fontGetGlyphExtents font glyph = liftIO $ do
    font' <- unsafeManagedPtrCastPtr font
    inkRect <- callocBytes 16 :: IO (Ptr Pango.Rectangle.Rectangle)
    logicalRect <- callocBytes 16 :: IO (Ptr Pango.Rectangle.Rectangle)
    pango_font_get_glyph_extents font' glyph inkRect logicalRect
    inkRect' <- (wrapPtr Pango.Rectangle.Rectangle) inkRect
    logicalRect' <- (wrapPtr Pango.Rectangle.Rectangle) logicalRect
    touchManagedPtr font
    return (inkRect', logicalRect')

data FontGetGlyphExtentsMethodInfo
instance (signature ~ (Word32 -> m (Pango.Rectangle.Rectangle,Pango.Rectangle.Rectangle)), MonadIO m, IsFont a) => O.MethodInfo FontGetGlyphExtentsMethodInfo a signature where
    overloadedMethod _ = fontGetGlyphExtents

-- method Font::get_metrics
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "font", argType = TInterface (Name {namespace = "Pango", name = "Font"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #PangoFont", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "language", argType = TInterface (Name {namespace = "Pango", name = "Language"}), direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "language tag used to determine which script to get the metrics\n           for, or %NULL to indicate to get the metrics for the entire font.", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TInterface (Name {namespace = "Pango", name = "FontMetrics"}))
-- throws : False
-- Skip return : False

foreign import ccall "pango_font_get_metrics" pango_font_get_metrics :: 
    Ptr Font ->                             -- font : TInterface (Name {namespace = "Pango", name = "Font"})
    Ptr Pango.Language.Language ->          -- language : TInterface (Name {namespace = "Pango", name = "Language"})
    IO (Ptr Pango.FontMetrics.FontMetrics)

{- |
Gets overall metric information for a font. Since the metrics may be
substantially different for different scripts, a language tag can
be provided to indicate that the metrics should be retrieved that
correspond to the script(s) used by that language.

If /@font@/ is 'Nothing', this function gracefully sets some sane values in the
output variables and returns.
-}
fontGetMetrics ::
    (B.CallStack.HasCallStack, MonadIO m, IsFont a) =>
    a
    {- ^ /@font@/: a 'GI.Pango.Objects.Font.Font' -}
    -> Maybe (Pango.Language.Language)
    {- ^ /@language@/: language tag used to determine which script to get the metrics
           for, or 'Nothing' to indicate to get the metrics for the entire font. -}
    -> m Pango.FontMetrics.FontMetrics
    {- ^ __Returns:__ a 'GI.Pango.Structs.FontMetrics.FontMetrics' object. The caller must call 'GI.Pango.Structs.FontMetrics.fontMetricsUnref'
  when finished using the object. -}
fontGetMetrics font language = liftIO $ do
    font' <- unsafeManagedPtrCastPtr font
    maybeLanguage <- case language of
        Nothing -> return nullPtr
        Just jLanguage -> do
            jLanguage' <- unsafeManagedPtrGetPtr jLanguage
            return jLanguage'
    result <- pango_font_get_metrics font' maybeLanguage
    checkUnexpectedReturnNULL "fontGetMetrics" result
    result' <- (wrapBoxed Pango.FontMetrics.FontMetrics) result
    touchManagedPtr font
    whenJust language touchManagedPtr
    return result'

data FontGetMetricsMethodInfo
instance (signature ~ (Maybe (Pango.Language.Language) -> m Pango.FontMetrics.FontMetrics), MonadIO m, IsFont a) => O.MethodInfo FontGetMetricsMethodInfo a signature where
    overloadedMethod _ = fontGetMetrics

-- method Font::descriptions_free
-- method type : MemberFunction
-- Args : [Arg {argCName = "descs", argType = TCArray False (-1) 1 (TInterface (Name {namespace = "Pango", name = "FontDescription"})), direction = DirectionIn, mayBeNull = True, argDoc = Documentation {rawDocText = Just "a pointer\nto an array of #PangoFontDescription, may be %NULL", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferEverything},Arg {argCName = "n_descs", argType = TBasicType TInt, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "number of font descriptions in @descs", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : [Arg {argCName = "n_descs", argType = TBasicType TInt, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "number of font descriptions in @descs", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "pango_font_descriptions_free" pango_font_descriptions_free :: 
    Ptr (Ptr Pango.FontDescription.FontDescription) -> -- descs : TCArray False (-1) 1 (TInterface (Name {namespace = "Pango", name = "FontDescription"}))
    Int32 ->                                -- n_descs : TBasicType TInt
    IO ()

{- |
Frees an array of font descriptions.
-}
fontDescriptionsFree ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Maybe ([Pango.FontDescription.FontDescription])
    {- ^ /@descs@/: a pointer
to an array of 'GI.Pango.Structs.FontDescription.FontDescription', may be 'Nothing' -}
    -> m ()
fontDescriptionsFree descs = liftIO $ do
    let nDescs = case descs of
            Nothing -> 0
            Just jDescs -> fromIntegral $ length jDescs
    maybeDescs <- case descs of
        Nothing -> return nullPtr
        Just jDescs -> do
            jDescs' <- mapM B.ManagedPtr.disownBoxed jDescs
            jDescs'' <- packPtrArray jDescs'
            return jDescs''
    pango_font_descriptions_free maybeDescs nDescs
    whenJust descs (mapM_ touchManagedPtr)
    return ()