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