import from github
This commit is contained in:
1
tools/rsfont/.gitignore
vendored
Normal file
1
tools/rsfont/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
rsfont
|
19
tools/rsfont/LICENSE
Normal file
19
tools/rsfont/LICENSE
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2015-2016 YamaArashi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
24
tools/rsfont/Makefile
Normal file
24
tools/rsfont/Makefile
Normal file
@ -0,0 +1,24 @@
|
||||
CC ?= gcc
|
||||
|
||||
CFLAGS = -Wall -Wextra -Werror -std=c11 -O2 -DPNG_SKIP_SETJMP_CHECK
|
||||
|
||||
LIBS = -lpng -lz
|
||||
|
||||
SRCS = main.c convert_png.c util.c font.c
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
EXE := .exe
|
||||
else
|
||||
EXE :=
|
||||
endif
|
||||
|
||||
all: rsfont$(EXE)
|
||||
@:
|
||||
|
||||
rsfont$(EXE): $(SRCS) convert_png.h gfx.h global.h util.h font.h
|
||||
$(CC) $(CFLAGS) $(SRCS) -o $@ $(LDFLAGS) $(LIBS)
|
||||
|
||||
clean:
|
||||
$(RM) rsfont rsfont.exe
|
169
tools/rsfont/convert_png.c
Normal file
169
tools/rsfont/convert_png.c
Normal file
@ -0,0 +1,169 @@
|
||||
// Copyright (c) 2015 YamaArashi
|
||||
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <png.h>
|
||||
#include "global.h"
|
||||
#include "convert_png.h"
|
||||
#include "gfx.h"
|
||||
|
||||
void ReadPng(char *path, struct Image *image)
|
||||
{
|
||||
FILE *fp = fopen(path, "rb");
|
||||
|
||||
if (fp == NULL)
|
||||
FATAL_ERROR("Failed to open \"%s\" for reading.\n", path);
|
||||
|
||||
unsigned char sig[8];
|
||||
|
||||
if (fread(sig, 8, 1, fp) != 1)
|
||||
FATAL_ERROR("Failed to read PNG signature from \"%s\".\n", path);
|
||||
|
||||
if (png_sig_cmp(sig, 0, 8))
|
||||
FATAL_ERROR("\"%s\" does not have a valid PNG signature.\n", path);
|
||||
|
||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
|
||||
if (!png_ptr)
|
||||
FATAL_ERROR("Failed to create PNG read struct.\n");
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
|
||||
if (!info_ptr)
|
||||
FATAL_ERROR("Failed to create PNG info struct.\n");
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
FATAL_ERROR("Failed to init I/O for reading \"%s\".\n", path);
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
png_set_sig_bytes(png_ptr, 8);
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
||||
|
||||
if (bit_depth != image->bitDepth)
|
||||
FATAL_ERROR("\"%s\" has a bit depth of %d, but the expected bit depth is %d.\n", path, bit_depth, image->bitDepth);
|
||||
|
||||
int color_type = png_get_color_type(png_ptr, info_ptr);
|
||||
|
||||
if (color_type != PNG_COLOR_TYPE_GRAY && color_type != PNG_COLOR_TYPE_PALETTE)
|
||||
FATAL_ERROR("\"%s\" has an unsupported color type.\n", path);
|
||||
|
||||
// Check if the image has a palette so that we can tell if the colors need to be inverted later.
|
||||
// Don't read the palette because it's not needed for now.
|
||||
image->hasPalette = (color_type == PNG_COLOR_TYPE_PALETTE);
|
||||
|
||||
image->width = png_get_image_width(png_ptr, info_ptr);
|
||||
image->height = png_get_image_height(png_ptr, info_ptr);
|
||||
|
||||
int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
|
||||
image->pixels = malloc(image->height * rowbytes);
|
||||
|
||||
if (image->pixels == NULL)
|
||||
FATAL_ERROR("Failed to allocate pixel buffer.\n");
|
||||
|
||||
png_bytepp row_pointers = malloc(image->height * sizeof(png_bytep));
|
||||
|
||||
if (row_pointers == NULL)
|
||||
FATAL_ERROR("Failed to allocate row pointers.\n");
|
||||
|
||||
for (int i = 0; i < image->height; i++)
|
||||
row_pointers[i] = (png_bytep)(image->pixels + (i * rowbytes));
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
FATAL_ERROR("Error reading from \"%s\".\n", path);
|
||||
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
|
||||
free(row_pointers);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void SetPngPalette(png_structp png_ptr, png_infop info_ptr, struct Palette *palette)
|
||||
{
|
||||
png_colorp colors = malloc(palette->numColors * sizeof(png_color));
|
||||
|
||||
if (colors == NULL)
|
||||
FATAL_ERROR("Failed to allocate PNG palette.\n");
|
||||
|
||||
for (int i = 0; i < palette->numColors; i++) {
|
||||
colors[i].red = palette->colors[i].red;
|
||||
colors[i].green = palette->colors[i].green;
|
||||
colors[i].blue = palette->colors[i].blue;
|
||||
}
|
||||
|
||||
png_set_PLTE(png_ptr, info_ptr, colors, palette->numColors);
|
||||
|
||||
free(colors);
|
||||
}
|
||||
|
||||
void WritePng(char *path, struct Image *image)
|
||||
{
|
||||
FILE *fp = fopen(path, "wb");
|
||||
|
||||
if (fp == NULL)
|
||||
FATAL_ERROR("Failed to open \"%s\" for writing.\n", path);
|
||||
|
||||
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
|
||||
if (!png_ptr)
|
||||
FATAL_ERROR("Failed to create PNG write struct.\n");
|
||||
|
||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||
|
||||
if (!info_ptr)
|
||||
FATAL_ERROR("Failed to create PNG info struct.\n");
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
FATAL_ERROR("Failed to init I/O for writing \"%s\".\n", path);
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
FATAL_ERROR("Error writing header for \"%s\".\n", path);
|
||||
|
||||
int color_type = image->hasPalette ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_GRAY;
|
||||
|
||||
png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
|
||||
image->bitDepth, color_type, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
|
||||
if (image->hasPalette) {
|
||||
SetPngPalette(png_ptr, info_ptr, &image->palette);
|
||||
|
||||
if (image->hasTransparency) {
|
||||
png_byte trans = 0;
|
||||
png_set_tRNS(png_ptr, info_ptr, &trans, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
png_bytepp row_pointers = malloc(image->height * sizeof(png_bytep));
|
||||
|
||||
if (row_pointers == NULL)
|
||||
FATAL_ERROR("Failed to allocate row pointers.\n");
|
||||
|
||||
int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
||||
|
||||
for (int i = 0; i < image->height; i++)
|
||||
row_pointers[i] = (png_bytep)(image->pixels + (i * rowbytes));
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
FATAL_ERROR("Error writing \"%s\".\n", path);
|
||||
|
||||
png_write_image(png_ptr, row_pointers);
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
FATAL_ERROR("Error ending write of \"%s\".\n", path);
|
||||
|
||||
png_write_end(png_ptr, NULL);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
free(row_pointers);
|
||||
}
|
11
tools/rsfont/convert_png.h
Normal file
11
tools/rsfont/convert_png.h
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2015 YamaArashi
|
||||
|
||||
#ifndef CONVERT_PNG_H
|
||||
#define CONVERT_PNG_H
|
||||
|
||||
#include "gfx.h"
|
||||
|
||||
void ReadPng(char *path, struct Image *image);
|
||||
void WritePng(char *path, struct Image *image);
|
||||
|
||||
#endif // CONVERT_PNG_H
|
455
tools/rsfont/font.c
Normal file
455
tools/rsfont/font.c
Normal file
@ -0,0 +1,455 @@
|
||||
// Copyright(c) 2015-2016 YamaArashi
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "global.h"
|
||||
#include "font.h"
|
||||
#include "gfx.h"
|
||||
#include "util.h"
|
||||
|
||||
unsigned char gFontPalette[][3] =
|
||||
{
|
||||
{0xFF, 0xFF, 0xFF}, // bg (white)
|
||||
{0x38, 0x38, 0x38}, // fg (dark grey)
|
||||
{0xD8, 0xD8, 0xD8}, // shadow (light grey)
|
||||
};
|
||||
|
||||
void ConvertFromTiles1Bpp(unsigned char *src, unsigned char *dest, int numGlyphs, int layout)
|
||||
{
|
||||
for (int glyph = 0; glyph < numGlyphs; glyph++)
|
||||
{
|
||||
if (layout == 0)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
uint8_t srcRow = src[(glyph * 8) + i];
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int x = ((glyph % 16) * 8) + j;
|
||||
int y = ((glyph / 16) * 8) + i;
|
||||
dest[(y * 128) + x] = (srcRow >> (7 - j)) & 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// layout type 1
|
||||
|
||||
int tile1Offset = glyph * 16;
|
||||
int tile2Offset = tile1Offset + 8;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
uint8_t srcRow = src[tile1Offset + i];
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int x = ((glyph % 16) * 8) + j;
|
||||
int y = ((glyph / 16) * 16) + i;
|
||||
dest[(y * 128) + x] = (srcRow >> (7 - j)) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
uint8_t srcRow = src[tile2Offset + i];
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int x = ((glyph % 16) * 8) + j;
|
||||
int y = ((glyph / 16) * 16) + 8 + i;
|
||||
dest[(y * 128) + x] = (srcRow >> (7 - j)) & 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertToTiles1Bpp(unsigned char *src, unsigned char *dest, int numGlyphs, int layout)
|
||||
{
|
||||
for (int glyph = 0; glyph < numGlyphs; glyph++)
|
||||
{
|
||||
if (layout == 0)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
uint8_t destRow = 0;
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int x = ((glyph % 16) * 8) + j;
|
||||
int y = ((glyph / 16) * 8) + i;
|
||||
unsigned char color = src[(y * 128) + x];
|
||||
|
||||
if (color > 1)
|
||||
FATAL_ERROR("More than 2 colors in 1 BPP font.\n");
|
||||
|
||||
destRow <<= 1;
|
||||
destRow |= color;
|
||||
}
|
||||
|
||||
dest[(glyph * 8) + i] = destRow;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// layout type 1
|
||||
|
||||
int tile1Offset = glyph * 16;
|
||||
int tile2Offset = tile1Offset + 8;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
uint8_t destRow = 0;
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int x = ((glyph % 16) * 8) + j;
|
||||
int y = ((glyph / 16) * 16) + i;
|
||||
unsigned char color = src[(y * 128) + x];
|
||||
|
||||
if (color > 1)
|
||||
FATAL_ERROR("More than 2 colors in 1 BPP font.\n");
|
||||
|
||||
destRow <<= 1;
|
||||
destRow |= color;
|
||||
}
|
||||
|
||||
dest[tile1Offset + i] = destRow;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
uint8_t destRow = 0;
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int x = ((glyph % 16) * 8) + j;
|
||||
int y = ((glyph / 16) * 16) + 8 + i;
|
||||
unsigned char color = src[(y * 128) + x];
|
||||
|
||||
if (color > 1)
|
||||
FATAL_ERROR("More than 2 colors in 1 BPP font.\n");
|
||||
|
||||
destRow <<= 1;
|
||||
destRow |= color;
|
||||
}
|
||||
|
||||
dest[tile2Offset + i] = destRow;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertFromTiles4Bpp(unsigned char *src, unsigned char *dest, int numGlyphs, int layout)
|
||||
{
|
||||
static unsigned char table[16] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1,
|
||||
};
|
||||
|
||||
for (int glyph = 0; glyph < numGlyphs; glyph++)
|
||||
{
|
||||
if (layout == 0)
|
||||
{
|
||||
int offset = glyph * 32;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
uint32_t srcRow = (src[offset + 3] << 24)
|
||||
| (src[offset + 2] << 16)
|
||||
| (src[offset + 1] << 8)
|
||||
| src[offset];
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int x = ((glyph % 16) * 8) + j;
|
||||
int y = ((glyph / 16) * 8) + i;
|
||||
dest[(y * 128) + x] = table[srcRow & 0xF];
|
||||
srcRow >>= 4;
|
||||
}
|
||||
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int tile1Offset;
|
||||
int tile2Offset;
|
||||
|
||||
if (layout == 1)
|
||||
{
|
||||
tile1Offset = glyph * 64;
|
||||
tile2Offset = tile1Offset + 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
tile1Offset = ((glyph / 16) * 1024) + ((glyph % 16) * 32);
|
||||
tile2Offset = tile1Offset + 512;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
uint32_t srcRow = (src[tile1Offset + 3] << 24)
|
||||
| (src[tile1Offset + 2] << 16)
|
||||
| (src[tile1Offset + 1] << 8)
|
||||
| src[tile1Offset];
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int x = ((glyph % 16) * 8) + j;
|
||||
int y = ((glyph / 16) * 16) + i;
|
||||
dest[(y * 128) + x] = table[srcRow & 0xF];
|
||||
srcRow >>= 4;
|
||||
}
|
||||
|
||||
tile1Offset += 4;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
uint32_t srcRow = (src[tile2Offset + 3] << 24)
|
||||
| (src[tile2Offset + 2] << 16)
|
||||
| (src[tile2Offset + 1] << 8)
|
||||
| src[tile2Offset];
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int x = ((glyph % 16) * 8) + j;
|
||||
int y = ((glyph / 16) * 16) + 8 + i;
|
||||
dest[(y * 128) + x] = table[srcRow & 0xF];
|
||||
srcRow >>= 4;
|
||||
}
|
||||
|
||||
tile2Offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertToTiles4Bpp(unsigned char *src, unsigned char *dest, int numGlyphs, int layout)
|
||||
{
|
||||
static unsigned char table[3] =
|
||||
{
|
||||
0, 15, 14,
|
||||
};
|
||||
|
||||
for (int glyph = 0; glyph < numGlyphs; glyph++)
|
||||
{
|
||||
if (layout == 0)
|
||||
{
|
||||
int offset = glyph * 32;
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
uint32_t destRow = 0;
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int x = ((glyph % 16) * 8) + j;
|
||||
int y = ((glyph / 16) * 8) + i;
|
||||
unsigned char color = src[(y * 128) + x];
|
||||
|
||||
if (color > 2)
|
||||
FATAL_ERROR("More than 3 colors in 4 BPP font.\n");
|
||||
|
||||
destRow >>= 4;
|
||||
destRow |= (table[color] << 28);
|
||||
}
|
||||
|
||||
dest[offset] = destRow & 0xFF;
|
||||
dest[offset + 1] = (destRow >> 8) & 0xFF;
|
||||
dest[offset + 2] = (destRow >> 16) & 0xFF;
|
||||
dest[offset + 3] = (destRow >> 24) & 0xFF;
|
||||
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int tile1Offset;
|
||||
int tile2Offset;
|
||||
|
||||
if (layout == 1)
|
||||
{
|
||||
tile1Offset = glyph * 64;
|
||||
tile2Offset = tile1Offset + 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
tile1Offset = ((glyph / 16) * 1024) + ((glyph % 16) * 32);
|
||||
tile2Offset = tile1Offset + 512;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
uint32_t destRow = 0;
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int x = ((glyph % 16) * 8) + j;
|
||||
int y = ((glyph / 16) * 16) + i;
|
||||
unsigned char color = src[(y * 128) + x];
|
||||
|
||||
if (color > 2)
|
||||
FATAL_ERROR("More than 3 colors in 4 BPP font.\n");
|
||||
|
||||
destRow >>= 4;
|
||||
destRow |= (table[color] << 28);
|
||||
}
|
||||
|
||||
dest[tile1Offset] = destRow & 0xFF;
|
||||
dest[tile1Offset + 1] = (destRow >> 8) & 0xFF;
|
||||
dest[tile1Offset + 2] = (destRow >> 16) & 0xFF;
|
||||
dest[tile1Offset + 3] = (destRow >> 24) & 0xFF;
|
||||
|
||||
tile1Offset += 4;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
uint32_t destRow = 0;
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int x = ((glyph % 16) * 8) + j;
|
||||
int y = ((glyph / 16) * 16) + 8 + i;
|
||||
unsigned char color = src[(y * 128) + x];
|
||||
|
||||
if (color > 2)
|
||||
FATAL_ERROR("More than 3 colors in 4 BPP font.\n");
|
||||
|
||||
destRow >>= 4;
|
||||
destRow |= (table[color] << 28);
|
||||
}
|
||||
|
||||
dest[tile2Offset] = destRow & 0xFF;
|
||||
dest[tile2Offset + 1] = (destRow >> 8) & 0xFF;
|
||||
dest[tile2Offset + 2] = (destRow >> 16) & 0xFF;
|
||||
dest[tile2Offset + 3] = (destRow >> 24) & 0xFF;
|
||||
|
||||
tile2Offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SetFontPalette(struct Image *image)
|
||||
{
|
||||
image->hasPalette = true;
|
||||
|
||||
image->palette.numColors = 3;
|
||||
|
||||
for (int i = 0; i < image->palette.numColors; i++)
|
||||
{
|
||||
image->palette.colors[i].red = gFontPalette[i][0];
|
||||
image->palette.colors[i].green = gFontPalette[i][1];
|
||||
image->palette.colors[i].blue = gFontPalette[i][2];
|
||||
}
|
||||
|
||||
image->hasTransparency = false;
|
||||
}
|
||||
|
||||
int CalcFileSize(int numGlyphs, int bpp, int layout)
|
||||
{
|
||||
if (layout == 2)
|
||||
{
|
||||
// assume 4 BPP
|
||||
int numFullRows = numGlyphs / 16;
|
||||
int remainder = numGlyphs % 16;
|
||||
int fullRowsSize = numFullRows * 1024;
|
||||
int remainderSize = 0;
|
||||
|
||||
if (remainder != 0)
|
||||
remainderSize = 1024 - (16 - remainder) * 32;
|
||||
|
||||
return fullRowsSize + remainderSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
int tilesPerGlyph = layout > 0 ? 2 : 1;
|
||||
int bytesPerTile = 8 * bpp;
|
||||
return numGlyphs * tilesPerGlyph * bytesPerTile;
|
||||
}
|
||||
}
|
||||
|
||||
void ReadFont(char *path, struct Image *image, int numGlyphs, int bpp, int layout)
|
||||
{
|
||||
int fileSize;
|
||||
unsigned char *buffer = ReadWholeFile(path, &fileSize);
|
||||
|
||||
int expectedFileSize = CalcFileSize(numGlyphs, bpp, layout);
|
||||
|
||||
if (fileSize != expectedFileSize)
|
||||
FATAL_ERROR("The file size is %d but should be %d.\n", fileSize, expectedFileSize);
|
||||
|
||||
int numRows = (numGlyphs + 15) / 16;
|
||||
int rowHeight = layout > 0 ? 16 : 8;
|
||||
|
||||
image->width = 128;
|
||||
image->height = numRows * rowHeight;
|
||||
image->bitDepth = 8;
|
||||
image->pixels = calloc(image->width * image->height, 1);
|
||||
|
||||
if (image->pixels == NULL)
|
||||
FATAL_ERROR("Failed to allocate memory for font.\n");
|
||||
|
||||
if (bpp == 1)
|
||||
ConvertFromTiles1Bpp(buffer, image->pixels, numGlyphs, layout);
|
||||
else
|
||||
ConvertFromTiles4Bpp(buffer, image->pixels, numGlyphs, layout);
|
||||
|
||||
free(buffer);
|
||||
|
||||
SetFontPalette(image);
|
||||
}
|
||||
|
||||
void WriteFont(char *path, struct Image *image, int numGlyphs, int bpp, int layout)
|
||||
{
|
||||
if (image->width != 128)
|
||||
FATAL_ERROR("The width of the font image (%d) is not 128.\n", image->width);
|
||||
|
||||
int numRows = (numGlyphs + 15) / 16;
|
||||
int rowHeight = layout > 0 ? 16 : 8;
|
||||
int expectedHeight = numRows * rowHeight;
|
||||
|
||||
if (image->height < expectedHeight)
|
||||
FATAL_ERROR("The height of the font image (%d) is less than %d.\n", image->height, expectedHeight);
|
||||
|
||||
int fileSize = CalcFileSize(numGlyphs, bpp, layout);
|
||||
|
||||
unsigned char *buffer = calloc(fileSize, 1);
|
||||
|
||||
if (buffer == NULL)
|
||||
FATAL_ERROR("Failed to allocate memory for font.\n");
|
||||
|
||||
if (bpp == 1)
|
||||
ConvertToTiles1Bpp(image->pixels, buffer, numGlyphs, layout);
|
||||
else
|
||||
ConvertToTiles4Bpp(image->pixels, buffer, numGlyphs, layout);
|
||||
|
||||
WriteWholeFile(path, buffer, fileSize);
|
||||
|
||||
free(buffer);
|
||||
}
|
30
tools/rsfont/font.h
Normal file
30
tools/rsfont/font.h
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright(c) 2015-2016 YamaArashi
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#ifndef FONT_H
|
||||
#define FONT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "gfx.h"
|
||||
|
||||
void ReadFont(char *path, struct Image *image, int numGlyphs, int bpp, int layout);
|
||||
void WriteFont(char *path, struct Image *image, int numGlyphs, int bpp, int layout);
|
||||
|
||||
#endif // FONT_H
|
50
tools/rsfont/gfx.h
Normal file
50
tools/rsfont/gfx.h
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright(c) 2015-2016 YamaArashi
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#ifndef GFX_H
|
||||
#define GFX_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct Color
|
||||
{
|
||||
unsigned char red;
|
||||
unsigned char green;
|
||||
unsigned char blue;
|
||||
};
|
||||
|
||||
struct Palette
|
||||
{
|
||||
struct Color colors[256];
|
||||
int numColors;
|
||||
};
|
||||
|
||||
struct Image {
|
||||
int width;
|
||||
int height;
|
||||
int bitDepth;
|
||||
unsigned char *pixels;
|
||||
bool hasPalette;
|
||||
struct Palette palette;
|
||||
bool hasTransparency;
|
||||
};
|
||||
|
||||
#endif // GFX_H
|
31
tools/rsfont/global.h
Normal file
31
tools/rsfont/global.h
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2015 YamaArashi
|
||||
|
||||
#ifndef GLOBAL_H
|
||||
#define GLOBAL_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#define FATAL_ERROR(format, ...) \
|
||||
do { \
|
||||
fprintf(stderr, format, __VA_ARGS__); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
#define UNUSED
|
||||
|
||||
#else
|
||||
|
||||
#define FATAL_ERROR(format, ...) \
|
||||
do { \
|
||||
fprintf(stderr, format, ##__VA_ARGS__); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
#define UNUSED __attribute__((__unused__))
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
#endif // GLOBAL_H
|
93
tools/rsfont/main.c
Normal file
93
tools/rsfont/main.c
Normal file
@ -0,0 +1,93 @@
|
||||
// Copyright(c) 2015-2016 YamaArashi
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include "global.h"
|
||||
#include "util.h"
|
||||
#include "gfx.h"
|
||||
#include "convert_png.h"
|
||||
#include "font.h"
|
||||
|
||||
int ExtensionToBpp(const char *extension)
|
||||
{
|
||||
if (!strcmp(extension, "1bpp"))
|
||||
return 1;
|
||||
else if (!strcmp(extension, "4bpp"))
|
||||
return 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 5)
|
||||
FATAL_ERROR("Usage: rsfont INPUT_FILE OUTPUT_FILE NUM_GLYPHS LAYOUT_TYPE\n");
|
||||
|
||||
char *inputPath = argv[1];
|
||||
char *outputPath = argv[2];
|
||||
char *inputFileExtension = GetFileExtension(inputPath);
|
||||
char *outputFileExtension = GetFileExtension(outputPath);
|
||||
|
||||
if (inputFileExtension == NULL)
|
||||
FATAL_ERROR("Input file \"%s\" has no extension.\n", inputPath);
|
||||
|
||||
if (outputFileExtension == NULL)
|
||||
FATAL_ERROR("Output file \"%s\" has no extension.\n", outputPath);
|
||||
|
||||
int numGlyphs;
|
||||
int bpp;
|
||||
int layout;
|
||||
|
||||
if (!ParseNumber(argv[3], NULL, 10, &numGlyphs))
|
||||
FATAL_ERROR("Failed to parse number of glyphs.\n");
|
||||
|
||||
if (!ParseNumber(argv[4], NULL, 10, &layout))
|
||||
FATAL_ERROR("Failed to parse layout type.\n");
|
||||
|
||||
if (layout < 0 || layout > 2)
|
||||
FATAL_ERROR("Layout type %d is invalid. Layout type must be 0, 1, or 2.\n", layout);
|
||||
|
||||
bool toPng;
|
||||
|
||||
if (!strcmp(inputFileExtension, "png") && (bpp = ExtensionToBpp(outputFileExtension)) != 0)
|
||||
toPng = false;
|
||||
else if ((bpp = ExtensionToBpp(inputFileExtension)) != 0 && !strcmp(outputFileExtension, "png"))
|
||||
toPng = true;
|
||||
else
|
||||
FATAL_ERROR("Don't know how to convert \"%s\" to \"%s\".\n", inputPath, outputPath);
|
||||
|
||||
if (bpp == 1 && layout == 2)
|
||||
FATAL_ERROR("Layout type 2 is not supported with 1 BPP fonts.\n");
|
||||
|
||||
struct Image image;
|
||||
|
||||
if (toPng)
|
||||
{
|
||||
ReadFont(inputPath, &image, numGlyphs, bpp, layout);
|
||||
WritePng(outputPath, &image);
|
||||
}
|
||||
else
|
||||
{
|
||||
image.bitDepth = 8;
|
||||
ReadPng(inputPath, &image);
|
||||
WriteFont(outputPath, &image, numGlyphs, bpp, layout);
|
||||
}
|
||||
}
|
124
tools/rsfont/util.c
Normal file
124
tools/rsfont/util.c
Normal file
@ -0,0 +1,124 @@
|
||||
// Copyright (c) 2015 YamaArashi
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include "global.h"
|
||||
#include "util.h"
|
||||
|
||||
bool ParseNumber(char *s, char **end, int radix, int *intValue)
|
||||
{
|
||||
char *localEnd;
|
||||
|
||||
if (end == NULL)
|
||||
end = &localEnd;
|
||||
|
||||
errno = 0;
|
||||
|
||||
const long longValue = strtol(s, end, radix);
|
||||
|
||||
if (*end == s)
|
||||
return false; // not a number
|
||||
|
||||
if ((longValue == LONG_MIN || longValue == LONG_MAX) && errno == ERANGE)
|
||||
return false;
|
||||
|
||||
if (longValue > INT_MAX)
|
||||
return false;
|
||||
|
||||
if (longValue < INT_MIN)
|
||||
return false;
|
||||
|
||||
*intValue = (int)longValue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char *GetFileExtension(char *path)
|
||||
{
|
||||
char *extension = path;
|
||||
|
||||
while (*extension != 0)
|
||||
extension++;
|
||||
|
||||
while (extension > path && *extension != '.')
|
||||
extension--;
|
||||
|
||||
if (extension == path)
|
||||
return NULL;
|
||||
|
||||
extension++;
|
||||
|
||||
if (*extension == 0)
|
||||
return NULL;
|
||||
|
||||
return extension;
|
||||
}
|
||||
|
||||
unsigned char *ReadWholeFile(char *path, int *size)
|
||||
{
|
||||
FILE *fp = fopen(path, "rb");
|
||||
|
||||
if (fp == NULL)
|
||||
FATAL_ERROR("Failed to open \"%s\" for reading.\n", path);
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
|
||||
*size = ftell(fp);
|
||||
|
||||
unsigned char *buffer = malloc(*size);
|
||||
|
||||
if (buffer == NULL)
|
||||
FATAL_ERROR("Failed to allocate memory for reading \"%s\".\n", path);
|
||||
|
||||
rewind(fp);
|
||||
|
||||
if (fread(buffer, *size, 1, fp) != 1)
|
||||
FATAL_ERROR("Failed to read \"%s\".\n", path);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
unsigned char *ReadWholeFileZeroPadded(char *path, int *size, int padAmount)
|
||||
{
|
||||
FILE *fp = fopen(path, "rb");
|
||||
|
||||
if (fp == NULL)
|
||||
FATAL_ERROR("Failed to open \"%s\" for reading.\n", path);
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
|
||||
*size = ftell(fp);
|
||||
|
||||
unsigned char *buffer = calloc(*size + padAmount, 1);
|
||||
|
||||
if (buffer == NULL)
|
||||
FATAL_ERROR("Failed to allocate memory for reading \"%s\".\n", path);
|
||||
|
||||
rewind(fp);
|
||||
|
||||
if (fread(buffer, *size, 1, fp) != 1)
|
||||
FATAL_ERROR("Failed to read \"%s\".\n", path);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void WriteWholeFile(char *path, void *buffer, int bufferSize)
|
||||
{
|
||||
FILE *fp = fopen(path, "wb");
|
||||
|
||||
if (fp == NULL)
|
||||
FATAL_ERROR("Failed to open \"%s\" for writing.\n", path);
|
||||
|
||||
if (fwrite(buffer, bufferSize, 1, fp) != 1)
|
||||
FATAL_ERROR("Failed to write to \"%s\".\n", path);
|
||||
|
||||
fclose(fp);
|
||||
}
|
14
tools/rsfont/util.h
Normal file
14
tools/rsfont/util.h
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2015 YamaArashi
|
||||
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool ParseNumber(char *s, char **end, int radix, int *intValue);
|
||||
char *GetFileExtension(char *path);
|
||||
unsigned char *ReadWholeFile(char *path, int *size);
|
||||
unsigned char *ReadWholeFileZeroPadded(char *path, int *size, int padAmount);
|
||||
void WriteWholeFile(char *path, void *buffer, int bufferSize);
|
||||
|
||||
#endif // UTIL_H
|
Reference in New Issue
Block a user