awtk/tools/theme_gen/xml_theme_gen.cc

313 lines
7.5 KiB
C++
Raw Normal View History

2018-02-21 19:36:38 +08:00
/**
* File: xml_gen.c
2018-05-15 09:31:58 +08:00
* Author: AWTK Develop Team
2018-02-21 19:36:38 +08:00
* Brief: generate theme date from xml
*
2020-01-01 11:27:36 +08:00
* Copyright (c) 2018 - 2020 Guangzhou ZHIYUAN Electronics Co.,Ltd.
2018-02-21 19:36:38 +08:00
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* License file for more details.
*
*/
/**
* History:
* ================================================================
* 2018-01-19 Li XianJing <xianjimli@hotmail.com> adapted from ftk.
*
*/
2018-03-18 11:29:31 +08:00
#include "theme_gen.h"
2018-02-21 19:36:38 +08:00
#include "base/enums.h"
#include "base/theme.h"
2019-09-18 18:02:37 +08:00
#include "base/style.h"
2018-02-21 19:36:38 +08:00
#include "base/widget.h"
#include "common/utils.h"
2018-03-18 11:29:31 +08:00
#include "xml_theme_gen.h"
2018-02-21 19:36:38 +08:00
#include "xml/xml_parser.h"
#include "tkc/color_parser.h"
2020-07-08 16:39:01 +08:00
#include "tkc/buffer.h"
2018-08-24 07:45:37 +08:00
#include "base/assets_manager.h"
2018-02-21 19:36:38 +08:00
2020-11-25 11:16:33 +08:00
#define TAG_PROPERTY "property"
2018-02-21 19:36:38 +08:00
typedef struct _xml_builder_t {
XmlBuilder builder;
ThemeGen gen;
Style widget_style;
Style share_style;
2020-11-25 11:16:33 +08:00
Style state_style;
2018-03-31 13:48:18 +08:00
uint16_t level;
2018-07-17 11:27:14 +08:00
string style_name;
2018-06-25 17:27:17 +08:00
string widget_type;
2020-11-25 11:16:33 +08:00
bool_t is_property;
char property_name[TK_NAME_LEN * 2 + 2];
2018-02-21 19:36:38 +08:00
} xml_builder_t;
static void xml_gen_style(xml_builder_t* b, Style& s, const char** attrs) {
2019-09-18 18:02:37 +08:00
value_t v;
uint32_t i = 0;
2019-09-18 18:02:37 +08:00
value_set_int(&v, 0);
while (attrs[i]) {
const char* name = attrs[i];
const char* value = attrs[i + 1];
2019-09-18 18:02:37 +08:00
ENSURE(style_normalize_value(name, value, &v) == RET_OK);
if (strcmp(name, "name") != 0) {
if (v.type == VALUE_TYPE_STRING) {
s.AddString(name, value_str(&v));
} else {
s.AddInt(name, value_int(&v));
}
}
2020-10-18 12:17:55 +08:00
value_reset(&v);
i += 2;
}
}
2018-03-31 13:48:18 +08:00
static void xml_gen_on_widget(xml_builder_t* b, const char* tag, const char** attrs) {
b->widget_style.Reset();
xml_gen_style(b, b->widget_style, attrs);
2018-06-25 17:27:17 +08:00
b->widget_type = tag;
2018-07-17 11:27:14 +08:00
b->style_name = TK_DEFAULT_STYLE;
2018-03-31 13:48:18 +08:00
}
static void xml_gen_on_style(xml_builder_t* b, const char* tag, const char** attrs) {
2018-02-21 19:36:38 +08:00
uint32_t i = 0;
2018-07-17 11:27:14 +08:00
b->style_name = TK_DEFAULT_STYLE;
2018-02-21 19:36:38 +08:00
2018-03-31 13:48:18 +08:00
while (attrs[i]) {
const char* name = attrs[i];
const char* value = attrs[i + 1];
2018-02-21 19:36:38 +08:00
if (strcmp(name, "name") == 0) {
2018-07-17 11:27:14 +08:00
b->style_name = value;
2018-03-31 13:48:18 +08:00
}
2018-03-31 13:48:18 +08:00
i += 2;
}
b->share_style.Reset();
xml_gen_style(b, b->share_style, attrs);
2018-03-31 13:48:18 +08:00
}
2018-02-21 19:36:38 +08:00
2018-03-31 13:48:18 +08:00
static void xml_gen_on_state(xml_builder_t* b, const char* tag, const char** attrs) {
2020-11-25 11:16:33 +08:00
b->state_style.Reset();
b->state_style.widget_type = b->widget_type;
b->state_style.name = b->style_name;
b->state_style.state = tag;
xml_gen_style(b, b->state_style, attrs);
}
2018-02-21 19:36:38 +08:00
2020-11-25 11:16:33 +08:00
static void xml_gen_on_start_property(XmlBuilder* thiz, const char* tag, const char** attrs) {
uint32_t i = 0;
xml_builder_t* b = (xml_builder_t*)thiz;
2018-02-21 19:36:38 +08:00
2020-11-25 11:16:33 +08:00
while (attrs[i] != NULL) {
const char* key = attrs[i];
const char* value = attrs[i + 1];
if (tk_str_eq(key, "name")) {
tk_strncpy(b->property_name, value, TK_NAME_LEN * 2 + 1);
break;
}
}
2018-03-31 13:48:18 +08:00
}
static void xml_gen_on_start(XmlBuilder* thiz, const char* tag, const char** attrs) {
xml_builder_t* b = (xml_builder_t*)thiz;
2020-11-25 11:16:33 +08:00
if (tk_str_eq(tag, TAG_PROPERTY)) {
b->is_property = TRUE;
xml_gen_on_start_property(thiz, tag, attrs);
2018-03-31 13:48:18 +08:00
} else {
2020-11-25 11:16:33 +08:00
b->is_property = FALSE;
if (b->level == 0) {
xml_gen_on_widget(b, tag, attrs);
} else if (b->level == 1) {
xml_gen_on_style(b, tag, attrs);
} else {
xml_gen_on_state(b, tag, attrs);
}
b->level++;
2018-03-31 13:48:18 +08:00
}
2018-02-21 19:36:38 +08:00
return;
}
2020-11-25 11:16:33 +08:00
static void xml_gen_on_widget_end(XmlBuilder* thiz) {
xml_builder_t* b = (xml_builder_t*)thiz;
2020-12-01 14:46:46 +08:00
2020-11-25 11:16:33 +08:00
for (int i = 0; i < b->widget_style.datas.size(); i++) {
2020-12-01 14:46:46 +08:00
Style& style = b->widget_style.datas[i];
2020-11-25 11:16:33 +08:00
for (int j = 0; j < style.datas.size(); j++) {
Style state;
state.Merge(b->widget_style);
state.Merge(style);
state.Merge(style.datas[j]);
state.widget_type = style.datas[j].widget_type;
state.name = style.datas[j].name;
state.state = style.datas[j].state;
b->gen.AddStyle(state);
}
}
}
static void xml_gen_on_style_end(XmlBuilder* thiz) {
xml_builder_t* b = (xml_builder_t*)thiz;
b->widget_style.datas.push_back(b->share_style);
b->share_style.Reset();
}
static void xml_gen_on_state_end(XmlBuilder* thiz) {
xml_builder_t* b = (xml_builder_t*)thiz;
b->share_style.datas.push_back(b->state_style);
b->state_style.Reset();
}
2018-02-21 19:36:38 +08:00
static void xml_gen_on_end(XmlBuilder* thiz, const char* tag) {
(void)tag;
2018-03-31 13:48:18 +08:00
xml_builder_t* b = (xml_builder_t*)thiz;
2020-11-25 11:16:33 +08:00
if (tk_str_eq(tag, TAG_PROPERTY)) {
b->is_property = FALSE;
} else {
if (b->level == 1) {
xml_gen_on_widget_end(thiz);
} else if (b->level == 2) {
xml_gen_on_style_end(thiz);
} else if (b->level == 3) {
xml_gen_on_state_end(thiz);
}
b->level--;
}
2018-03-31 13:48:18 +08:00
2018-02-21 19:36:38 +08:00
return;
}
static void xml_gen_on_text(XmlBuilder* thiz, const char* text, size_t length) {
2020-11-25 11:16:33 +08:00
xml_builder_t* b = (xml_builder_t*)thiz;
if (b->is_property) {
2020-12-05 08:10:11 +08:00
Style* s = NULL;
2020-11-25 11:16:33 +08:00
if (b->level == 1) {
s = &(b->widget_style);
} else if (b->level == 2) {
s = &(b->share_style);
} else if (b->level == 3) {
s = &(b->state_style);
}
2020-12-05 08:10:11 +08:00
if (s != NULL) {
value_t v;
ENSURE(style_normalize_value(b->property_name, text, &v) == RET_OK);
if (v.type == VALUE_TYPE_STRING) {
s->AddString(b->property_name, value_str(&v));
} else {
s->AddInt(b->property_name, value_int(&v));
}
value_reset(&v);
2020-11-25 11:16:33 +08:00
}
}
2018-02-21 19:36:38 +08:00
return;
}
static void xml_gen_on_comment(XmlBuilder* thiz, const char* text, size_t length) {
(void)thiz;
(void)text;
(void)length;
return;
}
static void xml_gen_on_pi(XmlBuilder* thiz, const char* tag, const char** attrs) {
(void)thiz;
(void)tag;
(void)attrs;
return;
}
static void xml_gen_on_error(XmlBuilder* thiz, int line, int row, const char* message) {
(void)thiz;
printf("parse error: %d:%d %s\n", line, row, message);
return;
}
static void xml_gen_destroy(XmlBuilder* thiz) {
(void)thiz;
return;
}
static XmlBuilder* builder_init(xml_builder_t& b) {
b.builder.on_start = xml_gen_on_start;
b.builder.on_end = xml_gen_on_end;
b.builder.on_text = xml_gen_on_text;
b.builder.on_error = xml_gen_on_error;
b.builder.on_comment = xml_gen_on_comment;
b.builder.on_pi = xml_gen_on_pi;
b.builder.destroy = xml_gen_destroy;
b.level = 0;
2018-07-17 11:27:14 +08:00
b.style_name = TK_DEFAULT_STYLE;
2018-06-25 17:27:17 +08:00
b.widget_type = "";
2020-12-08 15:20:04 +08:00
b.is_property = FALSE;
2018-02-21 19:36:38 +08:00
return &(b.builder);
}
uint32_t xml_gen_buff(const char* xml, uint8_t* output, uint32_t max_size) {
xml_builder_t b;
return_value_if_fail(xml != NULL && output != NULL, 0);
XmlParser* parser = xml_parser_create();
xml_parser_set_builder(parser, builder_init(b));
xml_parser_parse(parser, xml, strlen(xml));
2020-07-08 16:39:01 +08:00
wbuffer_t wbuffer;
wbuffer_init(&wbuffer, output, max_size);
2018-02-21 19:36:38 +08:00
2020-10-18 12:17:55 +08:00
b.gen.Output(&wbuffer);
2018-02-21 19:36:38 +08:00
2020-07-08 16:39:01 +08:00
wbuffer_deinit(&wbuffer);
2018-02-21 19:36:38 +08:00
xml_parser_destroy(parser);
2020-07-08 16:39:01 +08:00
return 0;
2018-02-21 19:36:38 +08:00
}
2020-03-23 12:16:07 +08:00
bool xml_gen(const char* input_file, const char* output_file, const char* theme,
bool_t output_bin) {
2018-02-21 19:36:38 +08:00
xml_builder_t b;
2020-07-08 16:39:01 +08:00
wbuffer_t wbuffer;
2018-02-21 19:36:38 +08:00
return_value_if_fail(input_file != NULL && output_file != NULL, false);
2020-07-08 16:39:01 +08:00
wbuffer_init_extendable(&wbuffer);
2018-02-21 19:36:38 +08:00
XmlParser* parser = xml_parser_create();
xml_parser_set_builder(parser, builder_init(b));
xml_parser_parse_file(parser, input_file);
2020-07-08 16:39:01 +08:00
if (b.gen.Output(&wbuffer) == RET_OK) {
if (output_bin) {
write_file(output_file, wbuffer.data, wbuffer.cursor);
} else {
output_res_c_source(output_file, theme, ASSET_TYPE_STYLE, 0, wbuffer.data, wbuffer.cursor);
}
}
2018-02-21 19:36:38 +08:00
2020-07-08 16:39:01 +08:00
wbuffer_deinit(&wbuffer);
2018-02-21 19:36:38 +08:00
xml_parser_destroy(parser);
return true;
}