如何在没有Cabal的情况下使用Chart-diagrams的标准字体部署可执行文件

时间:2014-02-04 09:56:07

标签: haskell

我需要在Windows环境中部署应用程序(特定于Window XP),其中我的部署选项几乎仅限于复制.exe或可能的文件夹结构。我正在使用Chart库和新的(ish)Diagrams后端,这对于这种情况来说似乎是完美的。

但是,我很快发现使用Chart's Diagrams后端构建的应用程序引用了具有绝对路径的数据文件(字体SVG),在这种情况下,这些路径深埋在我的开发计算机上的.cabal-sandbox目录中。不用说,当将可执行文件复制到生产工作站时,这不能很好地工作。

这个问题是否有一个非常脆弱的解决方案? (我想我可以通过将repo移动到我的dev comp上的C:\ myrepo \来修改它,在那里构建它,然后确保在生产中将相关文件复制到C:\ myrepo.cabal-sandbox工作站,但它是丑陋和脆弱的!)

1 个答案:

答案 0 :(得分:0)

正如Jan Bracker所指出的那样,Chart-diagrams库/后端提供了提供custom fonts的可能性。随库提供的标准字体可以复制到自定义(相对)位置,并通过此机制重新配置。

根据Jan的指示,我发现了一个可行的解决方案。以下是我最终的结果:

-- | Makes the standard font relocatable.
module LocalFonts (localFonts) where

import qualified Data.Map as M
import Graphics.Rendering.Chart.Backend.Types
import System.FilePath (replaceFileName)


localFonts :: FilePath -> M.Map (String, FontSlant, FontWeight) FilePath
localFonts exec = let
    serifR   = replaceFileName exec "fonts/LinLibertine_R.svg"
    serifRB  = replaceFileName exec "fonts/LinLibertine_RB.svg"
    serifRBI = replaceFileName exec "fonts/LinLibertine_RBI.svg"
    serifRI  = replaceFileName exec "fonts/LinLibertine_RI.svg"
    sansR    = replaceFileName exec "fonts/SourceSansPro_R.svg"
    sansRB   = replaceFileName exec "fonts/SourceSansPro_RB.svg"
    sansRBI  = replaceFileName exec "fonts/SourceSansPro_RBI.svg"
    sansRI   = replaceFileName exec "fonts/SourceSansPro_RI.svg"
    monoR    = replaceFileName exec "fonts/SourceCodePro_R.svg"
    monoRB   = replaceFileName exec "fonts/SourceCodePro_RB.svg"
  in M.fromList
    [ ( ("serif"     , FontSlantNormal , FontWeightNormal) , serifR   )
    , ( ("serif"     , FontSlantNormal , FontWeightBold  ) , serifRB  )
    , ( ("serif"     , FontSlantItalic , FontWeightNormal) , serifRI  )
    , ( ("serif"     , FontSlantOblique, FontWeightNormal) , serifRI  )
    , ( ("serif"     , FontSlantItalic , FontWeightBold  ) , serifRBI )
    , ( ("serif"     , FontSlantOblique, FontWeightBold  ) , serifRBI )

    , ( ("sans-serif", FontSlantNormal , FontWeightNormal) , sansR    )
    , ( ("sans-serif", FontSlantNormal , FontWeightBold  ) , sansRB   )
    , ( ("sans-serif", FontSlantItalic , FontWeightNormal) , sansRI   )
    , ( ("sans-serif", FontSlantOblique, FontWeightNormal) , sansRI   )
    , ( ("sans-serif", FontSlantItalic , FontWeightBold  ) , sansRBI  )
    , ( ("sans-serif", FontSlantOblique, FontWeightBold  ) , sansRBI  )

    , ( ("monospace" , FontSlantNormal , FontWeightNormal) , monoR    )
    , ( ("monospace" , FontSlantNormal , FontWeightBold  ) , monoRB   )
    , ( ("monospace" , FontSlantItalic , FontWeightNormal) , monoR    )
    , ( ("monospace" , FontSlantOblique, FontWeightNormal) , monoR    )
    , ( ("monospace" , FontSlantItalic , FontWeightBold  ) , monoRB   )
    , ( ("monospace" , FontSlantOblique, FontWeightBold  ) , monoRB   )
    ]

在我的应用程序代码中,我将localFonts用于:

  exec <- getExecutablePath  -- from System.Environment
  renderableToFile (localFO exec) ...
  where
    localFO = FileOptions (width opts, height opts) SVG_EMBEDDED . localFonts

然后,在生产中安装时,我将fonts-charts中的fonts目录复制到与可执行文件相同的目录中。适合我的需要。