| 141 | }); |
| 142 | } |
| 143 | static void setupFontRender(CLI::App& font) |
| 144 | { |
| 145 | auto* cmd = font.add_subcommand("render", "Render font to PNG file"); |
| 146 | static std::string inputPath; |
| 147 | static std::string outputPath; |
| 148 | static std::string sampleText; |
| 149 | cmd->add_option("input", inputPath, "Input FXY font file")->required()->check(CLI::ExistingFile); |
| 150 | cmd->add_option("-o,--output", outputPath, "Output image file (.png, .bmp, .tga)")->required(); |
| 151 | cmd->add_option("--text", sampleText, "Custom text (default: charmap grid)"); |
| 152 | |
| 153 | cmd->callback( |
| 154 | []() |
| 155 | { |
| 156 | Poseidon::FontPreviewOptions opts; |
| 157 | if (!sampleText.empty()) |
| 158 | opts.sampleText = sampleText; |
| 159 | else |
| 160 | opts.charmap = true; |
| 161 | |
| 162 | auto preview = Poseidon::PreviewFont(inputPath, opts); |
| 163 | if (!preview.valid()) |
| 164 | { |
| 165 | std::cerr << "Error: Failed to render font" << std::endl; |
| 166 | throw CLI::RuntimeError(1); |
| 167 | } |
| 168 | |
| 169 | if (!preview.saveToFile(outputPath)) |
| 170 | { |
| 171 | std::cerr << "Error: Failed to write output" << std::endl; |
| 172 | throw CLI::RuntimeError(1); |
| 173 | } |
| 174 | |
| 175 | std::cout << "Rendered: " << outputPath << " (" << preview.width << "x" << preview.height << ")" |
| 176 | << std::endl; |
| 177 | }); |
| 178 | } |
| 179 | |
| 180 | // Mirror of Font.cpp's BucketFTPixelSize (not exported): snap an ideal pixel |
| 181 | // size to the 4px grid the FreeType atlas actually rasterizes at. |
no test coverage detected