summaryrefslogtreecommitdiff
path: root/components/rtgui/common
diff options
context:
space:
mode:
authorbernard.xiong <[email protected]>2010-05-08 15:50:45 +0000
committerbernard.xiong <[email protected]>2010-05-08 15:50:45 +0000
commite7fb7e6c1480c8e38f8fa0affbd874edc307527c (patch)
tree21b2e4284de0516895fb4ad7f44f20f33814925b /components/rtgui/common
parentcfe7e91b95a7b59270e27c969018374513fde6be (diff)
update according 0.3.1 series and add XML parser.
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@699 bbd45198-f89e-11dd-88c7-29a3b14d5316
Diffstat (limited to 'components/rtgui/common')
-rw-r--r--components/rtgui/common/dc_buffer.c17
-rw-r--r--components/rtgui/common/rtgui_xml.c296
2 files changed, 303 insertions, 10 deletions
diff --git a/components/rtgui/common/dc_buffer.c b/components/rtgui/common/dc_buffer.c
index 15282c38bd..b924084aec 100644
--- a/components/rtgui/common/dc_buffer.c
+++ b/components/rtgui/common/dc_buffer.c
@@ -29,7 +29,6 @@ struct rtgui_dc_buffer
rt_uint16_t pitch;
/* blit info */
- rt_uint32_t clip_sync;
rtgui_region_t clip;
/* pixel data */
@@ -87,7 +86,6 @@ struct rtgui_dc* rtgui_dc_buffer_create(int w, int h)
dc->height = h;
dc->pitch = w * sizeof(rtgui_color_t);
- dc->clip_sync = 0;
rtgui_region_init(&(dc->clip));
dc->pixel = rtgui_malloc(h * dc->pitch);
@@ -260,7 +258,7 @@ static void rtgui_dc_buffer_blit(struct rtgui_dc* self, struct rtgui_point* dc_p
if (dest->type == RTGUI_DC_HW)
{
- rtgui_color_t* pixel;
+ rtgui_color_t* pixel;
rt_uint8_t *line_ptr;
rt_uint16_t rect_width, rect_height, index;
void (*blit_line)(rtgui_color_t* color, rt_uint8_t* dest, int line);
@@ -282,7 +280,6 @@ static void rtgui_dc_buffer_blit(struct rtgui_dc* self, struct rtgui_point* dc_p
case 1:
blit_line = rtgui_blit_line_1;
break;
-
case 2:
blit_line = rtgui_blit_line_2;
break;
@@ -300,17 +297,17 @@ static void rtgui_dc_buffer_blit(struct rtgui_dc* self, struct rtgui_point* dc_p
line_ptr = (rt_uint8_t*) rtgui_malloc(rect_width * hw->device->byte_per_pixel);
/* prepare pixel line */
- pixel = (rtgui_color_t*)(dc->pixel + dc_point->y * dc->pitch + dc_point->x * sizeof(rtgui_color_t));
+ pixel = (rtgui_color_t*)(dc->pixel + dc_point->y * dc->pitch + dc_point->x * sizeof(rtgui_color_t));
/* draw each line */
for (index = rect->y1; index < rect->y1 + rect_height; index ++)
{
/* blit on line buffer */
- blit_line(pixel, line_ptr, rect_width);
- pixel += dc->width;
-
- /* draw on hardware dc */
- rtgui_dc_hw_draw_raw_hline(hw, line_ptr, rect->x1, rect->x1 + rect_width, index);
+ blit_line(pixel, line_ptr, rect_width);
+ pixel += dc->width;
+
+ /* draw on hardware dc */
+ rtgui_dc_hw_draw_raw_hline(hw, line_ptr, rect->x1, rect->x1 + rect_width, index);
}
/* release line buffer */
diff --git a/components/rtgui/common/rtgui_xml.c b/components/rtgui/common/rtgui_xml.c
new file mode 100644
index 0000000000..66315eb8cf
--- /dev/null
+++ b/components/rtgui/common/rtgui_xml.c
@@ -0,0 +1,296 @@
+#include <rtgui/rtgui_xml.h>
+
+/* Internal states that the parser can be in at any given time. */
+enum {
+ STAT_START = 0, /* starting base state, default state */
+ STAT_TEXT, /* text state */
+ STAT_START_TAG, /* start tag state */
+ STAT_START_TAGNAME, /* start tagname state */
+ STAT_START_TAGNAME_END, /* start tagname ending state */
+ STAT_END_TAG, /* end tag state */
+ STAT_END_TAGNAME, /* end tag tagname state */
+ STAT_END_TAGNAME_END, /* end tag tagname ending */
+ STAT_EMPTY_TAG, /* empty tag state */
+ STAT_SPACE, /* linear whitespace state */
+ STAT_ATTR_NAME, /* attribute name state */
+ STAT_ATTR_NAME_END, /* attribute name ending state */
+ STAT_ATTR_VAL, /* attribute value starting state */
+ STAT_ATTR_VAL2, /* attribute value state */
+ STAT_ERROR /* error state */
+};
+
+/* character classes that we will match against; This could be expanded if
+ need be, however, we are aiming for simple. */
+enum {
+ CLASS_TYPE_NONE = 0, /* matches nothing, a base state */
+ CLASS_TYPE_LEFT_ANGLE, /* matches start tag '<' */
+ CLASS_TYPE_SLASH, /* matches forward slash */
+ CLASS_TYPE_RIGHT_ANGLE, /* matches end tag '>' */
+ CLASS_TYPE_EQUALS, /* matches equals sign */
+ CLASS_TYPE_QUOTE, /* matches double-quotes */
+ CLASS_TYPE_LETTERS, /* matches a-zA-Z letters and digits 0-9 */
+ CLASS_TYPE_SPACE, /* matches whitespace */
+ CLASS_TYPE_ANY /* matches any ASCII character; will match all
+ above classes */
+};
+
+/* xml state transition table */
+struct rtgui_xml_state
+{
+ rt_uint8_t state;
+ rt_uint8_t class_type;
+ rt_uint8_t next_state;
+ rt_uint8_t event;
+};
+
+/* Note: States must be grouped in match order AND grouped together! */
+static const struct rtgui_xml_state RTGUI_XML_STATES [] = {
+ /* [0-2] starting state, which also serves as the default state in case
+ of error */
+ { STAT_START, CLASS_TYPE_SPACE, STAT_SPACE, EVENT_NONE },
+ { STAT_START, CLASS_TYPE_LEFT_ANGLE, STAT_START_TAG, EVENT_NONE },
+ { STAT_START, CLASS_TYPE_ANY, STAT_TEXT, EVENT_COPY },
+
+ /* [3-5] space state handles linear white space */
+ { STAT_SPACE, CLASS_TYPE_SPACE, STAT_SPACE, EVENT_NONE },
+ { STAT_SPACE, CLASS_TYPE_LEFT_ANGLE, STAT_START_TAG, EVENT_TEXT },
+ { STAT_SPACE, CLASS_TYPE_ANY, STAT_TEXT, EVENT_COPY },
+
+ /* [6-8] handle start tag */
+ { STAT_START_TAG, CLASS_TYPE_LETTERS, STAT_START_TAGNAME, EVENT_COPY },
+ { STAT_START_TAG, CLASS_TYPE_SLASH, STAT_END_TAG, EVENT_COPY },
+ /* below added since some individuals get a little carried away with
+ spacing around tag names, e.g. < tag > */
+ { STAT_START_TAG, CLASS_TYPE_SPACE, STAT_START_TAG, EVENT_NONE },
+
+ /* [9-12] handle start tag name */
+ { STAT_START_TAGNAME, CLASS_TYPE_LETTERS, STAT_START_TAGNAME, EVENT_NONE },
+ { STAT_START_TAGNAME, CLASS_TYPE_SPACE, STAT_START_TAGNAME_END, EVENT_START },
+ /* below added for tags without any space between tag and ending
+ slash, e.g., <br/> */
+ { STAT_START_TAGNAME, CLASS_TYPE_SLASH, STAT_EMPTY_TAG, EVENT_END },
+ { STAT_START_TAGNAME, CLASS_TYPE_RIGHT_ANGLE, STAT_START, EVENT_START },
+
+ /* [13-16] handle start tag name end */
+ { STAT_START_TAGNAME_END, CLASS_TYPE_LETTERS, STAT_ATTR_NAME, EVENT_COPY },
+ /* below added to handle additional space in between attribute value
+ pairs in start tags, e.g., <tag attr="2" attr2="test" > */
+ { STAT_START_TAGNAME_END, CLASS_TYPE_SPACE, STAT_START_TAGNAME_END, EVENT_NONE },
+ { STAT_START_TAGNAME_END, CLASS_TYPE_RIGHT_ANGLE, STAT_START, EVENT_START },
+ /* below supports tags that are self-closing, e.g., <br /> */
+ { STAT_START_TAGNAME_END, CLASS_TYPE_SLASH, STAT_EMPTY_TAG, EVENT_COPY },
+
+ /* [17] handle empty tags, e.g., <br /> */
+ { STAT_EMPTY_TAG, CLASS_TYPE_RIGHT_ANGLE, STAT_START, EVENT_END },
+
+ /* [18] handle end tag, e.g., <tag /> */
+ { STAT_END_TAG, CLASS_TYPE_LETTERS, STAT_END_TAGNAME, EVENT_NONE },
+
+ /* [19-21] handle end tag name */
+ { STAT_END_TAGNAME, CLASS_TYPE_LETTERS, STAT_END_TAGNAME, EVENT_NONE },
+ { STAT_END_TAGNAME, CLASS_TYPE_RIGHT_ANGLE, STAT_START, EVENT_END },
+ /* below adds support for spaces at the end of an end tag (before
+ closing bracket) */
+ { STAT_END_TAGNAME, CLASS_TYPE_SPACE, STAT_END_TAGNAME_END, EVENT_END },
+
+ /* [22] handle ending of end tag name */
+ { STAT_END_TAGNAME_END, CLASS_TYPE_SPACE, STAT_END_TAGNAME_END, EVENT_NONE },
+ { STAT_END_TAGNAME_END, CLASS_TYPE_RIGHT_ANGLE,STAT_START, EVENT_NONE },
+
+ /* [23-25] handle text */
+ { STAT_TEXT, CLASS_TYPE_SPACE, STAT_SPACE, EVENT_NONE },
+ { STAT_TEXT, CLASS_TYPE_LEFT_ANGLE, STAT_START_TAG, EVENT_TEXT },
+ { STAT_TEXT, CLASS_TYPE_ANY, STAT_TEXT, EVENT_NONE },
+
+ /* [26-30] handle attribute names */
+ { STAT_ATTR_NAME, CLASS_TYPE_LETTERS, STAT_ATTR_NAME, EVENT_COPY },
+ /* below add support for space before the equals sign, e.g, <tag
+ attr ="2"> */
+ { STAT_ATTR_NAME, CLASS_TYPE_SPACE, STAT_ATTR_NAME_END, EVENT_NAME },
+ { STAT_ATTR_NAME, CLASS_TYPE_EQUALS, STAT_ATTR_VAL, EVENT_NAME },
+
+ /* [31-33] attribute name end */
+ { STAT_ATTR_NAME_END, CLASS_TYPE_SPACE, STAT_ATTR_NAME_END, EVENT_NONE },
+ { STAT_ATTR_NAME_END, CLASS_TYPE_LETTERS, STAT_ATTR_NAME, EVENT_COPY },
+ { STAT_ATTR_NAME_END, CLASS_TYPE_EQUALS, STAT_ATTR_VAL, EVENT_NONE },
+
+ /* [34-35] handle attribute values, initial quote and spaces */
+ { STAT_ATTR_VAL, CLASS_TYPE_QUOTE, STAT_ATTR_VAL2, EVENT_NONE },
+ /* below handles initial spaces before quoted attribute value */
+ { STAT_ATTR_VAL, CLASS_TYPE_SPACE, STAT_ATTR_VAL, EVENT_NONE },
+
+ /* [36-37] handle actual attribute values */
+ { STAT_ATTR_VAL2, CLASS_TYPE_QUOTE, STAT_START_TAGNAME_END, EVENT_VAL },
+ { STAT_ATTR_VAL2, CLASS_TYPE_LETTERS, STAT_ATTR_VAL2, EVENT_COPY },
+ { STAT_ATTR_VAL2, CLASS_TYPE_SLASH, STAT_ATTR_VAL2, EVENT_NONE },
+
+ /* End of table marker */
+ { STAT_ERROR, CLASS_TYPE_NONE, STAT_ERROR, EVENT_NONE }
+};
+
+struct rtgui_xml
+{
+ /* event handler */
+ rtgui_xml_event_handler_t event_handler;
+ void* user;
+
+ char* buffer; /* xml buffer */
+ rt_size_t buffer_size; /* buffer size */
+ rt_size_t position; /* current position in buffer */
+ rt_uint16_t state, event; /* current state and event */
+
+ rt_bool_t copy; /* copy text into tmp buffer */
+ rt_bool_t halt; /* halt parsing of document */
+};
+
+rtgui_xml_t* rtgui_xml_create(rt_size_t buffer_size, rtgui_xml_event_handler_t handler,
+ void* user)
+{
+ rtgui_xml_t* xml = (rtgui_xml_t*) rtgui_malloc(sizeof(struct rtgui_xml));
+ rt_memset(xml, 0, sizeof(rtgui_xml_t));
+
+ xml->event_handler = handler;
+ xml->user = user;
+
+ /* create buffer */
+ xml->buffer_size = buffer_size;
+ xml->buffer = (char*)rtgui_malloc(xml->buffer_size);
+ return xml;
+}
+
+void rtgui_xml_destroy(rtgui_xml_t* xml)
+{
+ if(xml)
+ {
+ rtgui_free(xml->buffer);
+ rtgui_free(xml);
+ }
+}
+
+const char* rtgui_xml_event_str(rt_uint8_t event)
+{
+ switch(event)
+ {
+ case EVENT_START:
+ return "start tag";
+ break;
+ case EVENT_END:
+ return "end tag";
+ break;
+ case EVENT_TEXT:
+ return "text";
+ break;
+ case EVENT_NAME:
+ return "attr name";
+ break;
+ case EVENT_VAL:
+ return "attr val";
+ break;
+ case EVENT_END_DOC:
+ return "end document";
+ break;
+ default:
+ break;
+ }
+ return "err";
+}
+
+int rtgui_xml_parse(rtgui_xml_t* xml, const char* buf, rt_size_t len)
+{
+ int i, j, c, match;
+
+#define is_space(ch) \
+ ((rt_uint32_t)(ch - 9) < 5u || ch == ' ')
+#define is_alpha(ch) \
+ ((rt_uint32_t)((ch | 0x20) - 'a') < 26u)
+#define is_digit(ch) \
+ ((rt_uint32_t)(ch - '0') < 10u)
+#define is_letters(ch) \
+ (is_alpha(ch) || is_digit(ch) || (ch == '.'))
+
+ for(i=0; i<len; i++)
+ {
+ if(xml->halt) break;
+
+ c = buf[i] & 0xff;
+
+ /* search in state table */
+ for(j=0, match = 0; RTGUI_XML_STATES[j].state != STAT_ERROR; j++)
+ {
+ if(RTGUI_XML_STATES[j].state != xml->state)
+ continue;
+
+ switch(RTGUI_XML_STATES[j].class_type)
+ {
+ case CLASS_TYPE_LETTERS:
+ match = is_letters(c);
+ break;
+ case CLASS_TYPE_LEFT_ANGLE:
+ match = (c == '<');
+ break;
+ case CLASS_TYPE_SLASH:
+ match = (c == '/');
+ break;
+ case CLASS_TYPE_RIGHT_ANGLE:
+ match = (c == '>');
+ break;
+ case CLASS_TYPE_EQUALS:
+ match = (c == '=');
+ break;
+ case CLASS_TYPE_QUOTE:
+ match = (c == '"');
+ break;
+ case CLASS_TYPE_SPACE:
+ match = is_space(c);
+ break;
+ case CLASS_TYPE_ANY:
+ match = 1;
+ break;
+ default:
+ break;
+ }
+
+ /* we matched a character class */
+ if(match)
+ {
+ if(RTGUI_XML_STATES[j].event == EVENT_COPY)
+ {
+ xml->copy = RT_TRUE;
+ }
+ else if(RTGUI_XML_STATES[j].event != EVENT_NONE)
+ {
+ if(xml->copy == RT_TRUE)
+ {
+ /* basically we are guaranteed never to have an event of
+ type EVENT_COPY or EVENT_NONE here. */
+ xml->event = RTGUI_XML_STATES[j].event;
+ xml->buffer[xml->position] = 0; /* make a string */
+
+ if(!xml->event_handler(RTGUI_XML_STATES[j].event,
+ xml->buffer, xml->position ,
+ xml->user))
+ {
+ xml->halt = 1; /* stop parsing from here out */
+ }
+ xml->position = 0;
+ xml->copy = RT_FALSE;
+ }
+ }
+ if(xml->copy == RT_TRUE)
+ {
+ /* check to see if we have room; one less for trailing
+ nul */
+ if(xml->position < xml->buffer_size-1)
+ {
+ xml->buffer[xml->position] = buf[i];
+ xml->position++;
+ }
+ }
+ xml->state = RTGUI_XML_STATES[j].next_state; /* change state */
+ break; /* break out of loop though state search */
+ }
+ }
+ }
+
+ return !xml->halt;
+}