parent
7299521ab1
commit
12f9d2ec2c
@ -1,13 +1,15 @@ |
|||||||
set(COMPONENT_SRCS |
set(COMPONENT_SRCS |
||||||
"app_main.c" |
"app_main.c" |
||||||
"nokia.c" |
|
||||||
"knob.c" |
"knob.c" |
||||||
"gui.c" |
"gui.c" |
||||||
"analog.c" |
"analog.c" |
||||||
"liquid/liquid.c" |
"liquid/liquid.c" |
||||||
"liquid/scene_root.c" |
"liquid/scene_root.c" |
||||||
"liquid/scene_car.c" |
"liquid/scene_car.c" |
||||||
|
"graphics/nokia.c" |
||||||
|
"graphics/utf8.c" |
||||||
|
"graphics/font.c" |
||||||
) |
) |
||||||
set(COMPONENT_ADD_INCLUDEDIRS "liquid") |
set(COMPONENT_ADD_INCLUDEDIRS "liquid" "graphics") |
||||||
|
|
||||||
register_component() |
register_component() |
||||||
|
@ -0,0 +1,24 @@ |
|||||||
|
/**
|
||||||
|
* TODO file description |
||||||
|
*
|
||||||
|
* Created on 2020/01/04. |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef REFLOWER_FONT_H |
||||||
|
#define REFLOWER_FONT_H |
||||||
|
|
||||||
|
#include "font.h" |
||||||
|
#include "utf8.h" |
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
struct FontSymbol { |
||||||
|
union { |
||||||
|
const char symbol[4]; |
||||||
|
const uint32_t uint; |
||||||
|
}; |
||||||
|
uint8_t graphic[5]; |
||||||
|
}; |
||||||
|
|
||||||
|
const struct FontSymbol *Font_GetSymbol(struct Utf8Char ch); |
||||||
|
|
||||||
|
#endif //REFLOWER_FONT_H
|
@ -0,0 +1,116 @@ |
|||||||
|
#include <stdint.h> |
||||||
|
#include "utf8.h" |
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
//
|
||||||
|
// Created by MightyPork on 2017/08/20.
|
||||||
|
//
|
||||||
|
// UTF-8 parser - collects bytes of a code point before writing them
|
||||||
|
// into a screen cell.
|
||||||
|
//
|
||||||
|
|
||||||
|
const struct Utf8Char EMPTY_CHAR = (struct Utf8Char) { .uint = 0 }; |
||||||
|
|
||||||
|
// Code Points First Byte Second Byte Third Byte Fourth Byte
|
||||||
|
// U+0000 - U+007F 00 - 7F
|
||||||
|
// U+0080 - U+07FF C2 - DF 80 - BF
|
||||||
|
// U+0800 - U+0FFF E0 *A0 - BF 80 - BF
|
||||||
|
// U+1000 - U+CFFF E1 - EC 80 - BF 80 - BF
|
||||||
|
// U+D000 - U+D7FF ED 80 - *9F 80 - BF
|
||||||
|
// U+E000 - U+FFFF EE - EF 80 - BF 80 - BF
|
||||||
|
// U+10000 - U+3FFFF F0 *90 - BF 80 - BF 80 - BF
|
||||||
|
// U+40000 - U+FFFFF F1 - F3 80 - BF 80 - BF 80 - BF
|
||||||
|
// U+100000 - U+10FFFF F4 80 - *8F 80 - BF 80 - BF
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a received character |
||||||
|
*/ |
||||||
|
struct Utf8Char Utf8Parser_Handle(struct Utf8Parser *self, char c) |
||||||
|
{ |
||||||
|
uint8_t *bytes = self->buffer.bytes; |
||||||
|
|
||||||
|
uint8_t uc = (uint8_t)c; |
||||||
|
// collecting unicode glyphs...
|
||||||
|
if (uc & 0x80) { |
||||||
|
if (self->utf_len == 0) { |
||||||
|
bytes[0] = uc; |
||||||
|
self->utf_j = 1; |
||||||
|
|
||||||
|
// start
|
||||||
|
if (uc == 0xC0 || uc == 0xC1 || uc > 0xF4) { |
||||||
|
// forbidden start codes
|
||||||
|
goto fail; |
||||||
|
} |
||||||
|
|
||||||
|
if ((uc & 0xE0) == 0xC0) { |
||||||
|
self->utf_len = 2; |
||||||
|
} |
||||||
|
else if ((uc & 0xF0) == 0xE0) { |
||||||
|
self->utf_len = 3; |
||||||
|
} |
||||||
|
else if ((uc & 0xF8) == 0xF0) { |
||||||
|
self->utf_len = 4; |
||||||
|
} |
||||||
|
else { |
||||||
|
// chars over 127 that don't start unicode sequences
|
||||||
|
goto fail; |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
if ((uc & 0xC0) != 0x80) { |
||||||
|
bytes[self->utf_j++] = uc; |
||||||
|
goto fail; |
||||||
|
} |
||||||
|
else { |
||||||
|
bytes[self->utf_j++] = uc; |
||||||
|
if (self->utf_j >= self->utf_len) { |
||||||
|
// check for bad sequences - overlong or some other problem
|
||||||
|
if (bytes[0] == 0xF4 && bytes[1] > 0x8F) goto fail; |
||||||
|
if (bytes[0] == 0xF0 && bytes[1] < 0x90) goto fail; |
||||||
|
if (bytes[0] == 0xED && bytes[1] > 0x9F) goto fail; |
||||||
|
if (bytes[0] == 0xE0 && bytes[1] < 0xA0) goto fail; |
||||||
|
|
||||||
|
// trap for surrogates - those break javascript
|
||||||
|
if (bytes[0] == 0xED && bytes[1] >= 0xA0 && bytes[1] <= 0xBF) goto fail; |
||||||
|
|
||||||
|
goto success; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
bytes[0] = uc; |
||||||
|
goto success; |
||||||
|
} |
||||||
|
|
||||||
|
return EMPTY_CHAR; |
||||||
|
|
||||||
|
success:; |
||||||
|
struct Utf8Char result = self->buffer; |
||||||
|
self->buffer.uint = 0; // erase the buffer
|
||||||
|
self->utf_len = 0; |
||||||
|
return result; |
||||||
|
|
||||||
|
fail: |
||||||
|
self->buffer.uint = 0; // erase the buffer
|
||||||
|
self->utf_len = 0; |
||||||
|
return EMPTY_CHAR; |
||||||
|
} |
||||||
|
|
||||||
|
void Utf8Iterator_Start(struct Utf8Iterator *self, const char *source) { |
||||||
|
memset(self, 0, sizeof(struct Utf8Iterator)); |
||||||
|
self->source = source; |
||||||
|
} |
||||||
|
|
||||||
|
struct Utf8Char Utf8Iterator_Next(struct Utf8Iterator *self) { |
||||||
|
char c; |
||||||
|
struct Utf8Char uchar; |
||||||
|
while ((c = *self->source++) != 0) { |
||||||
|
uchar = Utf8Parser_Handle(&self->parser, c); |
||||||
|
if (uchar.uint) { |
||||||
|
return uchar; |
||||||
|
} |
||||||
|
} |
||||||
|
return EMPTY_CHAR; |
||||||
|
} |
@ -0,0 +1,65 @@ |
|||||||
|
/**
|
||||||
|
* TODO file description |
||||||
|
*
|
||||||
|
* Created on 2020/01/04. |
||||||
|
*/ |
||||||
|
|
||||||
|
#ifndef LIQUIDTYPE_UTF8_H |
||||||
|
#define LIQUIDTYPE_UTF8_H |
||||||
|
|
||||||
|
#include <stddef.h> |
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
struct Utf8Char { |
||||||
|
union { |
||||||
|
uint8_t bytes[4]; |
||||||
|
uint32_t uint; |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
struct Utf8Parser { |
||||||
|
struct Utf8Char buffer; |
||||||
|
uint8_t utf_len; |
||||||
|
uint8_t utf_j; |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
* Utf8 character iterator. |
||||||
|
* |
||||||
|
* Usage: |
||||||
|
* struct Utf8Iterator iter; |
||||||
|
* Utf8Iterator_Start(&iter, myString); |
||||||
|
* |
||||||
|
* union Utf8Char uchar; |
||||||
|
* while ((uchar = Utf8Iterator_Next(&iter)).uint) { |
||||||
|
* // do something with the char
|
||||||
|
* } |
||||||
|
* |
||||||
|
* // Free myString if needed.
|
||||||
|
* // The iterator does not need any cleanup if it lives on stack.
|
||||||
|
*/ |
||||||
|
struct Utf8Iterator { |
||||||
|
/* Characters to parse. The pointer is advanced as the iterator progresses. */ |
||||||
|
const char *source; |
||||||
|
struct Utf8Parser parser; |
||||||
|
}; |
||||||
|
|
||||||
|
void Utf8Iterator_Start(struct Utf8Iterator *self, const char *source); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next character from the iterator; Returns empty character if there are no more characters to parse. |
||||||
|
* |
||||||
|
* Invalid characters are skipped. |
||||||
|
*/ |
||||||
|
struct Utf8Char Utf8Iterator_Next(struct Utf8Iterator *self); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a character. |
||||||
|
* |
||||||
|
* The returned struct contains NIL (uint == 0) if no character is yet available. |
||||||
|
* |
||||||
|
* ASCII is passed through, utf-8 is collected and returned in one piece. |
||||||
|
*/ |
||||||
|
struct Utf8Char Utf8Parser_Handle(struct Utf8Parser *self, char c); |
||||||
|
|
||||||
|
#endif //LIQUIDTYPE_UTF8_H
|
Loading…
Reference in new issue