Skip to content

Commit 56da5b3

Browse files
authored
Add experimental spritefont output compatible with xna-cncnet-client (#1)
1 parent ecb3e6b commit 56da5b3

13 files changed

Lines changed: 2785 additions & 17 deletions

File tree

.github/workflows/release.yml

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ jobs:
7979
permissions:
8080
contents: write
8181
steps:
82+
- uses: actions/checkout@v4
83+
8284
- name: Download artifacts
8385
uses: actions/download-artifact@v4
8486
with:
@@ -89,13 +91,42 @@ jobs:
8991
mkdir -p release
9092
find dist -maxdepth 3 -type f -print -exec cp {} release/ \;
9193
94+
- name: Package release archives
95+
run: |
96+
set -euo pipefail
97+
98+
version="${GITHUB_REF_NAME}"
99+
mkdir -p packaged
100+
101+
for file in release/*; do
102+
base="$(basename "${file}")"
103+
stem="${base%.exe}"
104+
stage_dir="$(mktemp -d)"
105+
106+
cp "${file}" "${stage_dir}/"
107+
cp README.md LICENSE THIRD_PARTY_NOTICES.md "${stage_dir}/"
108+
109+
if [[ "${base}" == *.exe ]]; then
110+
asset="packaged/${stem}-${version}.zip"
111+
(
112+
cd "${stage_dir}"
113+
zip -q -r "${GITHUB_WORKSPACE}/${asset}" .
114+
)
115+
else
116+
asset="packaged/${stem}-${version}.tar.gz"
117+
tar -C "${stage_dir}" -czf "${asset}" .
118+
fi
119+
120+
rm -rf "${stage_dir}"
121+
done
122+
92123
- name: Publish GitHub release
93124
uses: softprops/action-gh-release@v2
94125
with:
95126
tag_name: ${{ github.ref_name }}
96127
name: ${{ github.ref_name }}
97128
generate_release_notes: true
98129
fail_on_unmatched_files: true
99-
files: release/*
130+
files: packaged/*
100131
env:
101132
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.vscode/*
22
out_font/*
3+
*.xnb
34
*.fnt
45
/ra2fnt
56
/ra2fnt.exe

README.md

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,16 @@ scripts\build-release.bat v1.0.0
2929

3030
## Usage
3131

32-
Export `.fnt` to PNG set:
32+
Export `.fnt` or `.xnb` to PNG set:
3333

3434
```bash
3535
./ra2fnt export -in game.fnt -out out_font
3636
```
3737

38+
```bash
39+
./ra2fnt export -in SpriteFont.xnb -out out_font
40+
```
41+
3842
Export with integer pixel scaling (for easier editing):
3943

4044
```bash
@@ -53,6 +57,12 @@ Create `.fnt` from PNG set:
5357
./ra2fnt create -in out_font -out rebuilt.fnt
5458
```
5559

60+
Create an experimental LZ4-compressed `SpriteFont XNB v5` font file for [`xna-cncnet-client`](https://github.com/CnCNet/xna-cncnet-client) from PNG set:
61+
62+
```bash
63+
./ra2fnt create -in out_font -out SpriteFont.xnb --format cncnet-spritefont
64+
```
65+
5666
Create without glyph deduplication:
5767

5868
```bash
@@ -78,7 +88,7 @@ If `out` directory already exists, `export` asks for confirmation before deletin
7888

7989
## Export format
8090

81-
`export` writes only PNG files grouped by Unicode ranges:
91+
`export` reads `.fnt` and `cncnet-spritefont` `.xnb` files, and writes only PNG files grouped by Unicode ranges:
8292

8393
```text
8494
out_font/
@@ -107,7 +117,7 @@ Zero-width glyphs are listed only in `metadata.json` (`symbol_width`).
107117

108118
## Create behavior
109119

110-
`create` reconstructs a `.fnt` from PNG files in the input directory:
120+
`create` reconstructs a font file from PNG files in the input directory:
111121

112122
- PNG files are discovered recursively (subdirectory names are ignored by parser).
113123
- Files must be named as fixed-length hex codepoints (for example `0x0041.png`, `0x30A1.png`).
@@ -120,6 +130,9 @@ Zero-width glyphs are listed only in `metadata.json` (`symbol_width`).
120130
- `ideograph_width` is taken from `metadata.json`.
121131
- `scale` is taken from `metadata.json`; when `scale > 1`, PNG dimensions are downscaled by this factor during `create` (back to normal font size).
122132
- Identical glyphs are deduplicated, so multiple codepoints can reference the same symbol index.
133+
- Output format is selected by `--format`:
134+
- `fnt` (default): writes Westwood Unicode BitFont `.fnt`
135+
- `cncnet-spritefont`: writes an experimental LZ4-compressed `SpriteFont XNB v5` `.xnb` font file for [`xna-cncnet-client`](https://github.com/CnCNet/xna-cncnet-client)
123136
- Use `--no-dedup` to disable deduplication.
124137
- Unicode table is rebuilt from filenames (`0xXXXX` -> symbol index in sorted codepoint order).
125138

@@ -141,3 +154,12 @@ Because unicode mapping order/tail bytes are rebuilt, the resulting `.fnt` is no
141154
- At least one non-zero-width PNG is required to infer `symbol_height`.
142155
- Zero-width glyphs are represented only in `metadata.json` and have no PNG files.
143156
- Unicode table order is rebuilt from sorted codepoints.
157+
- `cncnet-spritefont` always writes LZ4-compressed `SpriteFont XNB v5`.
158+
- `cncnet-spritefont` is an experimental feature.
159+
- When `?` is present, `cncnet-spritefont` writes it as `defaultChar` fallback.
160+
- `export` preserves PNG glyph images exactly when round-tripping `out_font -> .xnb -> out_font`.
161+
162+
## License
163+
164+
- Project license: `MIT` (see `LICENSE`)
165+
- Third-party notices: `THIRD_PARTY_NOTICES.md`

THIRD_PARTY_NOTICES.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Third-Party Notices
2+
3+
This project is licensed under the MIT License. It also includes or depends on third-party components under their own licenses.
4+
5+
## `github.com/pierrec/lz4/v4`
6+
7+
- Project: `github.com/pierrec/lz4/v4`
8+
- License: `BSD-3-Clause`
9+
- Source: `https://github.com/pierrec/lz4`
10+
11+
License text:
12+
13+
```text
14+
Copyright (c) 2015, Pierre Curto
15+
All rights reserved.
16+
17+
Redistribution and use in source and binary forms, with or without
18+
modification, are permitted provided that the following conditions are met:
19+
20+
* Redistributions of source code must retain the above copyright notice, this
21+
list of conditions and the following disclaimer.
22+
23+
* Redistributions in binary form must reproduce the above copyright notice,
24+
this list of conditions and the following disclaimer in the documentation
25+
and/or other materials provided with the distribution.
26+
27+
* Neither the name of xxHash nor the names of its
28+
contributors may be used to endorse or promote products derived from
29+
this software without specific prior written permission.
30+
31+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
32+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
35+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
39+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41+
```
42+
43+
## `github.com/secDre4mer/lzx`
44+
45+
- Project: `github.com/secDre4mer/lzx`
46+
- License: `MIT`
47+
- Source: `https://github.com/secDre4mer/lzx`
48+
49+
License text:
50+
51+
```text
52+
MIT License
53+
54+
Copyright (c) 2025 secDre4mer
55+
56+
Permission is hereby granted, free of charge, to any person obtaining a copy
57+
of this software and associated documentation files (the "Software"), to deal
58+
in the Software without restriction, including without limitation the rights
59+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
60+
copies of the Software, and to permit persons to whom the Software is
61+
furnished to do so, subject to the following conditions:
62+
63+
The above copyright notice and this permission notice shall be included in all
64+
copies or substantial portions of the Software.
65+
66+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
67+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
68+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
69+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
70+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
71+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
72+
SOFTWARE.
73+
```

cspell.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,8 @@
33
"language": "en",
44
"allowCompoundWords": true,
55
"useGitignore": true,
6-
"words": []
6+
"words": [
7+
"cncnet",
8+
"dedup"
9+
]
710
}

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
module ra2fnt
22

33
go 1.22
4+
5+
require (
6+
github.com/pierrec/lz4/v4 v4.1.26
7+
github.com/secDre4mer/lzx v0.0.0-20250826110518-fedea00d45a5
8+
)

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
github.com/pierrec/lz4/v4 v4.1.26 h1:GrpZw1gZttORinvzBdXPUXATeqlJjqUG/D87TKMnhjY=
2+
github.com/pierrec/lz4/v4 v4.1.26/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4=
3+
github.com/secDre4mer/lzx v0.0.0-20250826110518-fedea00d45a5 h1:kmHE1qapEHsBpWXyeWR+UCdtZHvSPgYX7VmMeGqnVQI=
4+
github.com/secDre4mer/lzx v0.0.0-20250826110518-fedea00d45a5/go.mod h1:oJAzpWn0j/MLx5UEIq5h9eyWfkk0KEnJ2/Js1oviEzQ=

0 commit comments

Comments
 (0)