summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop/CjkGlyphAtlas.fs
blob: fc19828d86244975b78c4ff926b938c6f549d49f (plain)
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
namespace LivingVillage.Desktop

open System
open System.IO
open Microsoft.Xna.Framework
open Microsoft.Xna.Framework.Graphics

module CjkGlyphAtlas =
    let columns = 16
    let cellPixels = 24

    // Keep this table sorted and stable so the generated PNG has a reproducible layout.
    let private characterTable =
        "×一不主乐乡买于互交人从价传体作使保倍停入关内准出到前力功动助单卖南原友取可同和回围圃在墙备夜大天失好始存完家察对就层居屋已年庄库应度开式当录得心必态怒总恼意戏成或打找报拒择挑据提播操效敌数新方无时明易是晚景暂更最有村板林标档桥歉民水求江没法游物状瓦用留白目石确社离移竹笑精系紧给绝继绪续置聊能范获菜衅观认讨议记讲设话说请读谅谈败资足近返还进迫退选速道量金鉴钱门闭闲间闻附零需面项须食饥饿黛,:"

    let characters = characterTable.ToCharArray()
    let rowCount = (characters.Length + columns - 1) / columns
    let pixelWidth = columns * cellPixels
    let pixelHeight = rowCount * cellPixels
    let assetRelativePath = "Assets/cjk-glyph-atlas.png"
    let manifestRelativePath = "Assets/cjk-glyphs.txt"

    let private indices =
        characters
        |> Array.mapi (fun index character -> character, index)
        |> Map.ofArray

    let contains (character: char) = Map.containsKey character indices

    let sourceRectangle (character: char) =
        indices
        |> Map.tryFind character
        |> Option.map (fun index ->
            Rectangle(
                (index % columns) * cellPixels,
                (index / columns) * cellPixels,
                cellPixels,
                cellPixels))

    let runtimeAssetPath () = Path.Combine(AppContext.BaseDirectory, assetRelativePath)

    let runtimeManifestPath () = Path.Combine(AppContext.BaseDirectory, manifestRelativePath)

    let load (device: GraphicsDevice) : Texture2D =
        let path = runtimeAssetPath ()
        if not (File.Exists path) then
            raise (FileNotFoundException(sprintf "CJK glyph atlas is missing: %s" path, path))

        use stream = File.OpenRead path
        let texture = Texture2D.FromStream(device, stream)
        if texture.Width <> pixelWidth || texture.Height <> pixelHeight then
            texture.Dispose()
            invalidOp (sprintf "CJK glyph atlas has dimensions %dx%d; expected %dx%d." texture.Width texture.Height pixelWidth pixelHeight)
        else
            texture