// ---------------------------------------------------------------------------- void text_buffer_add_text( text_buffer_t * self, vec2 * pen, markup_t * markup, const char * text, size_t length ) { font_manager_t * manager = self->manager; size_t i; const char * prev_character = NULL; if( markup == NULL ) { return; } if( !markup->font ) { markup->font = font_manager_get_from_markup( manager, markup ); if( ! markup->font ) { fprintf( stderr, "Houston, we've got a problem !\n" ); exit( EXIT_FAILURE ); } } if( length == 0 ) { length = utf8_strlen(text); } if( vertex_buffer_size( self->buffer ) == 0 ) { self->origin = *pen; self->line_left = pen->x; self->bounds.left = pen->x; self->bounds.top = pen->y; } else { if (pen->x < self->origin.x) { self->origin.x = pen->x; } if (pen->y != self->last_pen_y) { text_buffer_finish_line(self, pen, false); } } for( i = 0; utf8_strlen( text + i ) && length; i += utf8_surrogate_len( text + i ) ) { text_buffer_add_char( self, pen, markup, text + i, prev_character ); prev_character = text + i; length--; } self->last_pen_y = pen->y; }
static struct info_tag * tag_found_keyword (struct text_buffer *tmpbuf_ptr, char **kw) { struct info_tag *tag = xmalloc (sizeof (*tag)); tag->next = NULL; /* have to update in caller */ text_buffer_add_char (tmpbuf_ptr, 0); if (*kw != tmpbuf_ptr->base) { /* in case tmpbuf got realloc-ed */ *kw = tmpbuf_ptr->base; /* ick */ } tag->kw = xstrdup (*kw); tag->val = xstrdup (*kw + strlen(*kw) + 1); text_buffer_reset (tmpbuf_ptr); return tag; }
static int tag_image (char *text, struct text_buffer *outbuf) { mbi_iterator_t iter; enum { state_kw, state_val, state_qstr, state_delim } state = state_kw; struct text_buffer tmpbuf; char *kw; struct info_tag *tag_head = NULL, *tag; int escaped = 0; text_buffer_init (&tmpbuf); for (mbi_init (iter, text, strlen (text)); mbi_avail (iter); mbi_advance (iter)) { const char *cur_ptr; size_t cur_len; if (mb_isspace (mbi_cur (iter))) { if (state == state_val) { struct info_tag *new_kw = tag_found_keyword (&tmpbuf, &kw); new_kw->next = tag_head; tag_head = new_kw; state = state_delim; continue; } if (state == state_delim) continue; } cur_len = mb_len (mbi_cur (iter)); cur_ptr = mbi_cur_ptr (iter); if (state == state_qstr && escaped) { escaped = 0; } else if (cur_len == 1) { switch (*cur_ptr) { case '=': text_buffer_add_char (&tmpbuf, 0); kw = tmpbuf.base; if (!mbi_avail (iter)) break; mbi_advance (iter); state = state_val; cur_len = mb_len (mbi_cur (iter)); cur_ptr = mbi_cur_ptr (iter); if (!(cur_len == 1 && *cur_ptr == '"')) break; /* fall through */ case '"': if (state == state_val) { state = state_qstr; continue; } if (state == state_qstr) { struct info_tag *new_kw = tag_found_keyword (&tmpbuf, &kw); new_kw->next = tag_head; tag_head = new_kw; state = state_delim; continue; } break; case '\\': if (state == state_qstr) { escaped = 1; continue; } } } text_buffer_add_string (&tmpbuf, cur_ptr, cur_len); } tag = info_tag_find (tag_head, "text"); if (!tag) tag = info_tag_find (tag_head, "alt"); if (tag) { text_buffer_add_string (outbuf, tag->val, strlen (tag->val)); } text_buffer_free (&tmpbuf); info_tag_free (tag_head); return 0; }