Merge branch with support for retina display
This commit is contained in:
commit
a72431ace7
|
@ -84,11 +84,11 @@ lite_build_package_windows () {
|
|||
rm -fr ".package-build"
|
||||
echo "created package $package_name"
|
||||
}
|
||||
|
||||
lite_build_package_macosx () {
|
||||
|
||||
lite_build_package_macos () {
|
||||
local build="$1"
|
||||
local arch="$2"
|
||||
local os="macosx"
|
||||
local os="macos"
|
||||
|
||||
local appdir=".package-build/lite-xl.app"
|
||||
local bindir="$appdir/Contents/MacOS"
|
||||
|
@ -110,10 +110,7 @@ lite_build_package_macosx () {
|
|||
mv "$package_name" ..
|
||||
popd
|
||||
rm -fr ".package-build"
|
||||
local dmg_name="lite-xl-$os-$arch.dmg"
|
||||
rm -f "$dmg_name" && hdiutil create -volname lite-xl -srcfolder lite-xl.app -ov -format UDBZ "$dmg_name"
|
||||
echo "created package $package_name"
|
||||
echo "created disk image $dmg_name"
|
||||
}
|
||||
|
||||
lite_build_package_linux () {
|
||||
|
@ -161,7 +158,7 @@ lite_build_package () {
|
|||
if [[ "$OSTYPE" == msys || "$OSTYPE" == win32 ]]; then
|
||||
lite_build_package_windows "$@"
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
lite_build_package_macosx "$@"
|
||||
lite_build_package_macos "$@"
|
||||
elif [[ "$OSTYPE" == "linux"* || "$OSTYPE" == "freebsd"* ]]; then
|
||||
lite_build_package_linux "$@"
|
||||
else
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
## Window creation for Retina displays
|
||||
|
||||
The file info.plist sets NSHighResolutionCapable to true. This is fine for High-DPI
|
||||
and retina displays.
|
||||
|
||||
The `SDL_CreateWindow` is called with the flag `SDL_WINDOW_ALLOW_HIGHDPI`.
|
||||
On Mac OS it means that, in source file `video/cocoa/SDL_cocoawindow.m`, from
|
||||
function `Cocoa_CreateWindow`, SDL calls:
|
||||
|
||||
```objc
|
||||
/* highdpi will be TRUE below */
|
||||
BOOL highdpi = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
|
||||
[contentView setWantsBestResolutionOpenGLSurface:highdpi]
|
||||
```
|
||||
|
||||
Documentation for `setWantsBestResolutionOpenGLSurface`:
|
||||
|
||||
https://developer.apple.com/documentation/appkit/nsview/1414938-wantsbestresolutionopenglsurface
|
||||
|
||||
with more details in "OpenGL Programming Guide for Mac", chapter
|
||||
"Optimizing OpenGL for High Resolution":
|
||||
|
||||
https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/EnablingOpenGLforHighResolution/EnablingOpenGLforHighResolution.html#//apple_ref/doc/uid/TP40001987-CH1001-SW4
|
||||
|
||||
Citation from the official documentation:
|
||||
|
||||
You can opt in to high resolution by calling the method
|
||||
`setWantsBestResolutionOpenGLSurface:` when you initialize the view, and
|
||||
supplying YES as an argument:
|
||||
|
||||
```objc
|
||||
[self setWantsBestResolutionOpenGLSurface:YES];
|
||||
```
|
||||
|
||||
If you don’t opt in, the system magnifies the rendered results.
|
||||
|
||||
The wantsBestResolutionOpenGLSurface property is relevant only for views to
|
||||
which an NSOpenGLContext object is bound. Its value does not affect the behavior
|
||||
of other views. For compatibility, wantsBestResolutionOpenGLSurface defaults to
|
||||
NO, providing a 1-pixel-per-point framebuffer regardless of the backing scale
|
||||
factor for the display the view occupies. Setting this property to YES for a
|
||||
given view causes AppKit to allocate a higher-resolution framebuffer when
|
||||
appropriate for the backing scale factor and target display.
|
||||
|
||||
To function correctly with wantsBestResolutionOpenGLSurface set to YES, a view
|
||||
must perform correct conversions between view units (points) and pixel units as
|
||||
needed. For example, the common practice of passing the width and height of
|
||||
[self bounds] to glViewport() will yield incorrect results at high resolution,
|
||||
because the parameters passed to the glViewport() function must be in pixels. As
|
||||
a result, you’ll get only partial instead of complete coverage of the render
|
||||
surface. Instead, use the backing store bounds:
|
||||
|
||||
```objc
|
||||
[self convertRectToBacking:[self bounds]];
|
||||
```
|
||||
|
||||
## Coordinates
|
||||
|
||||
The SDL function `SDL_GL_GetDrawableSize` will provide the size of the underlying drawable
|
||||
in pixels. From the `SDL_video.h` header.
|
||||
|
||||
```c
|
||||
/**
|
||||
* \brief Get the size of a window's underlying drawable in pixels (for use
|
||||
* with glViewport).
|
||||
*
|
||||
* \param window Window from which the drawable size should be queried
|
||||
* \param w Pointer to variable for storing the width in pixels, may be NULL
|
||||
* \param h Pointer to variable for storing the height in pixels, may be NULL
|
||||
*
|
||||
* This may differ from SDL_GetWindowSize() if we're rendering to a high-DPI
|
||||
* drawable, i.e. the window was created with SDL_WINDOW_ALLOW_HIGHDPI on a
|
||||
* platform with high-DPI support (Apple calls this "Retina"), and not disabled
|
||||
* by the SDL_HINT_VIDEO_HIGHDPI_DISABLED hint.
|
||||
*
|
||||
* \sa SDL_GetWindowSize()
|
||||
* \sa SDL_CreateWindow()
|
||||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_GL_GetDrawableSize(SDL_Window * window, int *w,
|
||||
int *h);
|
||||
```
|
||||
|
||||
In turns it calls `Cocoa_GL_GetDrawableSize` from source file
|
||||
`video/cocoa/SDL_cocoaopengl.m`. The function use the method
|
||||
`[contentView convertRectToBacking:viewport]`:
|
||||
|
||||
```objc
|
||||
if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
|
||||
/* This gives us the correct viewport for a Retina-enabled view, only
|
||||
* supported on 10.7+. */
|
||||
if ([contentView respondsToSelector:@selector(convertRectToBacking:)]) {
|
||||
viewport = [contentView convertRectToBacking:viewport];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
to give back the sizes in pixels.
|
|
@ -40,6 +40,11 @@ if host_machine.system() == 'windows'
|
|||
lite_rc += windows.compile_resources('res.rc')
|
||||
endif
|
||||
|
||||
# On macos we need to use the SDL renderer to support retina displays
|
||||
if get_option('renderer') or host_machine.system() == 'darwin'
|
||||
lite_cargs += '-DLITE_USE_SDL_RENDERER'
|
||||
endif
|
||||
|
||||
subdir('lib/font_renderer')
|
||||
subdir('src')
|
||||
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
option('portable', type : 'boolean', value : false, description: 'Portable install')
|
||||
option('renderer', type : 'boolean', value : false, description: 'Use SDL renderer')
|
||||
|
||||
|
|
|
@ -72,9 +72,9 @@ static int f_draw_rect(lua_State *L) {
|
|||
}
|
||||
|
||||
static int draw_text_subpixel_impl(lua_State *L, bool draw_subpixel) {
|
||||
RenFont **font = luaL_checkudata(L, 1, API_TYPE_FONT);
|
||||
FontDesc *font_desc = luaL_checkudata(L, 1, API_TYPE_FONT);
|
||||
const char *text = luaL_checkstring(L, 2);
|
||||
/* The coordinate below will be in subpixels iff draw_subpixel is true.
|
||||
/* The coordinate below will be in subpixel iff draw_subpixel is true.
|
||||
Otherwise it will be in pixels. */
|
||||
int x_subpixel = luaL_checknumber(L, 3);
|
||||
int y = luaL_checknumber(L, 4);
|
||||
|
@ -90,7 +90,7 @@ static int draw_text_subpixel_impl(lua_State *L, bool draw_subpixel) {
|
|||
replace_color = (RenColor) {0};
|
||||
}
|
||||
|
||||
x_subpixel = rencache_draw_text(*font, text, x_subpixel, y, color, draw_subpixel, rep_table, replace_color);
|
||||
x_subpixel = rencache_draw_text(font_desc, text, x_subpixel, y, color, draw_subpixel, rep_table, replace_color);
|
||||
lua_pushnumber(L, x_subpixel);
|
||||
return 1;
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ static const luaL_Reg lib[] = {
|
|||
{ "draw_rect", f_draw_rect },
|
||||
{ "draw_text", f_draw_text },
|
||||
{ "draw_text_subpixel", f_draw_text_subpixel },
|
||||
{ NULL, NULL }
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#include "api.h"
|
||||
#include "fontdesc.h"
|
||||
#include "renderer.h"
|
||||
#include "rencache.h"
|
||||
|
||||
|
||||
static int f_load(lua_State *L) {
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
float size = luaL_checknumber(L, 2);
|
||||
|
@ -40,57 +40,63 @@ static int f_load(lua_State *L) {
|
|||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
RenFont **self = lua_newuserdata(L, sizeof(*self));
|
||||
|
||||
if (ren_verify_font(filename)) {
|
||||
luaL_error(L, "failed to load font");
|
||||
}
|
||||
|
||||
FontDesc *font_desc = lua_newuserdata(L, font_desc_alloc_size(filename));
|
||||
font_desc_init(font_desc, filename, size, font_options);
|
||||
luaL_setmetatable(L, API_TYPE_FONT);
|
||||
*self = ren_load_font(filename, size, font_options);
|
||||
if (!*self) { luaL_error(L, "failed to load font"); }
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int f_set_tab_size(lua_State *L) {
|
||||
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
|
||||
FontDesc *self = luaL_checkudata(L, 1, API_TYPE_FONT);
|
||||
int n = luaL_checknumber(L, 2);
|
||||
ren_set_font_tab_size(*self, n);
|
||||
font_desc_set_tab_size(self, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int f_gc(lua_State *L) {
|
||||
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
|
||||
if (*self) { rencache_free_font(*self); }
|
||||
FontDesc *self = luaL_checkudata(L, 1, API_TYPE_FONT);
|
||||
rencache_free_font(self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int f_get_width(lua_State *L) {
|
||||
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
|
||||
FontDesc *self = luaL_checkudata(L, 1, API_TYPE_FONT);
|
||||
const char *text = luaL_checkstring(L, 2);
|
||||
int subpixel_scale;
|
||||
int w = ren_get_font_width(*self, text, &subpixel_scale);
|
||||
lua_pushnumber(L, ren_font_subpixel_round(w, subpixel_scale, 0));
|
||||
/* By calling ren_get_font_width with NULL as third arguments
|
||||
we will obtain the width in points. */
|
||||
int w = ren_get_font_width(self, text, NULL);
|
||||
lua_pushnumber(L, w);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int f_subpixel_scale(lua_State *L) {
|
||||
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
|
||||
lua_pushnumber(L, ren_get_font_subpixel_scale(*self));
|
||||
FontDesc *self = luaL_checkudata(L, 1, API_TYPE_FONT);
|
||||
lua_pushnumber(L, ren_get_font_subpixel_scale(self));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int f_get_width_subpixel(lua_State *L) {
|
||||
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
|
||||
FontDesc *self = luaL_checkudata(L, 1, API_TYPE_FONT);
|
||||
const char *text = luaL_checkstring(L, 2);
|
||||
lua_pushnumber(L, ren_get_font_width(*self, text, NULL));
|
||||
int subpixel_scale;
|
||||
/* We need to pass a non-null subpixel_scale pointer to force
|
||||
subpixel width calculation. */
|
||||
lua_pushnumber(L, ren_get_font_width(self, text, &subpixel_scale));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int f_get_height(lua_State *L) {
|
||||
RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT);
|
||||
lua_pushnumber(L, ren_get_font_height(*self) );
|
||||
FontDesc *self = luaL_checkudata(L, 1, API_TYPE_FONT);
|
||||
lua_pushnumber(L, ren_get_font_height(self) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,9 @@ top:
|
|||
|
||||
case SDL_WINDOWEVENT:
|
||||
if (e.window.event == SDL_WINDOWEVENT_RESIZED) {
|
||||
ren_resize_window();
|
||||
lua_pushstring(L, "resized");
|
||||
/* The size below will be in points. */
|
||||
lua_pushnumber(L, e.window.data1);
|
||||
lua_pushnumber(L, e.window.data2);
|
||||
return 3;
|
||||
|
@ -316,6 +318,7 @@ static int f_set_window_size(lua_State *L) {
|
|||
double y = luaL_checknumber(L, 4);
|
||||
SDL_SetWindowSize(window, w, h);
|
||||
SDL_SetWindowPosition(window, x, y);
|
||||
ren_resize_window();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "fontdesc.h"
|
||||
#include "renderer.h"
|
||||
|
||||
|
||||
int font_desc_alloc_size(const char *filename) {
|
||||
return offsetof(FontDesc, filename) + strlen(filename) + 1;
|
||||
}
|
||||
|
||||
void font_desc_init(FontDesc *font_desc, const char *filename, float size, unsigned int font_options) {
|
||||
memcpy(font_desc->filename, filename, strlen(filename) + 1);
|
||||
font_desc->size = size;
|
||||
font_desc->options = font_options;
|
||||
font_desc->tab_size = 4;
|
||||
font_desc->cache_length = 0;
|
||||
font_desc->cache_last_index = 0; /* Normally no need to initialize. */
|
||||
}
|
||||
|
||||
void font_desc_free(FontDesc *font_desc) {
|
||||
for (int i = 0; i < font_desc->cache_length; i++) {
|
||||
ren_free_font(font_desc->cache[i].font);
|
||||
}
|
||||
font_desc->cache_length = 0;
|
||||
}
|
||||
|
||||
void font_desc_set_tab_size(FontDesc *font_desc, int tab_size) {
|
||||
font_desc->tab_size = tab_size;
|
||||
for (int i = 0; i < font_desc->cache_length; i++) {
|
||||
ren_set_font_tab_size(font_desc->cache[i].font, tab_size);
|
||||
}
|
||||
}
|
||||
|
||||
int font_desc_get_tab_size(FontDesc *font_desc) {
|
||||
return font_desc->tab_size;
|
||||
}
|
||||
|
||||
static void load_scaled_font(FontDesc *font_desc, int index, int scale) {
|
||||
RenFont *font = ren_load_font(font_desc->filename, scale * font_desc->size, font_desc->options);
|
||||
if (!font) {
|
||||
/* The font was able to load when initially loaded using renderer.load.font.
|
||||
If now is no longer available we just abort the application. */
|
||||
fprintf(stderr, "Fatal error: unable to load font %s. Application will abort.\n",
|
||||
font_desc->filename);
|
||||
exit(1);
|
||||
}
|
||||
font_desc->cache[index].font = font;
|
||||
font_desc->cache[index].scale = scale;
|
||||
}
|
||||
|
||||
RenFont *font_desc_get_font_at_scale(FontDesc *font_desc, int scale) {
|
||||
int index = -1;
|
||||
for (int i = 0; i < font_desc->cache_length; i++) {
|
||||
if (font_desc->cache[i].scale == scale) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index < 0) {
|
||||
index = font_desc->cache_length;
|
||||
if (index < FONT_CACHE_ARRAY_MAX) {
|
||||
load_scaled_font(font_desc, index, scale);
|
||||
font_desc->cache_length = index + 1;
|
||||
} else {
|
||||
// FIXME: should not print into the stderr or stdout.
|
||||
fprintf(stderr, "Warning: max array of font scale reached.\n");
|
||||
index = (font_desc->cache_last_index == 0 ? 1 : 0);
|
||||
ren_free_font(font_desc->cache[index].font);
|
||||
load_scaled_font(font_desc, index, scale);
|
||||
}
|
||||
}
|
||||
font_desc->cache_last_index = index;
|
||||
return font_desc->cache[index].font;
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef FONT_DESC_H
|
||||
#define FONT_DESC_H
|
||||
|
||||
typedef struct RenFont RenFont;
|
||||
|
||||
struct FontInstance {
|
||||
RenFont *font;
|
||||
short int scale;
|
||||
};
|
||||
typedef struct FontInstance FontInstance;
|
||||
|
||||
#define FONT_CACHE_ARRAY_MAX 2
|
||||
|
||||
struct FontDesc {
|
||||
float size;
|
||||
unsigned int options;
|
||||
short int tab_size;
|
||||
FontInstance cache[FONT_CACHE_ARRAY_MAX];
|
||||
short int cache_length;
|
||||
short int cache_last_index; /* More recently used instance. */
|
||||
char filename[0];
|
||||
};
|
||||
typedef struct FontDesc FontDesc;
|
||||
|
||||
void font_desc_init(FontDesc *font_desc, const char *filename, float size, unsigned int font_options);
|
||||
int font_desc_alloc_size(const char *filename);
|
||||
int font_desc_get_tab_size(FontDesc *font_desc);
|
||||
void font_desc_set_tab_size(FontDesc *font_desc, int tab_size);
|
||||
void font_desc_free(FontDesc *font_desc);
|
||||
RenFont *font_desc_get_font_at_scale(FontDesc *font_desc, int scale);
|
||||
|
||||
#endif
|
||||
|
|
@ -200,7 +200,7 @@ init_lua:
|
|||
}
|
||||
|
||||
lua_close(L);
|
||||
SDL_DestroyWindow(window);
|
||||
ren_free_window_resources();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ lite_sources = [
|
|||
'api/renderer_font.c',
|
||||
'api/system.c',
|
||||
'renderer.c',
|
||||
'renwindow.c',
|
||||
'fontdesc.c',
|
||||
'rencache.c',
|
||||
'main.c',
|
||||
]
|
||||
|
|
|
@ -24,7 +24,7 @@ typedef struct {
|
|||
int32_t size;
|
||||
RenRect rect;
|
||||
RenColor color;
|
||||
RenFont *font;
|
||||
FontDesc *font_desc;
|
||||
CPReplaceTable *replacements;
|
||||
RenColor replace_color;
|
||||
char text[0];
|
||||
|
@ -115,9 +115,9 @@ void rencache_show_debug(bool enable) {
|
|||
}
|
||||
|
||||
|
||||
void rencache_free_font(RenFont *font) {
|
||||
void rencache_free_font(FontDesc *font_desc) {
|
||||
Command *cmd = push_command(FREE_FONT, COMMAND_BARE_SIZE);
|
||||
if (cmd) { cmd->font = font; }
|
||||
if (cmd) { cmd->font_desc = font_desc; }
|
||||
}
|
||||
|
||||
|
||||
|
@ -136,17 +136,17 @@ void rencache_draw_rect(RenRect rect, RenColor color) {
|
|||
}
|
||||
}
|
||||
|
||||
int rencache_draw_text(RenFont *font,
|
||||
int rencache_draw_text(FontDesc *font_desc,
|
||||
const char *text, int x, int y, RenColor color, bool draw_subpixel,
|
||||
CPReplaceTable *replacements, RenColor replace_color)
|
||||
{
|
||||
int subpixel_scale;
|
||||
int w_subpixel = ren_get_font_width(font, text, &subpixel_scale);
|
||||
int w_subpixel = ren_get_font_width(font_desc, text, &subpixel_scale);
|
||||
RenRect rect;
|
||||
rect.x = (draw_subpixel ? ren_font_subpixel_round(x, subpixel_scale, -1) : x);
|
||||
rect.y = y;
|
||||
rect.width = ren_font_subpixel_round(w_subpixel, subpixel_scale, 0);
|
||||
rect.height = ren_get_font_height(font);
|
||||
rect.height = ren_get_font_height(font_desc);
|
||||
|
||||
if (rects_overlap(screen_rect, rect)) {
|
||||
int sz = strlen(text) + 1;
|
||||
|
@ -154,11 +154,11 @@ int rencache_draw_text(RenFont *font,
|
|||
if (cmd) {
|
||||
memcpy(cmd->text, text, sz);
|
||||
cmd->color = color;
|
||||
cmd->font = font;
|
||||
cmd->font_desc = font_desc;
|
||||
cmd->rect = rect;
|
||||
cmd->subpixel_scale = (draw_subpixel ? subpixel_scale : 1);
|
||||
cmd->x_subpixel_offset = x - subpixel_scale * rect.x;
|
||||
cmd->tab_size = ren_get_font_tab_size(font);
|
||||
cmd->tab_size = font_desc_get_tab_size(font_desc);
|
||||
cmd->replacements = replacements;
|
||||
cmd->replace_color = replace_color;
|
||||
}
|
||||
|
@ -272,13 +272,13 @@ void rencache_end_frame(void) {
|
|||
ren_draw_rect(cmd->rect, cmd->color);
|
||||
break;
|
||||
case DRAW_TEXT:
|
||||
ren_set_font_tab_size(cmd->font, cmd->tab_size);
|
||||
ren_draw_text(cmd->font, cmd->text, cmd->rect.x, cmd->rect.y, cmd->color,
|
||||
font_desc_set_tab_size(cmd->font_desc, cmd->tab_size);
|
||||
ren_draw_text(cmd->font_desc, cmd->text, cmd->rect.x, cmd->rect.y, cmd->color,
|
||||
cmd->replacements, cmd->replace_color);
|
||||
break;
|
||||
case DRAW_TEXT_SUBPIXEL:
|
||||
ren_set_font_tab_size(cmd->font, cmd->tab_size);
|
||||
ren_draw_text_subpixel(cmd->font, cmd->text,
|
||||
font_desc_set_tab_size(cmd->font_desc, cmd->tab_size);
|
||||
ren_draw_text_subpixel(cmd->font_desc, cmd->text,
|
||||
cmd->subpixel_scale * cmd->rect.x + cmd->x_subpixel_offset, cmd->rect.y, cmd->color,
|
||||
cmd->replacements, cmd->replace_color);
|
||||
break;
|
||||
|
@ -301,7 +301,7 @@ void rencache_end_frame(void) {
|
|||
cmd = NULL;
|
||||
while (next_command(&cmd)) {
|
||||
if (cmd->type == FREE_FONT) {
|
||||
ren_free_font(cmd->font);
|
||||
font_desc_free(cmd->font_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,11 @@
|
|||
#include "renderer.h"
|
||||
|
||||
void rencache_show_debug(bool enable);
|
||||
void rencache_free_font(RenFont *font);
|
||||
void rencache_free_font(FontDesc *font_desc);
|
||||
void rencache_set_clip_rect(RenRect rect);
|
||||
void rencache_draw_rect(RenRect rect, RenColor color);
|
||||
int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor color, bool draw_subpixel, CPReplaceTable *replacements, RenColor replace_color);
|
||||
int rencache_draw_text(FontDesc *font_desc, const char *text, int x, int y, RenColor color,
|
||||
bool draw_subpixel, CPReplaceTable *replacements, RenColor replace_color);
|
||||
void rencache_invalidate(void);
|
||||
void rencache_begin_frame(void);
|
||||
void rencache_end_frame(void);
|
||||
|
|
171
src/renderer.c
171
src/renderer.c
|
@ -2,8 +2,9 @@
|
|||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include "renderer.h"
|
||||
#include "font_renderer.h"
|
||||
#include "renderer.h"
|
||||
#include "renwindow.h"
|
||||
|
||||
#define MAX_GLYPHSET 256
|
||||
#define REPLACEMENT_CHUNK_SIZE 8
|
||||
|
@ -31,9 +32,7 @@ struct RenFont {
|
|||
FR_Renderer *renderer;
|
||||
};
|
||||
|
||||
|
||||
static SDL_Window *window;
|
||||
static FR_Clip_Area clip;
|
||||
static RenWindow window_renderer = {0};
|
||||
|
||||
static void* check_alloc(void *ptr) {
|
||||
if (!ptr) {
|
||||
|
@ -91,37 +90,44 @@ void ren_cp_replace_add(CPReplaceTable *rep_table, const char *src, const char *
|
|||
rep_table->size = table_size + 1;
|
||||
}
|
||||
|
||||
void ren_free_window_resources() {
|
||||
renwin_free(&window_renderer);
|
||||
}
|
||||
|
||||
void ren_init(SDL_Window *win) {
|
||||
assert(win);
|
||||
window = win;
|
||||
SDL_Surface *surf = SDL_GetWindowSurface(window);
|
||||
ren_set_clip_rect( (RenRect) { 0, 0, surf->w, surf->h } );
|
||||
window_renderer.window = win;
|
||||
renwin_init_surface(&window_renderer);
|
||||
renwin_clip_to_surface(&window_renderer);
|
||||
}
|
||||
|
||||
|
||||
void ren_resize_window() {
|
||||
renwin_resize_surface(&window_renderer);
|
||||
}
|
||||
|
||||
|
||||
void ren_update_rects(RenRect *rects, int count) {
|
||||
SDL_UpdateWindowSurfaceRects(window, (SDL_Rect*) rects, count);
|
||||
static bool initial_frame = true;
|
||||
if (initial_frame) {
|
||||
SDL_ShowWindow(window);
|
||||
renwin_show_window(&window_renderer);
|
||||
initial_frame = false;
|
||||
}
|
||||
renwin_update_rects(&window_renderer, rects, count);
|
||||
}
|
||||
|
||||
|
||||
void ren_set_clip_rect(RenRect rect) {
|
||||
clip.left = rect.x;
|
||||
clip.top = rect.y;
|
||||
clip.right = rect.x + rect.width;
|
||||
clip.bottom = rect.y + rect.height;
|
||||
renwin_set_clip_rect(&window_renderer, rect);
|
||||
}
|
||||
|
||||
|
||||
void ren_get_size(int *x, int *y) {
|
||||
SDL_Surface *surf = SDL_GetWindowSurface(window);
|
||||
*x = surf->w;
|
||||
*y = surf->h;
|
||||
RenWindow *ren = &window_renderer;
|
||||
const int scale = renwin_surface_scale(ren);
|
||||
SDL_Surface *surface = renwin_get_surface(ren);
|
||||
*x = surface->w / scale;
|
||||
*y = surface->h / scale;
|
||||
}
|
||||
|
||||
|
||||
|
@ -158,6 +164,17 @@ static GlyphSet* get_glyphset(RenFont *font, int codepoint) {
|
|||
}
|
||||
|
||||
|
||||
int ren_verify_font(const char *filename) {
|
||||
RenFont font[1];
|
||||
font->renderer = FR_Renderer_New(0);
|
||||
if (FR_Load_Font(font->renderer, filename)) {
|
||||
return 1;
|
||||
}
|
||||
FR_Renderer_Free(font->renderer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
RenFont* ren_load_font(const char *filename, float size, unsigned int renderer_flags) {
|
||||
RenFont *font = NULL;
|
||||
|
||||
|
@ -218,25 +235,34 @@ int ren_get_font_tab_size(RenFont *font) {
|
|||
}
|
||||
|
||||
|
||||
int ren_get_font_width(RenFont *font, const char *text, int *subpixel_scale) {
|
||||
/* Important: if subpixel_scale is NULL we will return width in points. Otherwise we will
|
||||
return width in subpixels. */
|
||||
int ren_get_font_width(FontDesc *font_desc, const char *text, int *subpixel_scale) {
|
||||
int x = 0;
|
||||
const char *p = text;
|
||||
unsigned codepoint;
|
||||
const int surface_scale = renwin_surface_scale(&window_renderer);
|
||||
RenFont *font = font_desc_get_font_at_scale(font_desc, surface_scale);
|
||||
while (*p) {
|
||||
p = utf8_to_codepoint(p, &codepoint);
|
||||
GlyphSet *set = get_glyphset(font, codepoint);
|
||||
FR_Bitmap_Glyph_Metrics *g = &set->glyphs[codepoint & 0xff];
|
||||
x += g->xadvance;
|
||||
}
|
||||
/* At this point here x is in subpixel units */
|
||||
const int x_scale_to_points = FR_Subpixel_Scale(font->renderer) * surface_scale;
|
||||
if (subpixel_scale) {
|
||||
*subpixel_scale = FR_Subpixel_Scale(font->renderer);
|
||||
*subpixel_scale = x_scale_to_points;
|
||||
return x;
|
||||
}
|
||||
return x;
|
||||
return (x + x_scale_to_points / 2) / x_scale_to_points;
|
||||
}
|
||||
|
||||
|
||||
int ren_get_font_height(RenFont *font) {
|
||||
return font->height;
|
||||
int ren_get_font_height(FontDesc *font_desc) {
|
||||
const int surface_scale = renwin_surface_scale(&window_renderer);
|
||||
RenFont *font = font_desc_get_font_at_scale(font_desc, surface_scale);
|
||||
return (font->height + surface_scale / 2) / surface_scale;
|
||||
}
|
||||
|
||||
|
||||
|
@ -249,16 +275,6 @@ static inline RenColor blend_pixel(RenColor dst, RenColor src) {
|
|||
}
|
||||
|
||||
|
||||
static inline RenColor blend_pixel2(RenColor dst, RenColor src, RenColor color) {
|
||||
src.a = (src.a * color.a) >> 8;
|
||||
int ia = 0xff - src.a;
|
||||
dst.r = ((src.r * color.r * src.a) >> 16) + ((dst.r * ia) >> 8);
|
||||
dst.g = ((src.g * color.g * src.a) >> 16) + ((dst.g * ia) >> 8);
|
||||
dst.b = ((src.b * color.b * src.a) >> 16) + ((dst.b * ia) >> 8);
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
#define rect_draw_loop(expr) \
|
||||
for (int j = y1; j < y2; j++) { \
|
||||
for (int i = x1; i < x2; i++) { \
|
||||
|
@ -271,17 +287,26 @@ static inline RenColor blend_pixel2(RenColor dst, RenColor src, RenColor color)
|
|||
void ren_draw_rect(RenRect rect, RenColor color) {
|
||||
if (color.a == 0) { return; }
|
||||
|
||||
int x1 = rect.x < clip.left ? clip.left : rect.x;
|
||||
int y1 = rect.y < clip.top ? clip.top : rect.y;
|
||||
const int surface_scale = renwin_surface_scale(&window_renderer);
|
||||
|
||||
/* transforms coordinates in pixels. */
|
||||
rect.x *= surface_scale;
|
||||
rect.y *= surface_scale;
|
||||
rect.width *= surface_scale;
|
||||
rect.height *= surface_scale;
|
||||
|
||||
const RenRect clip = window_renderer.clip;
|
||||
int x1 = rect.x < clip.x ? clip.x : rect.x;
|
||||
int y1 = rect.y < clip.y ? clip.y : rect.y;
|
||||
int x2 = rect.x + rect.width;
|
||||
int y2 = rect.y + rect.height;
|
||||
x2 = x2 > clip.right ? clip.right : x2;
|
||||
y2 = y2 > clip.bottom ? clip.bottom : y2;
|
||||
x2 = x2 > clip.x + clip.width ? clip.x + clip.width : x2;
|
||||
y2 = y2 > clip.y + clip.height ? clip.y + clip.height : y2;
|
||||
|
||||
SDL_Surface *surf = SDL_GetWindowSurface(window);
|
||||
RenColor *d = (RenColor*) surf->pixels;
|
||||
d += x1 + y1 * surf->w;
|
||||
int dr = surf->w - (x2 - x1);
|
||||
SDL_Surface *surface = renwin_get_surface(&window_renderer);
|
||||
RenColor *d = (RenColor*) surface->pixels;
|
||||
d += x1 + y1 * surface->w;
|
||||
int dr = surface->w - (x2 - x1);
|
||||
|
||||
if (color.a == 0xff) {
|
||||
rect_draw_loop(color);
|
||||
|
@ -290,38 +315,6 @@ void ren_draw_rect(RenRect rect, RenColor color) {
|
|||
}
|
||||
}
|
||||
|
||||
void ren_draw_image(RenImage *image, RenRect *sub, int x, int y, RenColor color) {
|
||||
if (color.a == 0) { return; }
|
||||
|
||||
int n;
|
||||
if ((n = clip.left - x) > 0) { sub->width -= n; sub->x += n; x += n; }
|
||||
if ((n = clip.top - y) > 0) { sub->height -= n; sub->y += n; x += n; }
|
||||
if ((n = x + sub->width - clip.right ) > 0) { sub->width -= n; }
|
||||
if ((n = y + sub->height - clip.bottom) > 0) { sub->height -= n; }
|
||||
|
||||
if (sub->width <= 0 || sub->height <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* draw */
|
||||
SDL_Surface *surf = SDL_GetWindowSurface(window);
|
||||
RenColor *s = image->pixels;
|
||||
RenColor *d = (RenColor*) surf->pixels;
|
||||
s += sub->x + sub->y * image->width;
|
||||
d += x + y * surf->w;
|
||||
int sr = image->width - sub->width;
|
||||
int dr = surf->w - sub->width;
|
||||
|
||||
for (int j = 0; j < sub->height; j++) {
|
||||
for (int i = 0; i < sub->width; i++) {
|
||||
*d = blend_pixel2(*d, *s, color);
|
||||
d++;
|
||||
s++;
|
||||
}
|
||||
d += dr;
|
||||
s += sr;
|
||||
}
|
||||
}
|
||||
|
||||
static int codepoint_replace(CPReplaceTable *rep_table, unsigned *codepoint) {
|
||||
for (int i = 0; i < rep_table->size; i++) {
|
||||
|
@ -335,12 +328,18 @@ static int codepoint_replace(CPReplaceTable *rep_table, unsigned *codepoint) {
|
|||
}
|
||||
|
||||
|
||||
void ren_draw_text_subpixel(RenFont *font, const char *text, int x_subpixel, int y, RenColor color,
|
||||
static FR_Clip_Area clip_area_from_rect(const RenRect r) {
|
||||
return (FR_Clip_Area) {r.x, r.y, r.x + r.width, r.y + r.height};
|
||||
}
|
||||
|
||||
|
||||
static void draw_text_impl(RenFont *font, const char *text, int x_subpixel, int y_pixel, RenColor color,
|
||||
CPReplaceTable *replacements, RenColor replace_color)
|
||||
{
|
||||
SDL_Surface *surf = renwin_get_surface(&window_renderer);
|
||||
FR_Clip_Area clip = clip_area_from_rect(window_renderer.clip);
|
||||
const char *p = text;
|
||||
unsigned codepoint;
|
||||
SDL_Surface *surf = SDL_GetWindowSurface(window);
|
||||
const FR_Color color_fr = { .r = color.r, .g = color.g, .b = color.b };
|
||||
while (*p) {
|
||||
FR_Color color_rep;
|
||||
|
@ -358,17 +357,28 @@ void ren_draw_text_subpixel(RenFont *font, const char *text, int x_subpixel, int
|
|||
}
|
||||
if (color.a != 0) {
|
||||
FR_Blend_Glyph(font->renderer, &clip,
|
||||
x_subpixel, y, (uint8_t *) surf->pixels, surf->w, set->image, g, color_rep);
|
||||
x_subpixel, y_pixel, (uint8_t *) surf->pixels, surf->w, set->image, g, color_rep);
|
||||
}
|
||||
x_subpixel += xadvance_original_cp;
|
||||
}
|
||||
}
|
||||
|
||||
void ren_draw_text(RenFont *font, const char *text, int x, int y, RenColor color,
|
||||
|
||||
void ren_draw_text_subpixel(FontDesc *font_desc, const char *text, int x_subpixel, int y, RenColor color,
|
||||
CPReplaceTable *replacements, RenColor replace_color)
|
||||
{
|
||||
const int subpixel_scale = FR_Subpixel_Scale(font->renderer);
|
||||
ren_draw_text_subpixel(font, text, subpixel_scale * x, y, color, replacements, replace_color);
|
||||
const int surface_scale = renwin_surface_scale(&window_renderer);
|
||||
RenFont *font = font_desc_get_font_at_scale(font_desc, surface_scale);
|
||||
draw_text_impl(font, text, x_subpixel, surface_scale * y, color, replacements, replace_color);
|
||||
}
|
||||
|
||||
void ren_draw_text(FontDesc *font_desc, const char *text, int x, int y, RenColor color,
|
||||
CPReplaceTable *replacements, RenColor replace_color)
|
||||
{
|
||||
const int surface_scale = renwin_surface_scale(&window_renderer);
|
||||
RenFont *font = font_desc_get_font_at_scale(font_desc, surface_scale);
|
||||
const int subpixel_scale = surface_scale * FR_Subpixel_Scale(font->renderer);
|
||||
draw_text_impl(font, text, subpixel_scale * x, surface_scale * y, color, replacements, replace_color);
|
||||
}
|
||||
|
||||
// Could be declared as static inline
|
||||
|
@ -385,7 +395,8 @@ int ren_font_subpixel_round(int width, int subpixel_scale, int orientation) {
|
|||
}
|
||||
|
||||
|
||||
int ren_get_font_subpixel_scale(RenFont *font) {
|
||||
return FR_Subpixel_Scale(font->renderer);
|
||||
int ren_get_font_subpixel_scale(FontDesc *font_desc) {
|
||||
const int surface_scale = renwin_surface_scale(&window_renderer);
|
||||
RenFont *font = font_desc_get_font_at_scale(font_desc, surface_scale);
|
||||
return FR_Subpixel_Scale(font->renderer) * surface_scale;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
#include <SDL.h>
|
||||
#include <stdint.h>
|
||||
#include "fontdesc.h"
|
||||
|
||||
typedef struct RenImage RenImage;
|
||||
typedef struct RenFont RenFont;
|
||||
|
||||
enum {
|
||||
RenFontAntialiasingMask = 1,
|
||||
|
@ -36,26 +36,29 @@ typedef struct CPReplaceTable CPReplaceTable;
|
|||
|
||||
|
||||
void ren_init(SDL_Window *win);
|
||||
void ren_resize_window();
|
||||
void ren_update_rects(RenRect *rects, int count);
|
||||
void ren_set_clip_rect(RenRect rect);
|
||||
void ren_get_size(int *x, int *y);
|
||||
void ren_get_size(int *x, int *y); /* Reports the size in points. */
|
||||
void ren_free_window_resources();
|
||||
|
||||
RenImage* ren_new_image(int width, int height);
|
||||
void ren_free_image(RenImage *image);
|
||||
|
||||
RenFont* ren_load_font(const char *filename, float size, unsigned int renderer_flags);
|
||||
int ren_verify_font(const char *filename);
|
||||
void ren_free_font(RenFont *font);
|
||||
void ren_set_font_tab_size(RenFont *font, int n);
|
||||
int ren_get_font_tab_size(RenFont *font);
|
||||
int ren_get_font_width(RenFont *font, const char *text, int *subpixel_scale);
|
||||
int ren_get_font_height(RenFont *font);
|
||||
int ren_get_font_subpixel_scale(RenFont *font);
|
||||
|
||||
int ren_get_font_width(FontDesc *font_desc, const char *text, int *subpixel_scale);
|
||||
int ren_get_font_height(FontDesc *font_desc);
|
||||
int ren_get_font_subpixel_scale(FontDesc *font_desc);
|
||||
int ren_font_subpixel_round(int width, int subpixel_scale, int orientation);
|
||||
|
||||
void ren_draw_rect(RenRect rect, RenColor color);
|
||||
void ren_draw_image(RenImage *image, RenRect *sub, int x, int y, RenColor color);
|
||||
void ren_draw_text(RenFont *font, const char *text, int x, int y, RenColor color, CPReplaceTable *replacements, RenColor replace_color);
|
||||
void ren_draw_text_subpixel(RenFont *font, const char *text, int x_subpixel, int y, RenColor color, CPReplaceTable *replacements, RenColor replace_color);
|
||||
void ren_draw_text(FontDesc *font_desc, const char *text, int x, int y, RenColor color, CPReplaceTable *replacements, RenColor replace_color);
|
||||
void ren_draw_text_subpixel(FontDesc *font_desc, const char *text, int x_subpixel, int y, RenColor color, CPReplaceTable *replacements, RenColor replace_color);
|
||||
|
||||
void ren_cp_replace_init(CPReplaceTable *rep_table);
|
||||
void ren_cp_replace_free(CPReplaceTable *rep_table);
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
#include <assert.h>
|
||||
#include "renwindow.h"
|
||||
|
||||
#ifdef LITE_USE_SDL_RENDERER
|
||||
static int query_surface_scale(RenWindow *ren) {
|
||||
int w_pixels, h_pixels;
|
||||
int w_points, h_points;
|
||||
SDL_GL_GetDrawableSize(ren->window, &w_pixels, &h_pixels);
|
||||
SDL_GetWindowSize(ren->window, &w_points, &h_points);
|
||||
/* We consider that the ratio pixel/point will always be an integer and
|
||||
it is the same along the x and the y axis. */
|
||||
assert(w_pixels % w_points == 0 && h_pixels % h_points == 0 && w_pixels / w_points == h_pixels / h_points);
|
||||
return w_pixels / w_points;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void renwin_init_surface(RenWindow *ren) {
|
||||
#ifdef LITE_USE_SDL_RENDERER
|
||||
if (ren->surface) {
|
||||
SDL_FreeSurface(ren->surface);
|
||||
}
|
||||
int w, h;
|
||||
SDL_GL_GetDrawableSize(ren->window, &w, &h);
|
||||
ren->surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_BGRA32);
|
||||
ren->surface_scale = query_surface_scale(ren);
|
||||
#endif
|
||||
}
|
||||
|
||||
int renwin_surface_scale(RenWindow *ren) {
|
||||
#ifdef LITE_USE_SDL_RENDERER
|
||||
return ren->surface_scale;
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static RenRect scaled_rect(const RenRect rect, const int scale) {
|
||||
return (RenRect) {rect.x * scale, rect.y * scale, rect.width * scale, rect.height * scale};
|
||||
}
|
||||
|
||||
|
||||
void renwin_clip_to_surface(RenWindow *ren) {
|
||||
SDL_Surface *surface = renwin_get_surface(ren);
|
||||
ren->clip = (RenRect) {0, 0, surface->w, surface->h};
|
||||
}
|
||||
|
||||
|
||||
void renwin_set_clip_rect(RenWindow *ren, RenRect rect) {
|
||||
ren->clip = scaled_rect(rect, renwin_surface_scale(ren));
|
||||
}
|
||||
|
||||
|
||||
SDL_Surface *renwin_get_surface(RenWindow *ren) {
|
||||
#ifdef LITE_USE_SDL_RENDERER
|
||||
return ren->surface;
|
||||
#else
|
||||
return SDL_GetWindowSurface(ren->window);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef LITE_USE_SDL_RENDERER
|
||||
static void setup_renderer(RenWindow *ren, int w, int h) {
|
||||
/* Note that w and h here should always be in pixels and obtained from
|
||||
a call to SDL_GL_GetDrawableSize(). */
|
||||
if (ren->renderer) {
|
||||
SDL_DestroyRenderer(ren->renderer);
|
||||
SDL_DestroyTexture(ren->texture);
|
||||
}
|
||||
ren->renderer = SDL_CreateRenderer(ren->window, -1, 0);
|
||||
ren->texture = SDL_CreateTexture(ren->renderer, SDL_PIXELFORMAT_BGRA32, SDL_TEXTUREACCESS_STREAMING, w, h);
|
||||
ren->surface_scale = query_surface_scale(ren);
|
||||
}
|
||||
#endif
|
||||
|
||||
void renwin_resize_surface(RenWindow *ren) {
|
||||
#ifdef LITE_USE_SDL_RENDERER
|
||||
int new_w, new_h;
|
||||
SDL_GL_GetDrawableSize(ren->window, &new_w, &new_h);
|
||||
/* Note that (w, h) may differ from (new_w, new_h) on retina displays. */
|
||||
if (new_w != ren->surface->w || new_h != ren->surface->h) {
|
||||
renwin_init_surface(ren);
|
||||
renwin_clip_to_surface(ren);
|
||||
setup_renderer(ren, new_w, new_h);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void renwin_show_window(RenWindow *ren) {
|
||||
SDL_ShowWindow(ren->window);
|
||||
#ifdef LITE_USE_SDL_RENDERER
|
||||
int w, h;
|
||||
SDL_GL_GetDrawableSize(ren->window, &w, &h);
|
||||
setup_renderer(ren, w, h);
|
||||
#endif
|
||||
}
|
||||
|
||||
void renwin_update_rects(RenWindow *ren, RenRect *rects, int count) {
|
||||
#ifdef LITE_USE_SDL_RENDERER
|
||||
const int scale = ren->surface_scale;
|
||||
for (int i = 0; i < count; i++) {
|
||||
const RenRect *r = &rects[i];
|
||||
const int x = scale * r->x, y = scale * r->y;
|
||||
const int w = scale * r->width, h = scale * r->height;
|
||||
const SDL_Rect sr = {.x = x, .y = y, .w = w, .h = h};
|
||||
int32_t *pixels = ((int32_t *) ren->surface->pixels) + x + ren->surface->w * y;
|
||||
SDL_UpdateTexture(ren->texture, &sr, pixels, ren->surface->w * 4);
|
||||
}
|
||||
SDL_RenderCopy(ren->renderer, ren->texture, NULL, NULL);
|
||||
SDL_RenderPresent(ren->renderer);
|
||||
#else
|
||||
SDL_UpdateWindowSurfaceRects(ren->window, (SDL_Rect*) rects, count);
|
||||
#endif
|
||||
}
|
||||
|
||||
void renwin_free(RenWindow *ren) {
|
||||
SDL_DestroyWindow(ren->window);
|
||||
ren->window = NULL;
|
||||
#ifdef LITE_USE_SDL_RENDERER
|
||||
SDL_DestroyRenderer(ren->renderer);
|
||||
SDL_DestroyTexture(ren->texture);
|
||||
SDL_FreeSurface(ren->surface);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#include <SDL.h>
|
||||
#include "renderer.h"
|
||||
|
||||
struct RenWindow {
|
||||
SDL_Window *window;
|
||||
RenRect clip; /* Clipping rect in pixel coordinates. */
|
||||
#ifdef LITE_USE_SDL_RENDERER
|
||||
SDL_Renderer *renderer;
|
||||
SDL_Texture *texture;
|
||||
SDL_Surface *surface;
|
||||
int surface_scale;
|
||||
#endif
|
||||
};
|
||||
typedef struct RenWindow RenWindow;
|
||||
|
||||
void renwin_init_surface(RenWindow *ren);
|
||||
int renwin_surface_scale(RenWindow *ren);
|
||||
void renwin_clip_to_surface(RenWindow *ren);
|
||||
void renwin_set_clip_rect(RenWindow *ren, RenRect rect);
|
||||
void renwin_resize_surface(RenWindow *ren);
|
||||
void renwin_show_window(RenWindow *ren);
|
||||
void renwin_update_rects(RenWindow *ren, RenRect *rects, int count);
|
||||
void renwin_free(RenWindow *ren);
|
||||
SDL_Surface *renwin_get_surface(RenWindow *ren);
|
||||
|
Loading…
Reference in New Issue