Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add transparent index and optimize font rendering with shadows. #730

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ if(MSVC)
string(REGEX REPLACE "/W3" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
# we would probably like to pass /Wall instead of /W4, but there's a lot
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /permissive- /W4")
#LibPNG is not linking on MSVC correctly, disable it.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMIN_BUILD")
Comment on lines +41 to +42
Copy link
Contributor

@Nopey Nopey Nov 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not. see also #769 (merged)

Copy link
Author

@nopjne nopjne Nov 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was temporary you can take it out when 769 is merged. Or I'll discard it it if 769 goes in first.

else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wformat -pedantic -Wvla")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb -DDEBUGMODE -Werror -fno-omit-frame-pointer")
Expand Down Expand Up @@ -235,6 +237,8 @@ add_dependencies(openomf copy_shaders)

# Build tools if requested
set(TOOL_TARGET_NAMES)


# always build languagetool, for BuildLanguages.cmake
add_executable(languagetool tools/languagetool/main.c)
list(APPEND TOOL_TARGET_NAMES languagetool)
Expand Down
3 changes: 2 additions & 1 deletion src/formats/bk.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "formats/internal/writer.h"
#include "formats/palette.h"
#include "formats/pcx.h"
#include "formats/transparent.h"
#include "formats/vga_image.h"
#include "utils/allocator.h"

