Add startings of the Chroma Editor.

This commit is contained in:
Curle 2021-06-16 21:06:49 +01:00
parent 31fdb462ab
commit 5c4a557755
Signed by: TheCurle
GPG Key ID: 5942F13718443F79
6 changed files with 420 additions and 21 deletions

View File

@ -23,6 +23,7 @@ SET(src_files
${CMAKE_SOURCE_DIR}/src/system/memory/stack.c
${CMAKE_SOURCE_DIR}/src/system/memory/paging.c
${CMAKE_SOURCE_DIR}/src/system/memory/abstract_allocator.c
${CMAKE_SOURCE_DIR}/src/system/memory/liballoc.c
${CMAKE_SOURCE_DIR}/src/system/memory/physmem.c
${CMAKE_SOURCE_DIR}/src/system/drivers/keyboard.c
${CMAKE_SOURCE_DIR}/src/system/drivers/elf.c
@ -32,6 +33,9 @@ SET(lib_files
${CMAKE_SOURCE_DIR}/src/lainlib/list/basic_list.c
${CMAKE_SOURCE_DIR}/src/lainlib/mutex/ticketlock.c
${CMAKE_SOURCE_DIR}/src/lainlib/compression/lzgmini.c
${CMAKE_SOURCE_DIR}/src/lainlib/string/str.c
${CMAKE_SOURCE_DIR}/src/editor/EditorMain.c
)
include_directories("inc")
@ -44,7 +48,7 @@ SET(src_preamble
${CMAKE_SOURCE_DIR}/src/global/crt0.o
${CMAKE_SOURCE_DIR}/src/global/crti.o
${CMAKE_SOURCE_DIR}/src/global/crtbegin.o
)
)
set(src_epilogue
${CMAKE_SOURCE_DIR}/src/global/crtend.o

119
inc/editor/main.h Normal file
View File

@ -0,0 +1,119 @@
#pragma once
/************************
*** Team Kitty, 2021 ***
*** Chroma ***
***********************/
/**
* This file contains most of the symbols required to start and run the Chroma Editor.
*
* The Editor uses a six-stage drawing system:
* - Background
* - Bars
* - Text Area
* - Text
* - Effects
*
* The dimensions are derived dynamically from the Print Info settings.
*
* The layout is as such:
* - 3% horizontal header, #BBBBBB.
* - Primary text, #000084.
* - Secondary text, #000000.
* - 97% background, #000084.
* - 15% optional banner, #00AAAA.
* - 80% text area, #BBBBBB.
* - Menus #FFFFFF.
* - Buttons #BBBBBB.
* - Drop shadow #000000.
*/
// Stores information about a single line.
struct EditorLine {
size_t Line;
size_t Length;
char* Text;
};
// Function pointer for menu-clicked callback.
typedef void (*MenuCallback)(void);
// A single item in the menu.
struct MenuItem {
size_t ParentID; // 0 for the root menu.
size_t ID;
MenuCallback Callback;
};
// The full menu that should be rendered. Can be nested.
typedef struct {
size_t MenuSize;
struct MenuItem* Menu;
size_t ActiveMenuItem;
} EditorMenu;
struct EditorMessage {
size_t TextLength;
char* Text;
size_t MessageWidth;
size_t MessageHeight;
};
// Provides all the context for rendering the editor.
struct EditorLayout {
size_t ScreenWidth;
size_t ScreenHeight;
size_t HeaderHeight;
EditorMenu Menu;
size_t TextBoxX;
size_t TextBoxY;
size_t TextBoxWidth;
size_t TextBoxHeight;
bool HasMessage;
struct EditorMessage* CurrentMessage;
};
// Provides all the context for manipulating state.
typedef struct {
struct EditorLayout Layout;
size_t Length; // How many lines?
size_t Size; // How many characters?
size_t CurrentLine;
size_t CurrentColumn;
struct EditorLine* Lines;
} EditorState;
// Given the kernel's keyboard handler ID, so that it may restore it at a later point.
void StartEditor(int KernelCallbackID);
// =========================== Drawing routines =========================== //
// Draw everything.
void DrawEditor(EditorState* currentState);
void DrawHeader();
void DrawBackground();
void DrawTextArea();
void DrawText();
void DrawLine();
void DrawMenus();
void DrawBoxes();
void DrawBoxShadows();
// =========================== State management ===========================
EditorState* GetState();
// Text editing.
void GetLine(EditorState* state, size_t line);
void SetLine(EditorState* state, struct EditorLine* line);
void AppendLine(EditorState* state, struct EditorLine* line);
void AppendToLine(EditorState* state, struct EditorLine* line, size_t textLength, char* text);
void RemoveLine(EditorState* state, size_t line);

View File

@ -12,6 +12,10 @@
* Set color with PrintInfo.
*/
void _swap_size_t(size_t a, size_t b);
int abs(int x);
typedef struct {
uint32_t charHeight;
uint32_t charWidth;
@ -27,6 +31,9 @@ typedef struct {
size_t charsPerRow;
size_t rowsPerScrn;
uint32_t scrlMode;
size_t screenWidth;
size_t screenHeight;
} PRINTINFO;
extern PRINTINFO PrintInfo;
@ -39,8 +46,13 @@ uint32_t GetForegroundColor();
void SetBackgroundColor(uint32_t color);
uint32_t GetBackgroundColor();
void DrawLine(size_t x0, size_t y0, size_t x1, size_t y1);
void DrawFilledRect(size_t x, size_t y, size_t width, size_t height);
void DrawLineRect(size_t x, size_t y, size_t width, size_t height, size_t thickness);
void DrawFilledRoundedRect(size_t x, size_t y, size_t width, size_t height, size_t radius);
void DrawLineRoundedRect(size_t x, size_t y, size_t width, size_t height, size_t radius);
// When height == width, this draws a circle.
void DrawOval(size_t centerX, size_t centerY, size_t height, size_t width);
void DrawFilledCircle(size_t centerX, size_t centerY, size_t radius);
void DrawLineCircle(size_t centerX, size_t centerY, size_t radius);
void DrawLineCircleCorners(size_t centerX, size_t centerY, size_t radius, char cornerMask);

32
src/editor/EditorMain.c Normal file
View File

@ -0,0 +1,32 @@
#include <kernel/chroma.h>
#include <kernel/video/draw.h>
#include <editor/main.h>
/************************
*** Team Kitty, 2021 ***
*** Chroma ***
***********************/
/**
* Contains startup and setup routines for the Chroma Editor.
*/
static int KernelID;
void StartEditor(int callbackID) {
KernelID = callbackID;
struct EditorLayout layout = (struct EditorLayout) {0};
layout.ScreenHeight = PrintInfo.screenHeight;
layout.ScreenWidth = PrintInfo.screenWidth;
layout.HeaderHeight = layout.ScreenHeight / 100 * 3;
SetForegroundColor(0x000084);
FillScreen();
SetForegroundColor(0x00BBBBBB);
DrawFilledRect(0, 0, PrintInfo.screenWidth, layout.HeaderHeight);
for(;;) {}
}

View File

@ -20,14 +20,6 @@ PRINTINFO PrintInfo = {0};
#define FONT bitfont_latin
static size_t strlen(const char* String) {
size_t Len = 0;
while(String[Len] != '\0') {
Len++;
}
return Len;
}
void InitPrint() {
PrintInfo.charHeight = 8;
PrintInfo.charWidth = 8;
@ -43,6 +35,9 @@ void InitPrint() {
PrintInfo.scrlMode = 0;
PrintInfo.screenWidth = bootldr.fb_width;
PrintInfo.screenHeight = bootldr.fb_height;
PrintInfo.charsPerRow = bootldr.fb_width / (PrintInfo.charScale * PrintInfo.charWidth) - 4;
PrintInfo.rowsPerScrn = bootldr.fb_height / (PrintInfo.charScale * PrintInfo.charHeight);
SerialPrintf("[Print] A single character is %ux%u pixels.\r\n", PrintInfo.charScale * PrintInfo.charWidth, PrintInfo.charScale * PrintInfo.charHeight);
@ -107,8 +102,8 @@ static void DrawChar(const char character, size_t x, size_t y) {
}
void DrawPixel(size_t x, size_t y) {
if(x > bootldr.fb_width) {
DrawPixel(x - bootldr.fb_width, y + (PrintInfo.charHeight * PrintInfo.charScale));
if(x > bootldr.fb_scanline) {
DrawPixel(x - bootldr.fb_scanline, y + (PrintInfo.charHeight * PrintInfo.charScale));
} else if(y > bootldr.fb_height) {
DrawPixel(x, y - bootldr.fb_height);
} else {
@ -235,3 +230,248 @@ void WriteStringWithFont(const char *inChar) {
inChar++; kx++;
}
}
/********************************** Geometry Rendering **********************************/
/**
* Implementation borrowed with <3 from Adafruit: https://github.com/adafruit/Adafruit-GFX-Library/blob/master/Adafruit_GFX.cpp
* TODO: Reimplement in Helix.
*
*/
/******* Internal *******/
inline void _swap_size_t(size_t a, size_t b) {
size_t t = a;
a = b;
b = t;
}
inline int abs(int x) {
return x < 0 ? -x : x;
}
void DrawLineInternal(size_t x0, size_t y0, size_t x1, size_t y1) {
bool steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
_swap_size_t(x0, y0);
_swap_size_t(x1, y1);
}
if (x0 > x1) {
_swap_size_t(x0, x1);
_swap_size_t(y0, y1);
}
size_t dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
int err = dx / 2;
size_t ystep;
if (y0 < y1)
ystep = 1;
else
ystep = -1;
for (; x0 <= x1; x0++) {
if (steep)
DrawPixel(y0, x0);
else
DrawPixel(x0, y0);
err -= dy;
if (err < 0) {
y0 += ystep;
err += dx;
}
}
}
void DrawHorizontalLine(size_t x, size_t y, size_t w) {
DrawLineInternal(x, y, x + w - 1, y);
}
void DrawVerticalLine(size_t x, size_t y, size_t h) {
DrawLineInternal(x, y, x, y + h - 1);
}
void DrawFilledCircleInternal(size_t centerX, size_t centerY, size_t radius, char cornerMask, size_t offset) {
int f = 1 - radius;
size_t ddF_x = 1;
size_t ddF_y = -2 * radius;
size_t x = 0;
size_t y = radius;
size_t px = x;
size_t py = y;
offset++;
while (x < y) {
if (f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
if (x < (y + 1)) {
if (cornerMask & 1)
DrawVerticalLine(centerX + x, centerY - y, 2 * y + offset);
if (cornerMask & 2)
DrawVerticalLine(centerX - x, centerY - y, 2 * y + offset);
}
if (y != py) {
if (cornerMask & 1)
DrawVerticalLine(centerX + py, centerY - px, 2 * px + offset);
if (cornerMask & 2)
DrawVerticalLine(centerX - py, centerY - px, 2 * px + offset);
py = y;
}
px = x;
}
}
/******* Public *******/
void DrawFilledRect(size_t x, size_t y, size_t width, size_t height) {
for (size_t i = y; i < y + height; i++)
DrawHorizontalLine(x, i, width);
}
void DrawLineRect(size_t x, size_t y, size_t width, size_t height, size_t thickness) {
UNUSED(thickness);
DrawHorizontalLine(x, y, width);
DrawHorizontalLine(x, y + height - 1, width);
DrawVerticalLine(x, y, height);
DrawVerticalLine(x + width - 1, y, height);
}
void DrawFilledRoundedRect(size_t x, size_t y, size_t width, size_t height, size_t radius) {
size_t max_radius = ((width < height) ? width : height) / 2; // 1/2 minor axis
if (radius > max_radius)
radius = max_radius;
DrawFilledRect(x + radius, y, width - 2 * radius, height);
// draw four corners
DrawFilledCircleInternal(x + width - radius - 1, y + radius, radius, 1, height - 2 * radius - 1);
DrawFilledCircleInternal(x + radius, y + radius, radius, 2, height - 2 * radius - 1);
}
void DrawLineRoundedRect(size_t x, size_t y, size_t width, size_t height, size_t radius) {
size_t max_radius = ((width < height) ? width : height) / 2; // 1/2 minor axis
if (radius > max_radius)
radius = max_radius;
DrawHorizontalLine(x + radius, y, width - 2 * radius); // Top
DrawHorizontalLine(x + radius, y + height - 1, width - 2 * radius); // Bottom
DrawVerticalLine(x, y + radius, height - 2 * radius); // Left
DrawVerticalLine(x + width - 1, y + radius, height - 2 * radius); // Right
// draw four corners
DrawLineCircleCorners(x + radius, y + radius, radius, 1);
DrawLineCircleCorners(x + width - radius - 1, y + radius, radius, 2);
DrawLineCircleCorners(x + width - radius - 1, y + height - radius - 1, radius, 4);
DrawLineCircleCorners(x + radius, y + height - radius - 1, radius, 8);
}
void DrawLine(size_t x0, size_t y0, size_t x1, size_t y1) {
if (x0 == x1) {
if (y0 > y1)
_swap_size_t(y0, y1);
DrawVerticalLine(x0, y0, y1 - y0 + 1);
} else if (y0 == y1) {
if (x0 > x1)
_swap_size_t(x0, x1);
DrawHorizontalLine(x0, y0, x1 - x0 + 1);
} else {
DrawLineInternal(x0, y0, x1, y1);
}
}
void DrawCircle(size_t centerX, size_t centerY, size_t radius) {
int f = 1 - radius;
size_t ddF_x = 1;
size_t ddF_y = -2 * radius;
size_t x = 0;
size_t y = radius;
DrawPixel(centerX, centerY + radius);
DrawPixel(centerX, centerY - radius);
DrawPixel(centerX + radius, centerY);
DrawPixel(centerX - radius, centerY);
while (x < y) {
if (f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
DrawPixel(centerX + x, centerY + y);
DrawPixel(centerX - x, centerY + y);
DrawPixel(centerX + x, centerY - y);
DrawPixel(centerX - x, centerY - y);
DrawPixel(centerX + y, centerY + x);
DrawPixel(centerX - y, centerY + x);
DrawPixel(centerX + y, centerY - x);
DrawPixel(centerX - y, centerY - x);
}
}
void DrawLineCircleCorners(size_t centerX, size_t centerY, size_t radius, char cornerMask) {
int f = 1 - radius;
size_t ddF_x = 1;
size_t ddF_y = -2 * radius;
size_t x = 0;
size_t y = radius;
DrawPixel(centerX, centerY + radius);
DrawPixel(centerX, centerY - radius);
DrawPixel(centerX + radius, centerY);
DrawPixel(centerX - radius, centerY);
while (x < y) {
if (f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
if(cornerMask & 0x4) {
DrawPixel(centerX + x, centerY + y);
DrawPixel(centerX + y, centerY + x);
}
if(cornerMask & 0x2) {
DrawPixel(centerX + x, centerY - y);
DrawPixel(centerX - y, centerY - x);
}
if(cornerMask & 0x8) {
DrawPixel(centerX - y, centerY + x);
DrawPixel(centerX - x, centerY + y);
}
if(cornerMask & 0x1) {
DrawPixel(centerX - y, centerY - x);
DrawPixel(centerX - x, centerY - y);
}
}
}
void DrawFilledCircle(size_t centerX, size_t centerY, size_t radius) {
DrawVerticalLine(centerX, centerY - radius, 2 * radius + 1);
DrawFilledCircleInternal(centerX, centerY, radius, 3, 0);
}

View File

@ -13,14 +13,6 @@
* This file also provides SerialPrintf.
*/
static size_t strlen(const char* String) {
size_t Len = 0;
while(String[Len] != '\0') {
Len++;
}
return Len;
}
static void NumToStr(char* Buffer, size_t Num, size_t Base) {
size_t Temp, i = 0, j = 0;