{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}


{-| Font configuration

IO functions to modify font config values.

-}

module DearImGui.Raw.Font.Config
  ( FontConfig(..)
  , new
  , destroy
    -- * Changing settings
  , setFontDataOwnedByAtlas
  , setFontNo
  , setSizePixels
  , setOversampleH
  , setOversampleV
  , setPixelSnapH
  , setGlyphExtraSpacing
  , setGlyphOffset
  , setGlyphRanges
  , setGlyphMinAdvanceX
  , setGlyphMaxAdvanceX
  , setMergeMode
  , setFontBuilderFlags
  , setRasterizerMultiply
  , setEllipsisChar
  )
  where

-- base
import Control.Monad.IO.Class
  ( MonadIO, liftIO )
import Foreign ( Ptr )
import Foreign.C

-- dear-imgui
import DearImGui.Context
  ( imguiContext )
import DearImGui.Structs
import DearImGui.Raw.Font.GlyphRanges
  ( GlyphRanges(..) )

-- inline-c
import qualified Language.C.Inline as C

-- inline-c-cpp
import qualified Language.C.Inline.Cpp as Cpp

C.context (Cpp.cppCtx <> C.bsCtx <> imguiContext)
C.include "imgui.h"
Cpp.using "namespace ImGui"

-- | Font configuration data handle
--
-- Wraps @ImFontConfig*@.
newtype FontConfig = FontConfig (Ptr ImFontConfig)

-- | Create an instance of config
new :: MonadIO m => m FontConfig
new :: forall (m :: * -> *). MonadIO m => m FontConfig
new = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  Ptr ImFontConfig -> FontConfig
FontConfig forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [C.block|
    ImFontConfig* {
      return IM_NEW(ImFontConfig);
    }
  |]

-- | Destroy an instance of config
--
-- Should be used __after__ font atlas building.
destroy :: MonadIO m => FontConfig -> m ()
destroy :: forall (m :: * -> *). MonadIO m => FontConfig -> m ()
destroy (FontConfig Ptr ImFontConfig
config) = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      IM_DELETE($(ImFontConfig* config));
    }
  |]


-- | TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself).
--
-- By default, it is @true@
setFontDataOwnedByAtlas :: MonadIO m => FontConfig -> CBool -> m ()
setFontDataOwnedByAtlas :: forall (m :: * -> *). MonadIO m => FontConfig -> CBool -> m ()
setFontDataOwnedByAtlas (FontConfig Ptr ImFontConfig
fc) CBool
value = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      $(ImFontConfig* fc)->FontDataOwnedByAtlas = $(bool value);
    }
  |]

-- | Index of font within TTF/OTF file
--
-- By default, it is @0@
setFontNo :: MonadIO m => FontConfig -> CInt -> m ()
setFontNo :: forall (m :: * -> *). MonadIO m => FontConfig -> CInt -> m ()
setFontNo (FontConfig Ptr ImFontConfig
fc) CInt
value = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      $(ImFontConfig* fc)->FontNo = $(int value);
    }
  |]

-- | Size in pixels for rasterizer (more or less maps to the resulting font height).
--
-- Implicitly set by @addFont...@ functions.
setSizePixels :: MonadIO m => FontConfig -> CFloat -> m ()
setSizePixels :: forall (m :: * -> *). MonadIO m => FontConfig -> CFloat -> m ()
setSizePixels (FontConfig Ptr ImFontConfig
fc) CFloat
value = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      $(ImFontConfig* fc)->SizePixels = $(float value);
    }
  |]

-- | Rasterize at higher quality for sub-pixel positioning. Note the difference between 2 and 3 is minimal so you can reduce this to 2 to save memory. Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details.
--
-- By default, it is @3@
setOversampleH :: MonadIO m => FontConfig -> CInt -> m ()
setOversampleH :: forall (m :: * -> *). MonadIO m => FontConfig -> CInt -> m ()
setOversampleH (FontConfig Ptr ImFontConfig
fc) CInt
value = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      $(ImFontConfig* fc)->OversampleH = $(int value);
    }
  |]

-- | Rasterize at higher quality for sub-pixel positioning. This is not really useful as we don't use sub-pixel positions on the Y axis.
--
-- By default, it is @1@
setOversampleV :: MonadIO m => FontConfig -> CInt -> m ()
setOversampleV :: forall (m :: * -> *). MonadIO m => FontConfig -> CInt -> m ()
setOversampleV (FontConfig Ptr ImFontConfig
fc) CInt
value = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      $(ImFontConfig* fc)->OversampleV = $(int value);
    }
  |]

-- | Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1.
--
-- By default, it is @false@
setPixelSnapH :: MonadIO m => FontConfig -> CBool -> m ()
setPixelSnapH :: forall (m :: * -> *). MonadIO m => FontConfig -> CBool -> m ()
setPixelSnapH (FontConfig Ptr ImFontConfig
fc) CBool
value = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      $(ImFontConfig* fc)->PixelSnapH = $(bool value);
    }
  |]