Expand Down Expand Up @@ -134,7 +135,7 @@ int sd_bk_load(sd_bk_file *bk, const char *filename) {

// Read background image
bk->background = omf_calloc(1, sizeof(sd_vga_image));
if((ret = sd_vga_image_create(bk->background, img_w, img_h)) != SD_SUCCESS) {
if((ret = sd_vga_image_create(bk->background, img_w, img_h, BACKGROUND_TRANSPARENT_INDEX)) != SD_SUCCESS) {
goto exit_0;
}
int bsize = img_w * img_h;
Expand Down
7 changes: 5 additions & 2 deletions src/formats/fonts.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "formats/fonts.h"
#include "formats/internal/reader.h"
#include "formats/internal/writer.h"
#include <assert.h>

int sd_font_create(sd_font *font) {
if(font == NULL) {
Expand Down Expand Up @@ -57,18 +58,20 @@ int sd_font_save(const sd_font *font, const char *file) {
return SD_SUCCESS;
}

int sd_font_decode(const sd_font *font, sd_vga_image *o, uint8_t ch, uint8_t color) {
int sd_font_decode(const sd_font *font, sd_vga_image *o, uint8_t ch, uint8_t color, int transparent) {
if(font == NULL || o == NULL || ch >= 224) {
return SD_INVALID_INPUT;
}

assert((transparent >= 0) && (transparent < 256));

int t = 0;
for(unsigned i = 0; i < font->h; i++) {
for(int k = font->h - 1; k >= 0; k--) {
if(font->chars[ch].data[i] & (1 << k)) {
o->data[t] = color;
} else {
o->data[t] = 0;
o->data[t] = (char)transparent;
Nopey marked this conversation as resolved.
Show resolved Hide resolved
}
t++;
}
Expand Down
2 changes: 1 addition & 1 deletion src/formats/fonts.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ int sd_font_save(const sd_font *font, const char *filename);
* \param ch Character to load. Must be 0 <= ch <= 224.
* \param color Color palette index (0 - 0xFF)
*/
int sd_font_decode(const sd_font *font, sd_vga_image *surface, uint8_t ch, uint8_t color);
int sd_font_decode(const sd_font *font, sd_vga_image *surface, uint8_t ch, uint8_t color, int transparent);

/**
* Same as sd_font_decode, but decodes to an RGBA surface.
Expand Down
11 changes: 8 additions & 3 deletions src/formats/pcx.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#include "formats/pcx.h"
#include "formats/error.h"
#include "formats/internal/reader.h"
#include "formats/transparent.h"
#include "utils/allocator.h"
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
Expand Down Expand Up @@ -69,7 +71,7 @@ int pcx_load(pcx_file *pcx, const char *filename) {
}

int ret;
if((ret = sd_vga_image_create(&(pcx->image), 320, 200)) != SD_SUCCESS) {
if((ret = sd_vga_image_create(&(pcx->image), 320, 200, FONT_TRANSPARENT_INDEX)) != SD_SUCCESS) {
return ret;
}

Expand Down Expand Up @@ -141,19 +143,22 @@ int pcx_load_font(pcx_font *font, const char *filename) {
return SD_SUCCESS;
}

int pcx_font_decode(const pcx_font *font, sd_vga_image *o, uint8_t ch, int8_t palette_offset) {
int pcx_font_decode(const pcx_font *font, sd_vga_image *o, uint8_t ch, int8_t palette_offset, int transparent) {
if(ch >= font->glyph_count || font == NULL || o == NULL) {
return SD_INVALID_INPUT;
}

// Fonts always need to have a transparent value.
assert((transparent >= 0) && (transparent < 256));
katajakasa marked this conversation as resolved.
Show resolved Hide resolved

int k = 0;
for(int i = font->glyphs[ch].y; i < font->glyphs[ch].y + font->glyph_height; i++) {
int l = 0;
for(int j = font->glyphs[ch].x; j < font->glyphs[ch].x + font->glyphs[ch].width; j++) {
if(font->pcx.image.data[(i * 320) + j]) {
o->data[(k * font->glyphs[ch].width) + l] = palette_offset + (int)font->pcx.image.data[(i * 320) + j];
} else {
o->data[(k * font->glyphs[ch].width) + l] = 0;
o->data[(k * font->glyphs[ch].width) + l] = transparent;
}

l++;
Expand Down
2 changes: 1 addition & 1 deletion src/formats/pcx.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ typedef struct {

int pcx_load(pcx_file *pcx, const char *filename);
int pcx_load_font(pcx_font *font, const char *filename);
int pcx_font_decode(const pcx_font *font, sd_vga_image *o, uint8_t ch, int8_t palette_offset);
int pcx_font_decode(const pcx_font *font, sd_vga_image *o, uint8_t ch, int8_t palette_offset, int transparent);
void pcx_free(pcx_file *pcx);
void pcx_font_free(pcx_font *font);

Expand Down
9 changes: 7 additions & 2 deletions src/formats/sprite.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "formats/error.h"
#include "formats/palette.h"
#include "formats/sprite.h"
#include "formats/transparent.h"
#include "utils/allocator.h"

int sd_sprite_create(sd_sprite *sprite) {
Expand Down Expand Up @@ -271,6 +272,7 @@ int sd_sprite_vga_decode(sd_vga_image *dst, const sd_sprite *src) {
uint16_t c = 0;
uint16_t data = 0;
char op = 0;
int transparent = SPRITE_TRANSPARENT_INDEX;

// Make sure we aren't being fed BS
if(dst == NULL || src == NULL) {
Expand All @@ -279,9 +281,9 @@ int sd_sprite_vga_decode(sd_vga_image *dst, const sd_sprite *src) {

// If image data length is 0, then size should be 1x1
if(src->len > 0) {
sd_vga_image_create(dst, src->width, src->height);
sd_vga_image_create(dst, src->width, src->height, transparent);
} else {
sd_vga_image_create(dst, 1, 1);
sd_vga_image_create(dst, 1, 1, transparent);
}

// XXX CREDITS.BK has a bunch of 0 width sprites, for some unknown reason
Expand Down Expand Up @@ -310,6 +312,7 @@ int sd_sprite_vga_decode(sd_vga_image *dst, const sd_sprite *src) {
uint8_t b = src->data[i];
int pos = ((y * src->width) + x);
dst->data[pos] = b;
assert(b != transparent);
i++; // we read 1 byte
x++;
data--;
Expand All @@ -324,6 +327,8 @@ int sd_sprite_vga_decode(sd_vga_image *dst, const sd_sprite *src) {
}
}

dst->transparent = transparent;

// All done. dst should now contain a valid vga image.
return SD_SUCCESS;
}
Expand Down
40 changes: 40 additions & 0 deletions src/formats/transparent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*! \file
* \brief Transparent VGA pixel values
* \details Describes the transparancy index value for various engine components.
* \copyright MIT license.
* \date 2024
* \author Andrew Thompson
* \author Tuomas Virtanen
*/

#ifndef TRANSPARENT_H
#define TRANSPARENT_H

// Default's.
// Please do not use the default definitions in the code directly. Define a new value below instead.
// This way all different transparency values are stored in one place.
#define DEFAULT_TRANSPARENT_INDEX 0
#define DEFAULT_NOT_TRANSPARENT -1

// All sprites have holes, these holes need to be transparent.
#define SPRITE_TRANSPARENT_INDEX DEFAULT_TRANSPARENT_INDEX

// Backgrounds have no transparent pixels and need all pixels to be rendered.
#define BACKGROUND_TRANSPARENT_INDEX DEFAULT_NOT_TRANSPARENT

// Force an opaque menu for now.
#define MENU_TRANSPARENT_INDEX DEFAULT_NOT_TRANSPARENT

// Portraits have a transparancy index that needs to offset past other items in the global palette.
// TODO: Should really become default.
#define PORTRAIT_TRANSPARENT_INDEX 0xD0

// Fonts need a transparent index that does not conflict with the lower 8 colors on the N64 otherwise there will be a
// combinatorial explosion.
#define FONT_TRANSPARENT_INDEX DEFAULT_TRANSPARENT_INDEX
#define PCX_FONT_TRANSPARENT_INDEX DEFAULT_TRANSPARENT_INDEX

// Gauges in the player select have an opaque background and are not transparent.
#define GAUGE_TRANSPARENT_INDEX DEFAULT_NOT_TRANSPARENT

#endif
25 changes: 20 additions & 5 deletions src/formats/vga_image.c
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
#if !defined(MIN_BUILD)
#include <png.h>
#endif
nopjne marked this conversation as resolved.
Show resolved Hide resolved
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "formats/error.h"
#include "formats/transparent.h"
#include "formats/vga_image.h"
#include "utils/allocator.h"
#include "utils/png_writer.h"

int sd_vga_image_create(sd_vga_image *img, unsigned int w, unsigned int h) {
int sd_vga_image_create(sd_vga_image *img, unsigned int w, unsigned int h, int transparent) {
if(img == NULL) {
return SD_INVALID_INPUT;
}
img->w = w;
img->h = h;
img->len = w * h;
img->data = omf_calloc(1, w * h);
img->transparent = transparent;
img->data = omf_alloc_with_options(1, img->len, ALLOC_HINT_TEXTURE);
assert((img->data != NULL) || (img->len == 0));
if(img->data != NULL) {
memset(img->data, 0, img->len);
}

return SD_SUCCESS;
}

Expand All @@ -27,7 +37,8 @@ int sd_vga_image_copy(sd_vga_image *dst, const sd_vga_image *src) {
dst->w = src->w;
dst->h = src->h;
dst->len = src->len;
dst->data = omf_calloc(src->len, 1);
dst->data = omf_malloc(src->len);
dst->transparent = src->transparent;
memcpy(dst->data, src->data, src->len);
return SD_SUCCESS;
}
Expand All @@ -36,7 +47,7 @@ void sd_vga_image_free(sd_vga_image *img) {
if(img == NULL) {
return;
}
omf_free(img->data);
omf_free_with_options(img->data, ALLOC_HINT_TEXTURE);
}

int sd_vga_image_decode(sd_rgba_image *dst, const sd_vga_image *src, const vga_palette *pal) {
Expand All @@ -62,6 +73,9 @@ int sd_vga_image_decode(sd_rgba_image *dst, const sd_vga_image *src, const vga_p
}

int sd_vga_image_from_png(sd_vga_image *img, const char *filename) {
#if defined(MIN_BUILD)
return 0;
#else
png_structp png_ptr;
png_infop info_ptr;
int ret = SD_SUCCESS;
Expand Down Expand Up @@ -136,7 +150,7 @@ int sd_vga_image_from_png(sd_vga_image *img, const char *filename) {
png_read_image(png_ptr, row_pointers);

// Convert
if(sd_vga_image_create(img, w, h) != SD_SUCCESS) {
if(sd_vga_image_create(img, w, h, DEFAULT_NOT_TRANSPARENT) != SD_SUCCESS) {
ret = SD_OUT_OF_MEMORY;
goto error_3;
}
Expand All @@ -159,6 +173,7 @@ int sd_vga_image_from_png(sd_vga_image *img, const char *filename) {
fclose(handle);
error_0:
return ret;
#endif
}

int sd_vga_image_to_png(const sd_vga_image *img, const vga_palette *pal, const char *filename) {
Expand Down
3 changes: 2 additions & 1 deletion src/formats/vga_image.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ typedef struct {
unsigned int h; ///< Pixel height
unsigned int len; ///< Byte length
char *data; ///< Palette representation of image data
int transparent;
} sd_vga_image;

/*! \brief Initialize VGA image structure
Expand All @@ -41,7 +42,7 @@ typedef struct {
* \param w Image width in pixels
* \param h Image height in pixels
*/
int sd_vga_image_create(sd_vga_image *img, unsigned int w, unsigned int h);
int sd_vga_image_create(sd_vga_image *img, unsigned int w, unsigned int h, int transparent);

/*! \brief Copy VGA image structure
*
Expand Down
3 changes: 2 additions & 1 deletion src/game/gui/gauge.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "game/gui/gauge.h"
#include "formats/transparent.h"
#include "game/gui/widget.h"
#include "utils/allocator.h"
#include "utils/miscmath.h"
Expand Down Expand Up @@ -74,7 +75,7 @@ typedef struct {
} gauge;

static void surface_from_pix_img(surface *sur, const pixel_image *pix) {
surface_create_from_data(sur, pix->width, pix->height, pix->data);
surface_create_from_data(sur, pix->width, pix->height, pix->data, GAUGE_TRANSPARENT_INDEX);
}

static void gauge_render(component *c) {
Expand Down
12 changes: 5 additions & 7 deletions src/game/gui/menu_background.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "game/gui/menu_background.h"
#include "formats/transparent.h"
#include "video/image.h"

#define COLOR_MENU_LINE 252
Expand All @@ -9,8 +10,7 @@
#define COLOR_MENU_BG 0

void menu_transparent_bg_create(surface *s, int w, int h) {
surface_create(s, w, h);
surface_set_transparency(s, -1);
surface_create(s, w, h, BACKGROUND_TRANSPARENT_INDEX);
}

void menu_background_create(surface *s, int w, int h) {
Expand All @@ -24,8 +24,7 @@ void menu_background_create(surface *s, int w, int h) {
image_line(&img, 0, y, w - 1, y, COLOR_MENU_LINE);
}
image_rect(&img, 0, 0, w - 1, h - 1, COLOR_MENU_BORDER);
surface_create_from_image(s, &img);
surface_set_transparency(s, COLOR_MENU_BG);
surface_create_from_image(s, &img, MENU_TRANSPARENT_INDEX);
image_free(&img);
}

Expand All @@ -42,8 +41,7 @@ void menu_background2_create(surface *s, int w, int h) {
}
image_rect(&img, 1, 1, w - 2, h - 2, COLOR_MENU_BORDER2);
image_rect(&img, 0, 0, w - 2, h - 2, COLOR_MENU_BORDER1);
surface_create_from_image(s, &img);
surface_set_transparency(s, COLOR_MENU_BG);
surface_create_from_image(s, &img, MENU_TRANSPARENT_INDEX);
image_free(&img);
}

Expand All @@ -53,6 +51,6 @@ void menu_background_border_create(surface *s, int w, int h) {
image_create(&img, w, h);
image_clear(&img, 0);
image_rect(&img, 0, 0, w - 1, h - 1, COLOR_MENU_BORDER);
surface_create_from_image(s, &img);
surface_create_from_image(s, &img, MENU_TRANSPARENT_INDEX);
image_free(&img);
}
Loading
Loading