parent
7299521ab1
commit
12f9d2ec2c
@ -1,13 +1,15 @@ |
||||
set(COMPONENT_SRCS |
||||
"app_main.c" |
||||
"nokia.c" |
||||
"knob.c" |
||||
"gui.c" |
||||
"analog.c" |
||||
"liquid/liquid.c" |
||||
"liquid/scene_root.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() |
||||
|
@ -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