-- | Extra spacing (in pixels) between glyphs. Only X axis is supported for now.
--
-- By default, it is @0, 0@
setGlyphExtraSpacing :: MonadIO m => FontConfig -> Ptr ImVec2 -> m ()
setGlyphExtraSpacing :: forall (m :: * -> *). MonadIO m => FontConfig -> Ptr ImVec2 -> m ()
setGlyphExtraSpacing (FontConfig Ptr ImFontConfig
fc) Ptr ImVec2
value = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      $(ImFontConfig* fc)->GlyphExtraSpacing = *$(ImVec2* value);
    }
  |]

-- | Offset all glyphs from this font input.
--
-- By default, it is @0, 0@
setGlyphOffset :: MonadIO m => FontConfig -> Ptr ImVec2 -> m ()
setGlyphOffset :: forall (m :: * -> *). MonadIO m => FontConfig -> Ptr ImVec2 -> m ()
setGlyphOffset (FontConfig Ptr ImFontConfig
fc) Ptr ImVec2
value = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      $(ImFontConfig* fc)->GlyphOffset = *$(ImVec2* value);
    }
  |]

-- | Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE.
--
-- By default, it is @NULL@
setGlyphRanges :: MonadIO m => FontConfig -> GlyphRanges -> m ()
setGlyphRanges :: forall (m :: * -> *).
MonadIO m =>
FontConfig -> GlyphRanges -> m ()
setGlyphRanges (FontConfig Ptr ImFontConfig
fc) (GlyphRanges Ptr ImWchar
value) = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      $(ImFontConfig* fc)->GlyphRanges = $(ImWchar* value);
    }
  |]

-- | Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font
--
-- By default, it is @0@
setGlyphMinAdvanceX :: MonadIO m => FontConfig -> CFloat -> m ()
setGlyphMinAdvanceX :: forall (m :: * -> *). MonadIO m => FontConfig -> CFloat -> m ()
setGlyphMinAdvanceX (FontConfig Ptr ImFontConfig
fc) CFloat
value = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      $(ImFontConfig* fc)->GlyphMinAdvanceX = $(float value);
    }
  |]

-- | Maximum AdvanceX for glyphs
--
-- By default, it is @FLT_MAX@
setGlyphMaxAdvanceX :: MonadIO m => FontConfig -> CFloat -> m ()
setGlyphMaxAdvanceX :: forall (m :: * -> *). MonadIO m => FontConfig -> CFloat -> m ()
setGlyphMaxAdvanceX (FontConfig Ptr ImFontConfig
fc) CFloat
value = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      $(ImFontConfig* fc)->GlyphMaxAdvanceX = $(float value);
    }
  |]

-- | Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights.
--
-- By default, it is @false@
setMergeMode :: MonadIO m => FontConfig -> CBool -> m ()
setMergeMode :: forall (m :: * -> *). MonadIO m => FontConfig -> CBool -> m ()
setMergeMode (FontConfig Ptr ImFontConfig
fc) CBool
value = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      $(ImFontConfig* fc)->MergeMode = $(bool value);
    }
  |]

-- | Settings for custom font builder.
-- THIS IS BUILDER IMPLEMENTATION DEPENDENT.
--
-- By default, it is @0@. Leave it so if unsure.
setFontBuilderFlags :: MonadIO m => FontConfig -> CUInt -> m ()
setFontBuilderFlags :: forall (m :: * -> *). MonadIO m => FontConfig -> CUInt -> m ()
setFontBuilderFlags (FontConfig Ptr ImFontConfig
fc) CUInt
value = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      $(ImFontConfig* fc)->FontBuilderFlags = $(unsigned int value);
    }
  |]

-- | Brighten (>1.0f) or darken (<1.0f) font output.
-- Brightening small fonts may be a good workaround to make them more readable.
--
-- By default, it is @1.0f@
setRasterizerMultiply :: MonadIO m => FontConfig -> CFloat -> m ()
setRasterizerMultiply :: forall (m :: * -> *). MonadIO m => FontConfig -> CFloat -> m ()
setRasterizerMultiply (FontConfig Ptr ImFontConfig
fc) CFloat
value = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      $(ImFontConfig* fc)->RasterizerMultiply = $(float value);
    }
  |]

-- | Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used.
--
-- By default, it is @-1@
setEllipsisChar :: MonadIO m => FontConfig -> ImWchar -> m ()
setEllipsisChar :: forall (m :: * -> *). MonadIO m => FontConfig -> ImWchar -> m ()
setEllipsisChar (FontConfig Ptr ImFontConfig
fc) ImWchar
value = forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO do
  [C.block|
    void {
      $(ImFontConfig* fc)->EllipsisChar = $(ImWchar value);
    }
  |]