Initial commit
This commit is contained in:
.gitignoreLinker.ldMakefileMakefile.flags
driver/irq/pic
execformat/pe
extlib
graphics
interrupt
handler.asm.Shandler.chandlers.hinit.cinterrupt.hinterrupt_testcode.Sload_gdt.Smap_handler.Ssyscall.Ssyscall.htestcode.h
kernel
libc
READMEabs.c
main.cmain.hinclude
assert.hctype.herrno.hfloat.hinttypes.hiso646.hlimits.hlocale.h
memcmp.cstrncat.cstrncmp.cstrncpy.cpdclib
_PDCLIB_config.h_PDCLIB_defguard.h_PDCLIB_glue.h_PDCLIB_internal.h_PDCLIB_lib_ext1.h_PDCLIB_print.h_PDCLIB_tzcode.h
signal.hstdalign.hstdarg.hstdbool.hstddef.hstdint.hstdio.hstdlib.hstdnoreturn.hstring.hthreads.htime.hwctype.hmemory
liballoc_impl.cmemory.cmemory.hmemory.hppmemory_cpp.cpppaging_init.cpaging_internal.hpaging_map.cpaging_modeswitch.Spaging_physical.ctest_fillbits.ctest_take_bitfield.c
run.cmdruntime
calling_convention.Scalling_convention.hmemcpy.cmemcpy.hmemset_memmove.Spanic_assert.asm.Spanic_assert.hprintf.cprintf.hstdio.cstdio.hstring.ctest_memmove.ctest_utf8.cunicode.cunicode.h
util
vterm
284
graphics/graphics.c
Normal file
284
graphics/graphics.c
Normal file
@ -0,0 +1,284 @@
|
||||
|
||||
|
||||
#include "graphics.h"
|
||||
#include "unifont.h"
|
||||
#include "../runtime/stdio.h"
|
||||
#include <efiprot.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "../runtime/memcpy.h"
|
||||
|
||||
const HelosGraphics_Color
|
||||
HelosGraphics_Color_Black = {0x00, 0x00, 0x00, 0xff},
|
||||
HelosGraphics_Color_White = {0xff, 0xff, 0xff, 0xff},
|
||||
HelosGraphics_Color_Red = {0x00, 0x00, 0xff, 0xff},
|
||||
HelosGraphics_Color_Green = {0x00, 0xff, 0x00, 0xff},
|
||||
HelosGraphics_Color_Blue = {0xff, 0x00, 0x00, 0xff},
|
||||
HelosGraphics_Color_Cyan = {0xff, 0xff, 0x00, 0xff},
|
||||
HelosGraphics_Color_Magenta = {0xff, 0x00, 0xff, 0xff},
|
||||
HelosGraphics_Color_Yellow = {0x00, 0xff, 0xff, 0xff};
|
||||
|
||||
|
||||
static EFI_GUID gopID = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
static EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
|
||||
|
||||
static EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
|
||||
static UINTN sizeofInfo, nModes, nativeMode;
|
||||
static HelosGraphics_Mode modes[128];
|
||||
|
||||
void *graphics_DeviceFramebuffer;
|
||||
|
||||
void * graphics_Framebuffer;
|
||||
uint64_t graphics_FramebufferSize;
|
||||
|
||||
uint32_t graphics_Doublebuffer[2048 * 1024];
|
||||
|
||||
|
||||
void graphics_Init() {
|
||||
assert(sizeof(HelosGraphics_Color) == sizeof(uint32_t) && "HelosGraphics_Color not packed to be 32-bit(4 bytes)");
|
||||
|
||||
EFI_STATUS status = efiBootServices->LocateProtocol(&gopID, NULL, (void **)&gop);
|
||||
if (EFI_ERROR(status)) {
|
||||
io_Printf("graphics_Init: Error locating GOP\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
status = gop->QueryMode(gop, gop->Mode == NULL ? 0 : gop->Mode->Mode, &sizeofInfo, &info);
|
||||
if (status == EFI_NOT_STARTED) {
|
||||
status = gop->SetMode(gop, 0);
|
||||
}
|
||||
if (EFI_ERROR(status)) {
|
||||
io_Printf("graphics_Init: Error getting native modes\r\n");
|
||||
return;
|
||||
} else {
|
||||
nativeMode = gop->Mode->Mode;
|
||||
nModes = gop->Mode->MaxMode;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nModes; i++) {
|
||||
status = gop->QueryMode(gop, i, &sizeofInfo, &info);
|
||||
modes[i].Width = info->HorizontalResolution;
|
||||
modes[i].Height = info->VerticalResolution;
|
||||
modes[i].PixelsPerLine = info->PixelsPerScanLine;
|
||||
modes[i].PixelFormat = info->PixelFormat;
|
||||
|
||||
if (modes[i].Width == HELOS_GRAPHICS_TARGET_MODE_WIDTH && modes[i].Height == HELOS_GRAPHICS_TARGET_MODE_HEIGHT)
|
||||
nativeMode = i;
|
||||
}
|
||||
|
||||
// set the new mode
|
||||
status = gop->SetMode(gop, nativeMode);
|
||||
if (EFI_ERROR(status)) {
|
||||
io_Printf("graphics_Init: Unable to set mode %d\r\n", nativeMode);
|
||||
return;
|
||||
}
|
||||
|
||||
io_Printf(
|
||||
"graphics_Init: Framebuffer:\r\n addr %08x len %d, size %dx%d, ppl %d\r\n",
|
||||
graphics_DeviceFramebuffer = (void *)gop->Mode->FrameBufferBase,
|
||||
graphics_FramebufferSize = gop->Mode->FrameBufferSize,
|
||||
gop->Mode->Info->HorizontalResolution,
|
||||
gop->Mode->Info->VerticalResolution,
|
||||
gop->Mode->Info->PixelsPerScanLine);
|
||||
|
||||
// warn the user if the framebuffer is not RGB
|
||||
io_Printf("graphics_Init: Framebuffer format: ");
|
||||
#define CASE(v) \
|
||||
break; \
|
||||
case v: io_Printf(#v "\r\n");
|
||||
switch (gop->Mode->Info->PixelFormat) {
|
||||
CASE(PixelRedGreenBlueReserved8BitPerColor)
|
||||
graphics_SetPixel = graphics_SetPixel_RGB;
|
||||
CASE(PixelBlueGreenRedReserved8BitPerColor)
|
||||
graphics_SetPixel = graphics_SetPixel_BGR;
|
||||
CASE(PixelBitMask)
|
||||
CASE(PixelBltOnly)
|
||||
CASE(PixelFormatMax)
|
||||
}
|
||||
#undef CASE
|
||||
|
||||
graphics_Framebuffer = (void *)graphics_Doublebuffer;
|
||||
graphics_CursorX = graphics_CursorY = 0;
|
||||
}
|
||||
|
||||
|
||||
graphics_SetPixel_Type *graphics_SetPixel;
|
||||
|
||||
void graphics_SetPixel_RGB(int posX, int posY, const HelosGraphics_Color *color) {
|
||||
struct {
|
||||
uint8_t R, G, B;
|
||||
uint8_t A;
|
||||
} colorRGB = {color->R, color->G, color->B, 0};
|
||||
|
||||
*((uint32_t *)(graphics_Framebuffer + modes[nativeMode].PixelsPerLine * 4 * posY + 4 * posX)) = (*((uint32_t *)&colorRGB));
|
||||
}
|
||||
|
||||
void graphics_SetPixel_BGR(int posX, int posY, const HelosGraphics_Color *color) {
|
||||
*((uint32_t *)(graphics_Framebuffer + modes[nativeMode].PixelsPerLine * 4 * posY + 4 * posX)) = (*((uint32_t *)color)) & 0x00ffffffu;
|
||||
}
|
||||
|
||||
|
||||
void graphics_GetSize(int *sizeX, int *sizeY, int *bitsPerPixel) {
|
||||
*sizeX = modes[nativeMode].Width;
|
||||
*sizeY = modes[nativeMode].Height;
|
||||
*bitsPerPixel = 24;
|
||||
}
|
||||
|
||||
void graphics_ClearBuffer(const HelosGraphics_Color *color) {
|
||||
uint32_t data;
|
||||
|
||||
if (*((uint32_t *)color) == *((uint32_t *)&HelosGraphics_Color_Black)) {
|
||||
memset(graphics_Framebuffer, 0, graphics_FramebufferSize);
|
||||
return;
|
||||
}
|
||||
|
||||
if (modes[nativeMode].PixelFormat == PixelRedGreenBlueReserved8BitPerColor) {
|
||||
struct {
|
||||
uint8_t R, G, B;
|
||||
uint8_t A;
|
||||
} colorRGB = {color->R, color->G, color->B, 0};
|
||||
data = (*(uint32_t *)&colorRGB) & 0x00ffffffu;
|
||||
} else if (modes[nativeMode].PixelFormat == PixelBlueGreenRedReserved8BitPerColor) {
|
||||
data = (*(uint32_t *)color) & 0x00ffffffu;
|
||||
}
|
||||
|
||||
uint32_t *buffer = graphics_Framebuffer, *end = graphics_Framebuffer + graphics_FramebufferSize / sizeof(uint32_t);
|
||||
while (buffer != end) {
|
||||
*buffer = data;
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
|
||||
void graphics_SwapBuffer() {
|
||||
memcpy(graphics_DeviceFramebuffer, graphics_Framebuffer, graphics_FramebufferSize);
|
||||
}
|
||||
|
||||
void graphics_FillPixel(int startX, int startY, int endX, int endY, const HelosGraphics_Color *color) {
|
||||
// TODO Optimize this! This is too sloooow
|
||||
if (gop->Mode->Info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor)
|
||||
for (int i = startX; i < endX; i++)
|
||||
for (int j = startY; j < endY; j++)
|
||||
*((uint32_t *)(graphics_Framebuffer + modes[nativeMode].PixelsPerLine * 4 * j + 4 * i)) = (*((uint32_t *)color)) & 0x00ffffffu;
|
||||
else if (gop->Mode->Info->PixelFormat == PixelRedGreenBlueReserved8BitPerColor)
|
||||
for (int i = startX; i < endX; i++)
|
||||
for (int j = startY; j < endY; j++) {
|
||||
struct {
|
||||
uint8_t B, G, R;
|
||||
uint8_t A;
|
||||
} colorRGB = {color->B, color->G, color->R, 0};
|
||||
|
||||
*((uint32_t *)(graphics_Framebuffer + modes[nativeMode].PixelsPerLine * 4 * j + 4 * i)) = (*((uint32_t *)&colorRGB));
|
||||
}
|
||||
}
|
||||
|
||||
int graphics_CursorX, graphics_CursorY;
|
||||
|
||||
void graphics_Scroll(int scrollY) {
|
||||
memmove(
|
||||
graphics_Doublebuffer,
|
||||
graphics_Doublebuffer + modes[nativeMode].PixelsPerLine * scrollY,
|
||||
sizeof(uint32_t) * (modes[nativeMode].PixelsPerLine * (modes[nativeMode].Height - scrollY)));
|
||||
// TODO proper memset instead of this sloooow FillPixel
|
||||
/*memset(
|
||||
graphics_Doublebuffer + modes[nativeMode].PixelsPerLine * (modes[nativeMode].Height - scrollY),
|
||||
0,
|
||||
sizeof(uint32_t) * modes[nativeMode].PixelsPerLine * (scrollY));*/
|
||||
graphics_FillPixel(0, modes[nativeMode].Height - scrollY, modes[nativeMode].Width, modes[nativeMode].Height, &HelosGraphics_Color_Black);
|
||||
}
|
||||
|
||||
void graphics_ElementSize(int sizeX, int sizeY) {
|
||||
if (graphics_CursorX + sizeX >= modes[nativeMode].Width) { // line breaking required
|
||||
graphics_CursorY += sizeY;
|
||||
graphics_CursorX = 0;
|
||||
}
|
||||
if (graphics_CursorY + sizeY >= modes[nativeMode].Height) { // scrolling required
|
||||
graphics_Scroll(sizeY + graphics_CursorY - modes[nativeMode].Height);
|
||||
graphics_CursorY = modes[nativeMode].Height - sizeY;
|
||||
}
|
||||
}
|
||||
|
||||
void graphics_Newline(int advanceY) {
|
||||
graphics_CursorY += advanceY;
|
||||
graphics_CursorX = 0;
|
||||
}
|
||||
|
||||
|
||||
void console_WriteChar(const HelosGraphics_Color *color, uint32_t c) {
|
||||
int width;
|
||||
switch (c) {
|
||||
case '\n':
|
||||
graphics_Newline(UNIFONT_CHAR_HEIGHT);
|
||||
break;
|
||||
case '\r':
|
||||
graphics_CursorX = 0;
|
||||
break;
|
||||
default:
|
||||
width = unifont_IsCharDoublewidth(c) ? UNIFONT_CHAR_WIDTH * 2 : UNIFONT_CHAR_WIDTH;
|
||||
graphics_ElementSize(width, UNIFONT_CHAR_HEIGHT);
|
||||
graphics_FillPixel(graphics_CursorX, graphics_CursorY, graphics_CursorX + width, graphics_CursorY + UNIFONT_CHAR_HEIGHT, &HelosGraphics_Color_Black);
|
||||
unifont_DrawChar(graphics_CursorX, graphics_CursorY, color, c);
|
||||
graphics_CursorX += width;
|
||||
}
|
||||
}
|
||||
|
||||
void console_Write(const HelosGraphics_Color *color, const uint32_t *str, int len) {
|
||||
bool wantSwap = false;
|
||||
if (len == 0) {
|
||||
while (*str != 0) {
|
||||
console_WriteChar(color, *str);
|
||||
if (*str == '\n')
|
||||
wantSwap = true;
|
||||
str++;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
console_WriteChar(color, str[i]);
|
||||
if (str[i] == '\n')
|
||||
wantSwap = true;
|
||||
}
|
||||
}
|
||||
if (wantSwap)
|
||||
graphics_SwapBuffer();
|
||||
}
|
||||
|
||||
void console_WriteUTF16(const HelosGraphics_Color *color, const uint16_t *str, int len) {
|
||||
bool wantSwap = false;
|
||||
if (len == 0) {
|
||||
while (*str != 0) {
|
||||
console_WriteChar(color, *str);
|
||||
if (*str == '\n')
|
||||
wantSwap = true;
|
||||
str++;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
console_WriteChar(color, str[i]);
|
||||
if (str[i] == '\n')
|
||||
wantSwap = true;
|
||||
}
|
||||
}
|
||||
if (wantSwap)
|
||||
graphics_SwapBuffer();
|
||||
}
|
||||
|
||||
void console_WriteASCII(const HelosGraphics_Color *color, const char *str, int len) {
|
||||
bool wantSwap = false;
|
||||
if (len == 0) {
|
||||
while (*str != 0) {
|
||||
console_WriteChar(color, *str);
|
||||
if (*str == '\n')
|
||||
wantSwap = true;
|
||||
str++;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
console_WriteChar(color, str[i]);
|
||||
if (str[i] == '\n')
|
||||
wantSwap = true;
|
||||
}
|
||||
}
|
||||
if (wantSwap)
|
||||
graphics_SwapBuffer();
|
||||
}
|
86
graphics/graphics.h
Normal file
86
graphics/graphics.h
Normal file
@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
|
||||
#include "../main.h"
|
||||
#include "efiprot.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// This defines a default target display mode for graphics_Init().
|
||||
#define HELOS_GRAPHICS_TARGET_MODE_WIDTH 1600
|
||||
#define HELOS_GRAPHICS_TARGET_MODE_HEIGHT 900
|
||||
|
||||
// HelosGraphics_Color is in ARGB little-endian packed format
|
||||
// (B,G,R,A in byte order)
|
||||
typedef struct {
|
||||
uint8_t B, G, R;
|
||||
uint8_t A;
|
||||
} PACKED HelosGraphics_Color;
|
||||
|
||||
extern const HelosGraphics_Color
|
||||
HelosGraphics_Color_Black,
|
||||
HelosGraphics_Color_White,
|
||||
HelosGraphics_Color_Red,
|
||||
HelosGraphics_Color_Green,
|
||||
HelosGraphics_Color_Blue,
|
||||
HelosGraphics_Color_Cyan,
|
||||
HelosGraphics_Color_Magenta,
|
||||
HelosGraphics_Color_Yellow;
|
||||
|
||||
typedef struct {
|
||||
int Width, Height;
|
||||
int PixelsPerLine;
|
||||
|
||||
EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
|
||||
} HelosGraphics_Mode;
|
||||
|
||||
|
||||
extern void * graphics_DeviceFramebuffer; // this is the framebuffer directly for the device via memory mapping.
|
||||
extern void * graphics_Framebuffer; // this is the double-buffered framebuffer (back buffer)
|
||||
extern uint64_t graphics_FramebufferSize;
|
||||
|
||||
|
||||
// Init() must be called prior to ExitBootServices()
|
||||
void graphics_Init();
|
||||
|
||||
|
||||
// bitsPerPixel does not count the alpha bits, i.e., is 24 on most modern monitors
|
||||
void graphics_GetSize(int *sizeX, int *sizeY, int *bitsPerPixel);
|
||||
void graphics_ClearBuffer(const HelosGraphics_Color *color);
|
||||
void graphics_SwapBuffer();
|
||||
|
||||
|
||||
// graphics_SetPixel is set by Init() to match one of SetPixel_RGB/BGR according to the framebuffer format.
|
||||
typedef void(graphics_SetPixel_Type)(int posX, int posY, const HelosGraphics_Color *color);
|
||||
extern graphics_SetPixel_Type *graphics_SetPixel;
|
||||
|
||||
// graphics_SetPixel_RGB/BGR writes the given pixel to the framebuffer in RGB/BGR format.
|
||||
void graphics_SetPixel_RGB(int posX, int posY, const HelosGraphics_Color *color);
|
||||
void graphics_SetPixel_BGR(int posX, int posY, const HelosGraphics_Color *color);
|
||||
|
||||
|
||||
void graphics_FillPixel(int startX, int startY, int endX, int endY, const HelosGraphics_Color *color);
|
||||
|
||||
|
||||
extern int graphics_CursorX, graphics_CursorY;
|
||||
|
||||
// graphics_Scroll scrolls the display vertically by scrollY pixels.
|
||||
void graphics_Scroll(int scrollY);
|
||||
// graphics_ElementSize handles size of an graphics element: scrolling, line breaking, etc.
|
||||
//
|
||||
// It does not change CursorX/Y, however.
|
||||
void graphics_ElementSize(int sizeX, int sizeY);
|
||||
void graphics_Newline(int advanceY);
|
||||
|
||||
|
||||
void console_WriteChar(const HelosGraphics_Color *color, uint32_t c);
|
||||
void console_Write(const HelosGraphics_Color *color, const uint32_t *str, int len);
|
||||
void console_WriteUTF16(const HelosGraphics_Color *color, const uint16_t *str, int len);
|
||||
void console_WriteASCII(const HelosGraphics_Color *color, const char *str, int len);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
18
graphics/test_unifont.c
Normal file
18
graphics/test_unifont.c
Normal file
@ -0,0 +1,18 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Unifont.h"
|
||||
|
||||
int main() {
|
||||
printf("Data at 0x%X\n\n", unifont_Data);
|
||||
|
||||
for (int i = 0; i < 64; i++) {
|
||||
printf("%02d(%02X):", i, i);
|
||||
for (int j = 0; j < 32; j++) {
|
||||
printf("%02X", (unsigned int)unifont_Data[i * 32 + j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
43
graphics/unifont.c
Normal file
43
graphics/unifont.c
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
#include "unifont.h"
|
||||
#include "graphics.h"
|
||||
#include <stddef.h>
|
||||
|
||||
size_t strlen(const char *);
|
||||
|
||||
void unifont_DrawChar(int posX, int posY, const HelosGraphics_Color *color, uint32_t codepoint) {
|
||||
const unsigned char *data = unifont_Data + codepoint * UNIFONT_CHAR_WIDTH * UNIFONT_CHAR_HEIGHT * 2 / 8;
|
||||
bool wide = unifont_IsCharDoublewidth(codepoint);
|
||||
|
||||
int charWidth = UNIFONT_CHAR_WIDTH * (wide ? 2 : 1);
|
||||
|
||||
for (int x = 0; x < charWidth; x++)
|
||||
for (int y = 0; y < UNIFONT_CHAR_HEIGHT; y++) {
|
||||
int pos = y * charWidth + x;
|
||||
if (data[pos / 8] & (1u << (7 - pos % 8)))
|
||||
graphics_SetPixel(posX + x, posY + y, color);
|
||||
}
|
||||
}
|
||||
|
||||
void unifont_DrawString(int posX, int posY, const HelosGraphics_Color *color, const uint32_t *codepoints, int count) {
|
||||
for (const uint32_t *end = codepoints + count; codepoints != end; codepoints++) {
|
||||
unifont_DrawChar(posX, posY, color, *codepoints);
|
||||
posX += UNIFONT_CHAR_WIDTH * (unifont_IsCharDoublewidth(*codepoints) ? 2 : 1);
|
||||
}
|
||||
}
|
||||
void unifont_DrawStringUTF16(int posX, int posY, const HelosGraphics_Color *color, const uint16_t *codepoints, int count) {
|
||||
for (const uint16_t *end = codepoints + count; codepoints != end; codepoints++) {
|
||||
unifont_DrawChar(posX, posY, color, *codepoints);
|
||||
posX += UNIFONT_CHAR_WIDTH * (unifont_IsCharDoublewidth(*codepoints) ? 2 : 1);
|
||||
}
|
||||
}
|
||||
void unifont_DrawStringASCII(int posX, int posY, const HelosGraphics_Color *color, const char *codepoints, int count) {
|
||||
if (count == 0) {
|
||||
count = strlen(codepoints);
|
||||
}
|
||||
for (const char *end = codepoints + count; codepoints != end; codepoints++) {
|
||||
unifont_DrawChar(posX, posY, color, *codepoints);
|
||||
//posX += UNIFONT_CHAR_WIDTH * (unifont_IsCharDoublewidth(*codepoints) ? 2 : 1);
|
||||
posX += UNIFONT_CHAR_WIDTH; // visible ASCII chars are all single-width
|
||||
}
|
||||
}
|
29
graphics/unifont.h
Normal file
29
graphics/unifont.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "../main.h"
|
||||
#include "graphics.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
#define UNIFONT_MAX_CHAR (0xffff)
|
||||
#define UNIFONT_CHAR_COUNT (0xffff + 1)
|
||||
|
||||
#define UNIFONT_CHAR_WIDTH 8
|
||||
#define UNIFONT_CHAR_HEIGHT 16
|
||||
|
||||
extern const unsigned char unifont_Data[], unifont_Width[];
|
||||
extern const unsigned char unifont_Data_End[], unifont_Width_End[]; // Past-the-end pointers for the data files
|
||||
|
||||
static inline bool unifont_IsCharDoublewidth(uint32_t codepoint) {
|
||||
const unsigned char *ptr = unifont_Width + codepoint / 8;
|
||||
if (ptr < unifont_Width_End)
|
||||
return (*ptr) & (1u << (7 - codepoint % 8));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void unifont_DrawChar(int posX, int posY, const HelosGraphics_Color *color, uint32_t codepoint);
|
||||
void unifont_DrawString(int posX, int posY, const HelosGraphics_Color *color, const uint32_t *codepoints, int count);
|
||||
void unifont_DrawStringUTF16(int posX, int posY, const HelosGraphics_Color *color, const uint16_t *codepoints, int count);
|
||||
void unifont_DrawStringASCII(int posX, int posY, const HelosGraphics_Color *color, const char *codepoints, int count);
|
71
graphics/xcursor/xcursor.h
Normal file
71
graphics/xcursor/xcursor.h
Normal file
@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../main.h"
|
||||
#include "../graphics.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// XCursor file format - see man page xcursor(3)
|
||||
// https://www.x.org/releases/X11R7.7/doc/man/man3/Xcursor.3.xhtml
|
||||
|
||||
// Header
|
||||
typedef struct {
|
||||
char magic[4]; // Magic string "Xcur"
|
||||
uint32_t headerSize; // Size of the header (16)
|
||||
uint32_t version; // File version number
|
||||
uint32_t numTOC; // Number of entries in the Table of Contents
|
||||
} PACKED xcursor_Header;
|
||||
|
||||
// Table of Content Entry
|
||||
typedef struct {
|
||||
uint32_t type; // Entry chunk type (0xfffe0001 = Comment, 0xfffd0002 = Image)
|
||||
uint32_t subtype; // Type specific Subtype, size(width=height) for images
|
||||
uint32_t offset; // Absolute byte position in the file
|
||||
} PACKED xcursor_TOCEntry;
|
||||
|
||||
|
||||
#define XCURSOR_CHUNKTYPE_COMMENT 0xfffe0001u
|
||||
#define XCURSOR_CHUNKTYPE_IMAGE 0xfffd0002u
|
||||
|
||||
// Common parts in different types of Chunk Headers
|
||||
typedef struct {
|
||||
uint32_t headerSize; // Size of the header
|
||||
uint32_t type; // Type of the Chunk, matches the Entry Type in the TOC
|
||||
uint32_t subtype; // Type specific subtype
|
||||
uint32_t version; // Version number of the chunk type
|
||||
} PACKED xcursor_ChunkHeader;
|
||||
|
||||
#define XCURSOR_COMMENT_SUBTYPE_COPYRIGHT 0x00000001u
|
||||
#define XCURSOR_COMMENT_SUBTYPE_LICENSE 0x00000002u
|
||||
#define XCURSOR_COMMENT_SUBTYPE_OTHER 0x00000003u
|
||||
|
||||
// Chunk Header for type Comment
|
||||
typedef struct {
|
||||
uint32_t headerSize; // Size of the header
|
||||
uint32_t type; // Type of the Chunk, matches the Entry Type in the TOC
|
||||
uint32_t subtype; // Type specific subtype, Copyright, License or Other
|
||||
uint32_t version; // Version number of the chunk type, =1
|
||||
|
||||
uint32_t length; // Length in bytes of the UTF-8 string
|
||||
char string[1]; // The UTF-8 string, spanning the rest of the chunk
|
||||
} PACKED xcursor_ChunkHeader_Comment;
|
||||
|
||||
typedef struct {
|
||||
uint32_t headerSize; // Size of the header
|
||||
uint32_t type; // Type of the Chunk, matches the Entry Type in the TOC
|
||||
uint32_t subtype; // Type specific subtype, Copyright, License or Other
|
||||
uint32_t version; // Version number of the chunk type, =1
|
||||
|
||||
uint32_t width, height; // Width/Height, <=0x7fff
|
||||
uint32_t xhot, yhot; // X/Y hotpoint, <=Width/Height
|
||||
uint32_t delay; // Delay between animation frames in milliseconds
|
||||
HelosGraphics_Color pixels[1]; // Packed ARGB little-endian format pixels, with A at the highest byte (BGRA in byte order)
|
||||
} PACKED xcursor_ChunkHeader_Image;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user