Пример #1
0
static bool nsfont_position_in_string(const plot_font_style_t *fstyle,
		const char *string, size_t length,
		int x, size_t *char_offset, int *actual_x)
{
        uint32_t ucs4;
        size_t nxtchr = 0;
        FT_Glyph glyph;
        int prev_x = 0;

        *actual_x = 0;
        while (nxtchr < length) {
                ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);

                glyph = fb_getglyph(fstyle, ucs4);
                if (glyph == NULL)
                        continue;

                *actual_x += glyph->advance.x >> 16;
                if (*actual_x > x)
                        break;

                prev_x = *actual_x;
                nxtchr = utf8_next(string, length, nxtchr);
        }

        /* choose nearest of previous and last x */
        if (abs(*actual_x - x) > abs(prev_x - x))
                *actual_x = prev_x;

        *char_offset = nxtchr;
	return true;
}
Пример #2
0
static utf8_convert_ret utf8_convert_html_chunk(iconv_t cd,
		const char *chunk, size_t inlen,
		char **out, size_t *outlen)
{
	size_t ret, esclen;
	uint32_t ucs4;
	char *pescape, escape[11];

	while (inlen > 0) {
		ret = iconv(cd, (void *) &chunk, &inlen, (void *) out, outlen);
		if (ret != (size_t) -1)
			break;

		if (errno != EILSEQ)
			return UTF8_CONVERT_NOMEM;

		ucs4 = utf8_to_ucs4(chunk, inlen);
		esclen = snprintf(escape, sizeof(escape), "&#x%06x;", ucs4);
		pescape = escape;
		ret = iconv(cd, (void *) &pescape, &esclen,
				(void *) out, outlen);
		if (ret == (size_t) -1)
			return UTF8_CONVERT_NOMEM;

		esclen = utf8_next(chunk, inlen, 0);
		chunk += esclen;
		inlen -= esclen;
	}

	return UTF8_CONVERT_OK;
}
Пример #3
0
static bool match_star(unsigned c, int flags, struct utf8_iter expr, struct utf8_iter text, char **end) {
	for (; !match_here(expr, text, end); utf8_next(&text))
		if (text.chr == 0 || !match_char(c, flags, &text))
			return false;

	return true;
}
Пример #4
0
/* Finds the position of the first candidate line break in the 今日は
 utf8-encoded text str. Returns -1 if no candidate could be found.
 Returns -2 if the string is empty.
 */
int
laytext_find_first_break(char * str, float max_width, laytext_callback * callback, void * extra) {
    int length = 0;
    int total_length = 0;
    long character;
    float width, delta_width;
    float height;
    int candidate = -1;
    char * index = str;
    width = 0.0;

    while (index) {
        callback(index, total_length, extra, &delta_width, &height);
        width = delta_width;
        if((width - max_width) > 0.5) {
            if (candidate == -1) { /* No break candidate, break before this character in stead. */
                return index - str - 1;
            } else { /* break at candidate. */
                return candidate;
            }
        }
        if ((*index) == ' ') {
            candidate = index - str;
        }
        /* If a newline the break is here. */
        if((*index) == '\n') {
            return index - str;
        }
        length = utf8_next(index, &index, &character);
        total_length += length;
    }
    /* If we get here the strin is short, no break needed. Negative indicates
     * this. */
    return -1;
}
Пример #5
0
Файл: unicode.c Проект: sgh/aos
void unicode_init(struct unicode_parser* parser, const char* str) {
	memset(&parser->prev, 0, sizeof(parser->prev));
	utf8_init(&parser->current, str);
	parser->next = parser->current;
	utf8_next(&parser->next);
	parser->unicode = parser->current.unicode;
// 	unicode_decode(&parser);
}
Пример #6
0
/**
 * Calculate the length (in bytes) of a bounded UTF-8 string
 *
 * \param s  The string
 * \param l  Maximum length of input (in bytes)
 * \param c  Maximum number of characters to measure
 * \return Length of string, in bytes
 */
size_t utf8_bounded_byte_length(const char *s, size_t l, size_t c)
{
	size_t len = 0;

	while (len < l && c-- > 0)
		len = utf8_next(s, l, len);

	return len;
}
Пример #7
0
static bool match_plus(unsigned c, int flags, struct utf8_iter expr, struct utf8_iter text, char **end) {
	if (!match_char(c, flags, &text))
		return false;

	do utf8_next(&text);
	while (text.chr != 0 && match_char(c, flags, &text));

	return match_here(expr, text, end);
}
Пример #8
0
char *match(char *expr_, char *text_, char **end) {
	struct utf8_iter expr;
	struct utf8_iter text;

	utf8_iter(&expr, expr_);
	utf8_iter(&text, text_);

	utf8_next(&text);

	if (utf8_next(&expr) == '^') {
		utf8_next(&expr);
		return match_here(expr, text, end) ? text.head : NULL;
	}

	do if (match_here(expr, text, end))
		return text.head;
	while (text.chr != 0 && utf8_next(&text));

	return NULL;
}
Пример #9
0
Файл: unicode.c Проект: sgh/aos
char unicode_next(struct unicode_parser* parser) {
	if (utf8_current(&parser->current)) {

		// Try to move to next symbol
		parser->prev = parser->current;
		parser->current = parser->next;
		utf8_next(&parser->next);
		unicode_decode(parser);
		return 1;
	}
	return 0;
}
Пример #10
0
size_t append_utf8_char(String * string, const char * mbs)
{
	/* Copy exactly one multi-byte character to buf */
	char buf[10];
	size_t n = utf8_next(mbs);

	assert(n<10, "Multi-byte character is too long!");
	strncpy(buf, mbs, n);
	buf[n] = 0;
	append_string(string, "%s", buf);
	return n;
}
Пример #11
0
static void glyphstring_create(FT_Face face, Text *text, FT_Glyph *glyph_string,
		FT_Vector *pos)
{
	const uint8_t *string = text->string;
	FT_Bool has_kerning;
	FT_UInt glyph_index, previous;
	FT_Vector pen, delta;
	uint32_t charcode;
	int i;

	has_kerning = FT_HAS_KERNING(face);
	previous = 0;
	i = 0;
	pen.x = pen.y = 0;
	while (string[0] != '\0')
	{
		charcode = utf8_next(&string);
		glyph_index = FT_Get_Char_Index(face, charcode);
		if (has_kerning && previous && glyph_index)
			FT_Get_Kerning(face, previous, glyph_index, FT_KERNING_DEFAULT,
					&delta);
		else
			delta.x = 0;

		if (glyph_index == 0)
			log_err("Glyph for character U+%X missing\n", charcode);

		if (FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER) != 0)
		{
			log_err("Error loading glyph for character U+%X\n", charcode);
			continue;
		}
		if (FT_Get_Glyph(face->glyph, &glyph_string[i]) != 0)
		{
			log_err("Error copying glyph for character U+%X\n", charcode);
			continue;
		}

		pen.x += delta.x;

		pos[i] = pen;

		pen.x += face->glyph->advance.x;
		pen.y += face->glyph->advance.y;

		previous = glyph_index;
		i++;
	}

	text->num_glyphs = i;
}
Пример #12
0
static void
nsgtk_tree_window_input_method_commit(GtkIMContext *ctx,
		const gchar *str, gpointer data)
{
	struct nsgtk_treeview *tw = (struct nsgtk_treeview *) data;
	size_t len = strlen(str), offset = 0;

	while (offset < len) {
		uint32_t nskey = utf8_to_ucs4(str + offset, len - offset);

		tree_keypress(tw->tree, nskey);

		offset = utf8_next(str, len, offset);
	}
}
Пример #13
0
static bool match_here(struct utf8_iter expr, struct utf8_iter text, char **end) {
	unsigned pre = expr.chr;
	int flags = 0;

	if (pre == 0) {
		if (end != NULL)
			*end = text.head;

		return true;
	}

	if (pre == '~') {
		pre = utf8_next(&expr);
		flags |= NEGATE;
	}

	if (pre == '%') {
		pre = utf8_next(&expr);

		switch (pre) {
		case 'a': /* alpha */
		case 'd': /* digit */
		case 'f': /* float */
		case 'g': /* graphic */
		case 'n': /* newline */
		case 's': /* space */
		case 'x': /* hex */
		case '?': /* anything */
			flags |= CLASS;
		}
	}

	utf8_next(&expr);

	if (expr.chr == '*') {
		utf8_next(&expr);
		return match_star(pre, flags, expr, text, end);
	} else if (expr.chr == '+') {
		utf8_next(&expr);
		return match_plus(pre, flags, expr, text, end);
	}

	if (pre == '$' && expr.chr == 0) {
		if (end != NULL)
			*end = text.head;

		return text.chr == 0;
	}

	if (text.chr != 0 && match_char(pre, flags, &text)) {
		utf8_next(&text);
		return match_here(expr, text, end);
	}

	return false;
}
Пример #14
0
static bool 
framebuffer_plot_text(int x, int y, const char *text, size_t length,
		const plot_font_style_t *fstyle)
{
        uint32_t ucs4;
        size_t nxtchr = 0;
        FT_Glyph glyph;
        FT_BitmapGlyph bglyph;
        nsfb_bbox_t loc;

        while (nxtchr < length) {
                ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
                nxtchr = utf8_next(text, length, nxtchr);

                glyph = fb_getglyph(fstyle, ucs4);
                if (glyph == NULL)
                        continue;

                if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
                        bglyph = (FT_BitmapGlyph)glyph;

                        loc.x0 = x + bglyph->left;
                        loc.y0 = y - bglyph->top;
                        loc.x1 = loc.x0 + bglyph->bitmap.width;
                        loc.y1 = loc.y0 + bglyph->bitmap.rows;

                        /* now, draw to our target surface */
                        if (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
                            nsfb_plot_glyph1(nsfb, 
                                             &loc, 
                                             bglyph->bitmap.buffer, 
                                             bglyph->bitmap.pitch, 
                                             fstyle->foreground);
                        } else {
                            nsfb_plot_glyph8(nsfb, 
                                             &loc, 
                                             bglyph->bitmap.buffer, 
                                             bglyph->bitmap.pitch, 
                                             fstyle->foreground);
                        }
                }
                x += glyph->advance.x >> 16;

        }
        return true;

}
Пример #15
0
/**
 * @ingroup hanjadictionary
 * @brief 한자 사전에서 뒷부분이 매치되는 키를 가진 엔트리를 찾는 함수
 * @param table 한자 사전 object
 * @param key 찾을 키, UTF-8 인코딩
 * @return 찾은 결과를 HanjaList object로 리턴한다. 찾은 것이 없거나 에러가 
 *         있으면 NULL을 리턴한다.
 *
 * @a key 값과 같거나 뒷부분이 같은 키를 가진 엔트리를 검색한다.
 * 그리고 key를 앞에서부터 한자씩 줄여가면서 검색을 계속한다.
 * 예로 들면 "삼국사기"를 검색하면 "삼국사기", "국사기", "사기", "기"를 
 * 각각 모두 검색한다.
 * 리턴된 결과는 다 사용하고 나면 반드시 hanja_list_delete() 함수로 free해야
 * 한다.
 */
HanjaList*
hanja_table_match_suffix(const HanjaTable* table, const char *key)
{
    const char* p;
    HanjaList* ret = NULL;

    if (key == NULL || key[0] == '\0' || table == NULL)
	return NULL;

    p = key;
    while (p[0] != '\0') {
	hanja_table_match(table, p, &ret);
	p = utf8_next(p);
    }

    return ret;
}
Пример #16
0
/**
 * Insert text into the text area
 *
 * \param self Text area
 * \param index 0-based character index to insert at
 * \param text UTF-8 text to insert
 */
void ro_textarea_insert_text(uintptr_t self, unsigned int index,
		const char *text)
{
	struct text_area *ta;
	unsigned int b_len = strlen(text);
	size_t b_off, c_len;

	ta = (struct text_area *)self;
	if (!ta || ta->magic != MAGIC) {
		LOG(("magic doesn't match"));
		return;
	}

	c_len = utf8_length(ta->text);

	/* Find insertion point */
	if (index > c_len)
		index = c_len;

	for (b_off = 0; index-- > 0;
			b_off = utf8_next(ta->text, ta->text_len, b_off))
		; /* do nothing */

	if (b_len + ta->text_len >= ta->text_alloc) {
		char *temp = realloc(ta->text, b_len + ta->text_len + 64);
		if (!temp) {
			LOG(("realloc failed"));
			return;
		}

		ta->text = temp;
		ta->text_alloc = b_len + ta->text_len + 64;
	}

	/* Shift text following up */
	memmove(ta->text + b_off + b_len, ta->text + b_off,
			ta->text_len - b_off);
	/* Insert new text */
	memcpy(ta->text + b_off, text, b_len);

	ta->text_len += b_len;

	/** \todo calculate line to reflow from */
	ro_textarea_reflow(ta, 0);
}
Пример #17
0
/**
 * Get the caret's position
 *
 * \param self Text area
 * \return 0-based character index of caret location, or -1 on error
 */
unsigned int ro_textarea_get_caret(uintptr_t self)
{
	struct text_area *ta;
	size_t c_off = 0, b_off;

	ta = (struct text_area *)self;
	if (!ta || ta->magic != MAGIC) {
		LOG(("magic doesn't match"));
		return -1;
	}

	/* Calculate character offset of this line's start */
	for (b_off = 0; b_off < ta->lines[ta->caret_pos.line].b_start;
			b_off = utf8_next(ta->text, ta->text_len, b_off))
		c_off++;

	return c_off + ta->caret_pos.char_off;
}
Пример #18
0
// UTF-8 -> ISO-8859-1
// コード範囲外の値は、下8ビッドだけ取る
static const char *utf8_to_8bit(const char *src)
{
    if (src != NULL) {
        int len = strlen(src);
        const char *p = src;
        const char *end = p + len;

        char *c_buf = Mem_get(&fg->st_mem, len + 1);
        int i = 0;

        while (p < end) {
            int ch = utf8_codepoint_at(p);
            c_buf[i++] = ch & 0xFF;
            utf8_next(&p, end);
        }
        c_buf[i] = '\0';
        return c_buf;
    } else {
        return NULL;
    }
}
Пример #19
0
static bool nsfont_split(const plot_font_style_t *fstyle,
		const char *string, size_t length,
		int x, size_t *char_offset, int *actual_x)
{
        uint32_t ucs4;
        size_t nxtchr = 0;
        int last_space_x = 0;
        int last_space_idx = 0;
        FT_Glyph glyph;

        *actual_x = 0;
        while (nxtchr < length) {
                ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);

                glyph = fb_getglyph(fstyle, ucs4);
                if (glyph == NULL)
                        continue;

                if (ucs4 == 0x20) {
                        last_space_x = *actual_x;
                        last_space_idx = nxtchr;
                }

                *actual_x += glyph->advance.x >> 16;
                if (*actual_x > x) {
                        /* string has exceeded available width return previous
                         * space 
                         */
                        *actual_x = last_space_x;
                        *char_offset = last_space_idx;
                        return true;
                }

                nxtchr = utf8_next(string, length, nxtchr);
        }

        *char_offset = nxtchr;

	return true;
}
Пример #20
0
/**
 * Measure the width of a string.
 *
 * \param  fstyle  style for this text
 * \param  string  UTF-8 string to measure
 * \param  length  length of string
 * \param  width   updated to width of string[0..length)
 * \return  true on success, false on error and error reported
 */
static bool nsfont_width(const plot_font_style_t *fstyle,
                         const char *string, size_t length,
                         int *width)
{
        uint32_t ucs4;
        size_t nxtchr = 0;
        FT_Glyph glyph;

        *width = 0;
        while (nxtchr < length) {
                ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr);
                nxtchr = utf8_next(string, length, nxtchr);

                glyph = fb_getglyph(fstyle, ucs4);
                if (glyph == NULL)
                        continue;

                *width += glyph->advance.x >> 16;
        }

	return true;
}
Пример #21
0
//#else
static bool framebuffer_plot_text_internal(int x, int y, const char *text, size_t length,
        const plot_font_style_t *fstyle)
{
    enum fb_font_style style = fb_get_font_style(fstyle);
    int size = fb_get_font_size(fstyle);
    const uint8_t *chrp;
    size_t nxtchr = 0;
    nsfb_bbox_t loc;
    uint32_t ucs4;
    int p = FB_FONT_PITCH * size;
    int w = FB_FONT_WIDTH * size;
    int h = FB_FONT_HEIGHT * size;

    y -= ((h * 3) / 4);
    /* the coord is the bottom-left of the pixels offset by 1 to make
     * it work since fb coords are the top-left of pixels */
    y += 1;

    while (nxtchr < length) {
        ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
        nxtchr = utf8_next(text, length, nxtchr);

        if (!codepoint_displayable(ucs4))
            continue;

        loc.x0 = x;
        loc.y0 = y;
        loc.x1 = loc.x0 + w;
        loc.y1 = loc.y0 + h;

        chrp = fb_get_glyph_internal(ucs4, style, size);
        nsfb_plot_glyph1(nsfb, &loc, chrp, p, fstyle->foreground);

        x += w;

    }

    return true;
}
Пример #22
0
/**
 * Convert a UTF-8 encoded string into the system local encoding
 *
 * \param string The string to convert
 * \param len The length (in bytes) of the string, or 0
 * \param result Pointer to location in which to store result
 * \return An nserror code
 */
nserror utf8_to_local_encoding(const char *string, size_t len, char **result)
{
	os_error *error;
	int alphabet, i;
	size_t off, prev_off;
	char *temp, *cur_pos;
	const char *enc;
	nserror err;

	assert(string);
	assert(result);

	/* get length, if necessary */
	if (len == 0)
		len = strlen(string);

	/* read system alphabet */
	error = xosbyte1(osbyte_ALPHABET_NUMBER, 127, 0, &alphabet);
	if (error)
		alphabet = territory_ALPHABET_LATIN1;

	/* UTF-8 -> simply copy string */
	if (alphabet == 111 /* UTF-8 */) {
		*result = strndup(string, len);
		return NSERROR_OK;
	}

	/* get encoding name */
	enc = (alphabet <= CONT_ENC_END ? localencodings[alphabet - 100]
			      : (alphabet == 120 ?
					localencodings[CONT_ENC_END - 100 + 1]
						 : localencodings[0]));

	/* create output buffer */
	*(result) = malloc(len + 1);
	if (!(*result))
		return NSERROR_NOMEM;
	*(*result) = '\0';

	prev_off = 0;
	cur_pos = (*result);

	/* Iterate over string, converting input between unconvertable
	 * characters and inserting appropriate output for characters
	 * that iconv can't handle. */
	for (off = 0; off < len; off = utf8_next(string, len, off)) {
		if (string[off] != 0xE2 &&
				string[off] != 0xC5 && string[off] != 0xEF)
			continue;

		for (i = 0; i != NOF_ELEMENTS(special_chars); i++) {
			if (strncmp(string + off, special_chars[i].utf,
					special_chars[i].len) != 0)
				continue;

			/* 0 length has a special meaning to utf8_to_enc */
			if (off - prev_off > 0) {
				err = utf8_to_enc(string + prev_off, enc,
						off - prev_off, &temp);
				if (err != NSERROR_OK) {
					assert(err != NSERROR_BAD_ENCODING);
					free(*result);
					return NSERROR_NOMEM;
				}

				strcat(cur_pos, temp);

				cur_pos += strlen(temp);

				free(temp);
			}

			*cur_pos = special_chars[i].local;
			*(++cur_pos) = '\0';
			prev_off = off + special_chars[i].len;
		}
	}

	/* handle last chunk
	 * NB. 0 length has a special meaning to utf8_to_enc */

	if (prev_off < len) {
		err = utf8_to_enc(string + prev_off, enc, len - prev_off,
				&temp);
		if (err != NSERROR_OK) {
			assert(err != NSERROR_BAD_ENCODING);
			free(*result);
			return NSERROR_NOMEM;
		}

		strcat(cur_pos, temp);

		free(temp);
	}

	return NSERROR_OK;
}
Пример #23
0
size_t text_renderer_render(text_renderer_p renderer, int32_t font_handle, char* text, size_t x, size_t y, float* buffer_ptr, size_t buffer_size) {
	text_renderer_font_p font = hash_get_ptr(renderer->fonts, font_handle);
	if (!font)
		return 0;
	
	// The current position is the baseline of the text so start one line down
	// from the position. Otherwise we would render above it.
	size_t pos_x = x, pos_y = y + (font->face->size->metrics.height / 64);
	float* p = buffer_ptr;
	FT_UInt glyph_index = 0, prev_glyph_index = 0;
	
	glBindTexture(GL_TEXTURE_RECTANGLE, renderer->texture);
	
	// Lookup the size of our texture (needed by find_free_cell_or_revoke_unused_cell() for some checks)
	GLint texture_width = 0, texture_height = 0;
	glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE, 0, GL_TEXTURE_WIDTH, &texture_width);
	glGetTexLevelParameteriv(GL_TEXTURE_RECTANGLE, 0, GL_TEXTURE_HEIGHT, &texture_height);
	
	GLint unpack_alignment = 0;
	glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	
	for(utf8_iterator_t it = utf8_first(text); it.code_point != 0; it = utf8_next(it)) {
		// Handle line break.
		if (it.code_point == '\n') {
			pos_y += font->face->size->metrics.height / 64;
			pos_x = x;
			
			// Don't do kerning at the next character after the line break.
			prev_glyph_index = 0;
			
			continue;
		}
		
		// Look if this glyph is present in the texture. If so this font has a cell reference
		// for this code point.
		text_renderer_cell_ref_p cell_ref = hash_get_ptr(font->cell_refs, it.code_point);
		
		// Glyph not rendered yet, try to render it
		if (!cell_ref) {
			glyph_index = FT_Get_Char_Index(font->face, it.code_point);
			if (glyph_index == 0)
				goto render_error_glyph;
			
			FT_Error error = FT_Load_Glyph(font->face, glyph_index, FT_LOAD_RENDER);
			if (error)
				goto render_error_glyph;
			
			// Look for a free cell to store the rendered glyph
			uint32_t gw = font->face->glyph->bitmap.width, gh = font->face->glyph->bitmap.rows;
			size_t line_idx = 0, cell_idx = 0;
			text_renderer_cell_p free_cell = find_free_cell_or_revoke_unused_cell(renderer, font, gw, gh, texture_width, texture_height, &line_idx, &cell_idx);
			
			if (free_cell == NULL)
				goto render_error_glyph;
			
			free_cell->glyph_index    = glyph_index;
			free_cell->hori_bearing_x = font->face->glyph->metrics.horiBearingX / 64;
			free_cell->hori_bearing_y = font->face->glyph->metrics.horiBearingY / 64;
			free_cell->hori_advance   = font->face->glyph->metrics.horiAdvance  / 64;
			
			/*
			printf("%c: %2ux%2u %2u bytes, pitch %u, x: %u, y: %u hori_bearing: %2u/%2u, adv: %2u\n",
				it.code_point, gw, gh, gw*gh, font->face->glyph->bitmap.pitch,
				free_cell->x, free_cell->y, free_cell->hori_bearing_x, free_cell->hori_bearing_y, free_cell->hori_advance);
			*/

			glPixelStorei(GL_UNPACK_ROW_LENGTH, font->face->glyph->bitmap.pitch);
			glTexSubImage2D(GL_TEXTURE_RECTANGLE, 0, free_cell->x, free_cell->y, gw, gh, GL_RED, GL_UNSIGNED_BYTE, font->face->glyph->bitmap.buffer);
			
			cell_ref = hash_put_ptr(font->cell_refs, it.code_point);
			cell_ref->line_idx = line_idx;
			cell_ref->cell_idx = cell_idx;
		}
		
		// Glyph rendered successfully, do kerning and generate vertices for it
		text_renderer_line_t line = array_elem(renderer->lines, text_renderer_line_t, cell_ref->line_idx);
		text_renderer_cell_t cell = array_elem(line.cells, text_renderer_cell_t, cell_ref->cell_idx);
		
		if (cell.glyph_index && prev_glyph_index) {
			FT_Vector delta;
			FT_Get_Kerning(font->face, prev_glyph_index, glyph_index, FT_KERNING_DEFAULT, &delta);
			pos_x += delta.x / 64;
		}
		
		// We have the texture coordinates of the glyph, generate the vertex buffer
		if ( (p + 6*4 - buffer_ptr) * sizeof(float) < buffer_size ) {
			float w = cell.width, h = line.height;
			
			float cx = pos_x + cell.hori_bearing_x;
			float cy = pos_y - cell.hori_bearing_y;
			
			float tl_x = cx + 0, tl_y = cy + 0,  tl_u = cell.x,     tl_v = cell.y;
			float tr_x = cx + w, tr_y = cy + 0,  tr_u = cell.x + w, tr_v = cell.y;
			float bl_x = cx + 0, bl_y = cy + h,  bl_u = cell.x,     bl_v = cell.y + h;
			float br_x = cx + w, br_y = cy + h,  br_u = cell.x + w, br_v = cell.y + h;
			
			*(p++) = tl_x; *(p++) = tl_y; *(p++) = tl_u; *(p++) = tl_v;
			*(p++) = tr_x; *(p++) = tr_y; *(p++) = tr_u; *(p++) = tr_v;
			*(p++) = bl_x; *(p++) = bl_y; *(p++) = bl_u; *(p++) = bl_v;
			*(p++) = tr_x; *(p++) = tr_y; *(p++) = tr_u; *(p++) = tr_v;
			*(p++) = br_x; *(p++) = br_y; *(p++) = br_u; *(p++) = br_v;
			*(p++) = bl_x; *(p++) = bl_y; *(p++) = bl_u; *(p++) = bl_v;
			
			pos_x += cell.hori_advance;
		}
		
		prev_glyph_index = glyph_index;
		continue;
		
		render_error_glyph:
			// For now just output nothing when we fail to render a glyph.
			// TODO: Figure out how to render a kind of error glyph.
			prev_glyph_index = glyph_index;
			continue;
	}
	
	glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment);
	glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
	glBindTexture(GL_TEXTURE_RECTANGLE, 0);
	
	return (p - buffer_ptr) * sizeof(float);
}
Пример #24
0
Файл: unicode.c Проект: sgh/aos
void unicode_decode(struct unicode_parser* parser) {
	unsigned int prev    = utf8_current(&parser->prev);
	unsigned int current = utf8_current(&parser->current);
	unsigned int next    = utf8_current(&parser->next);
	unsigned char prev_connects = 0;   // Can the previous character connect to me
	unsigned char next_connects = 0;   // Can the previous character connect to me
	unsigned char i_connect_left = 1;  // Can I connect left
	unsigned char i_connect_right = 1; // Can I connect right
	int idx;
	int i;
	char found = 0;

	parser->unicode = current;
return;
	// TODO This only applies to arabic chars
	// previous and next chars only connect if they are not whitespace or start/end of line
	prev_connects = connects_prev_next(prev, -1);
	next_connects = connects_prev_next(next, 1);

	// Find Ligatures
	for (idx=0; idx<sizeof(ligatures) / sizeof(ligatures[0]); idx+=3) {
		if (ligatures[idx] == current && ligatures[idx+1] == next) {
			utf8_next(&parser->next);
			parser->unicode = ligatures[idx+2];
			return;
		}
	}

	for (idx=0; idx<sizeof(contextual_forms) / sizeof(contextual_forms[0]); idx+=2) {
		if (contextual_forms[idx] == current) {
			found = 1;
			break;
		}
	}

	if (found) {
		// Characters which do only connect left
		for (i=0; i<sizeof(contextual_forms_nomiddle_noend) / sizeof(contextual_forms_nomiddle_noend[0]); i++) {
				if (current == contextual_forms_nomiddle_noend[i]) {
					i_connect_right = 0;
				}
				if (prev == contextual_forms_nomiddle_noend[i]) {
					prev_connects = 0;
				}
		}

		// If only previous an I can connect
		if (prev_connects && i_connect_left && !(i_connect_right && next_connects))
			current = contextual_forms[idx+1] + 1;

		// If only next an I can connect
		if (!(prev_connects && i_connect_left) && i_connect_right && next_connects)
			current = contextual_forms[idx+1] + 2;

		// Both I and previous and next char can connect
		if (prev_connects && i_connect_left && i_connect_right && next_connects)
			current = contextual_forms[idx+1] + 3;
	}

	parser->unicode = current;
}
Пример #25
0
/**
 * Set the caret's position
 *
 * \param self Text area
 * \param x X position of caret on the screen
 * \param y Y position of caret on the screen
 */
void ro_textarea_set_caret_xy(uintptr_t self, int x, int y)
{
	struct text_area *ta;
	wimp_window_state state;
	size_t b_off, c_off, temp;
	int line;
	os_coord os_line_height;
	rufl_code code;
	os_error *error;

	ta = (struct text_area *)self;
	if (!ta || ta->magic != MAGIC) {
		LOG(("magic doesn't match"));
		return;
	}

	if (ta->flags & TEXTAREA_READONLY)
		return;

	os_line_height.x = 0;
	os_line_height.y = (int)((float)(ta->line_height - ta->line_spacing) * 0.62) + 1;
	ro_convert_pixels_to_os_units(&os_line_height, (os_mode)-1);

	state.w = ta->window;
	error = xwimp_get_window_state(&state);
	if (error) {
		LOG(("xwimp_get_window_state: 0x%x: %s",
				error->errnum, error->errmess));
		return;
	}

	x = x - (state.visible.x0 - state.xscroll) - MARGIN_LEFT;
	y = (state.visible.y1 - state.yscroll) - y;

	line = y / ta->line_height;

	if (line < 0)
		line = 0;
	if (ta->line_count - 1 < (unsigned)line)
		line = ta->line_count - 1;

	code = rufl_x_to_offset(ta->font_family, ta->font_style,
			ta->font_size,
			ta->text + ta->lines[line].b_start,
			ta->lines[line].b_length,
			x, &b_off, &x);
	if (code != rufl_OK) {
		if (code == rufl_FONT_MANAGER_ERROR)
			LOG(("rufl_x_to_offset: 0x%x: %s",
					rufl_fm_error->errnum,
					rufl_fm_error->errmess));
		else
			LOG(("rufl_x_to_offset: 0x%x", code));
		return;
	}

	for (temp = 0, c_off = 0; temp < b_off + ta->lines[line].b_start;
			temp = utf8_next(ta->text, ta->text_len, temp))
		c_off++;

	ro_textarea_set_caret((uintptr_t)ta, c_off);
}
Пример #26
0
/**
 * Set the caret's position
 *
 * \param self Text area
 * \param caret 0-based character index to place caret at
 */
void ro_textarea_set_caret(uintptr_t self, unsigned int caret)
{
	struct text_area *ta;
	size_t c_len, b_off;
	unsigned int i;
	size_t index;
	int x;
	os_coord os_line_height;
	rufl_code code;
	os_error *error;

	ta = (struct text_area *)self;
	if (!ta || ta->magic != MAGIC) {
		LOG(("magic doesn't match"));
		return;
	}

	c_len = utf8_length(ta->text);

	if (caret > c_len)
		caret = c_len;

	/* Find byte offset of caret position */
	for (b_off = 0; caret > 0; caret--)
		b_off = utf8_next(ta->text, ta->text_len, b_off);

	/* Now find line in which byte offset appears */
	for (i = 0; i < ta->line_count - 1; i++)
		if (ta->lines[i + 1].b_start > b_off)
			break;

	ta->caret_pos.line = i;

	/* Now calculate the char. offset of the caret in this line */
	for (c_len = 0, ta->caret_pos.char_off = 0;
			c_len < b_off - ta->lines[i].b_start;
			c_len = utf8_next(ta->text + ta->lines[i].b_start,
					ta->lines[i].b_length, c_len))
		ta->caret_pos.char_off++;


	/* Finally, redraw the WIMP caret */
	index = ro_textarea_get_caret(self);
	os_line_height.x = 0;
	os_line_height.y = (int)((float)(ta->line_height - ta->line_spacing) * 0.62) + 1;
	ro_convert_pixels_to_os_units(&os_line_height, (os_mode)-1);

	for (b_off = 0; index-- > 0; b_off = utf8_next(ta->text, ta->text_len, b_off))
				; /* do nothing */

	code = rufl_width(ta->font_family, ta->font_style, ta->font_size,
			ta->text + ta->lines[ta->caret_pos.line].b_start,
			b_off - ta->lines[ta->caret_pos.line].b_start, &x);
	if (code != rufl_OK) {
		if (code == rufl_FONT_MANAGER_ERROR)
			LOG(("rufl_width: 0x%x: %s",
				rufl_fm_error->errnum,
				rufl_fm_error->errmess));
		else
			LOG(("rufl_width: 0x%x", code));
		return;
	}

	error = xwimp_set_caret_position(ta->window, -1, x + MARGIN_LEFT,
			-((ta->caret_pos.line + 1) * ta->line_height) -
				ta->line_height / 4 + ta->line_spacing,
			os_line_height.y, -1);
	if (error) {
		LOG(("xwimp_set_caret_position: 0x%x: %s",
				error->errnum, error->errmess));
		return;
	}
}
Пример #27
0
/**
 * Replace text in a text area
 *
 * \param self Text area
 * \param start Start character index of replaced section (inclusive)
 * \param end End character index of replaced section (exclusive)
 * \param text UTF-8 text to insert
 */
void ro_textarea_replace_text(uintptr_t self, unsigned int start,
		unsigned int end, const char *text)
{
	struct text_area *ta;
	int b_len = strlen(text);
	size_t b_start, b_end, c_len, diff;

	ta = (struct text_area *)self;
	if (!ta || ta->magic != MAGIC) {
		LOG(("magic doesn't match"));
		return;
	}

	c_len = utf8_length(ta->text);

	if (start > c_len)
		start = c_len;
	if (end > c_len)
		end = c_len;

	if (start == end)
		return ro_textarea_insert_text(self, start, text);

	if (start > end) {
		int temp = end;
		end = start;
		start = temp;
	}

	diff = end - start;

	for (b_start = 0; start-- > 0;
			b_start = utf8_next(ta->text, ta->text_len, b_start))
		; /* do nothing */

	for (b_end = b_start; diff-- > 0;
			b_end = utf8_next(ta->text, ta->text_len, b_end))
		; /* do nothing */

	if (b_len + ta->text_len - (b_end - b_start) >= ta->text_alloc) {
		char *temp = realloc(ta->text,
			b_len + ta->text_len - (b_end - b_start) + 64);
		if (!temp) {
			LOG(("realloc failed"));
			return;
		}

		ta->text = temp;
		ta->text_alloc =
			b_len + ta->text_len - (b_end - b_start) + 64;
	}

	/* Shift text following to new position */
	memmove(ta->text + b_start + b_len, ta->text + b_end,
			ta->text_len - b_end);

	/* Insert new text */
	memcpy(ta->text + b_start, text, b_len);

	ta->text_len += b_len - (b_end - b_start);

	/** \todo calculate line to reflow from */
	ro_textarea_reflow(ta, 0);
}
Пример #28
0
/**
 * 文字コードを変換しながらStreamに出力する
 * v : stream (optional,sb==NULLの場合必須)
 * sb : StrBuf : (optional)
 */
static int stream_write_sub_s(Value v, StrBuf *sb, const char *s_p, int s_size, RefTextIO *tio)
{
    if (s_size < 0) {
        s_size = strlen(s_p);
    }
    // TODO:未検証
    if (v != VALUE_NULL) {
        RefBytesIO *mb = Value_vp(v);
        if (mb->rh.type == fs->cls_bytesio) {
            sb = &mb->buf;
        }
    }
    if (sb != NULL) {
        // sprintfの場合tio==NULL
        if (tio == NULL || tio->cs->utf8) {
            if (!StrBuf_add(sb, s_p, s_size)) {
                return FALSE;
            }
            return TRUE;
        } else {
            if (tio->out.ic == (void*)-1) {
                if (!IconvIO_open(&tio->out, fs->cs_utf8, tio->cs, tio->trans ? "?" : NULL)) {
                    return FALSE;
                }
            }
            if (!IconvIO_conv(&tio->out, sb, s_p, s_size, TRUE, TRUE)) {
                return FALSE;
            }
            return TRUE;
        }
    } else {
        if (tio == NULL || tio->cs->utf8) {
            return stream_write_data(v, s_p, s_size);
        } else {
            Ref *r = Value_ref(v);
            IconvIO *ic = &tio->out;
            Value *vmb = &r->v[INDEX_WRITE_MEMIO];
            RefBytesIO *mb;
            int max = Value_integral(r->v[INDEX_WRITE_MAX]);

            if (max == -1) {
                throw_error_select(THROW_NOT_OPENED_FOR_WRITE);
                return FALSE;
            }
            if (tio->out.ic == (void*)-1) {
                if (!IconvIO_open(&tio->out, fs->cs_utf8, tio->cs, tio->trans ? "?" : NULL)) {
                    return FALSE;
                }
            }
            if (*vmb == VALUE_NULL) {
                *vmb = vp_Value(bytesio_new_sub(NULL, BUFFER_SIZE));
                max = BUFFER_SIZE;
                r->v[INDEX_WRITE_MAX] = int32_Value(max);
                // STDOUTだけ特別扱い
                if (fs->cgi_mode) {
                    if (r == Value_vp(fg->v_cio)) {
                        send_headers();
                    }
                }
            }
            mb = Value_vp(*vmb);

            ic->inbuf = s_p;
            ic->inbytesleft = s_size;
            ic->outbuf = mb->buf.p + mb->buf.size;
            ic->outbytesleft = max - mb->buf.size;

            for (;;) {
                switch (IconvIO_next(ic)) {
                case ICONV_OK:
                    mb->buf.size = ic->outbuf - mb->buf.p;
                    goto BREAK;
                case ICONV_OUTBUF:
                    mb->buf.size = ic->outbuf - mb->buf.p;
                    if (!stream_flush_sub(v)) {
                        return FALSE;
                    }
                    ic->outbuf = mb->buf.p;
                    ic->outbytesleft = max;
                    break;
                case ICONV_INVALID:
                    if (tio->trans) {
                        const char *ptr;
                        if (ic->outbytesleft == 0) {
                            mb->buf.size = ic->outbuf - mb->buf.p;
                            if (!stream_flush_sub(v)) {
                                return FALSE;
                            }
                            ic->outbuf = mb->buf.p;
                            ic->outbytesleft = max;
                        }
                        ptr = ic->inbuf;

                        *ic->outbuf++ = '?';
                        ic->outbytesleft--;

                        // 1文字進める
                        utf8_next(&ptr, ptr + ic->inbytesleft);
                        ic->inbytesleft -= ptr - ic->inbuf;
                        ic->inbuf = ptr;
                    } else {
                        RefCharset *cs = tio->cs;
                        throw_errorf(fs->mod_lang, "CharsetError", "Cannot convert %U to %S",
                                utf8_codepoint_at(ic->inbuf), cs->name);
                        return FALSE;
                    }
                    break;
                }
            }
        BREAK:
            return TRUE;
        }
    }
}
Пример #29
0
/**
 * Convert a UTF-8 encoded string into a string of the given encoding, 
 * applying HTML escape sequences where necessary.
 *
 * \param string   String to convert (NUL-terminated)
 * \param encname  Name of encoding to convert to
 * \param len      Length, in bytes, of the input string, or 0
 * \param result   Pointer to location to receive result
 * \return Appropriate utf8_convert_ret value
 */
utf8_convert_ret utf8_to_html(const char *string, const char *encname,
		size_t len, char **result)
{
	iconv_t cd;
	const char *in;
	char *out, *origout;
	size_t off, prev_off, inlen, outlen, origoutlen, esclen;
	utf8_convert_ret ret;
	char *pescape, escape[11];

	if (len == 0)
		len = strlen(string);

	cd = iconv_open(encname, "UTF-8");
	if (cd == (iconv_t) -1) {
		if (errno == EINVAL)
			return UTF8_CONVERT_BADENC;
		/* default to no memory */
		return UTF8_CONVERT_NOMEM;
	}

	/* Worst case is ASCII -> UCS4, with all characters escaped: 
	 * "&#xYYYYYY;", thus each input character may become a string 
	 * of 10 UCS4 characters, each 4 bytes in length */
	origoutlen = outlen = len * 10 * 4;
	origout = out = malloc(outlen);
	if (out == NULL) {
		iconv_close(cd);
		return UTF8_CONVERT_NOMEM;
	}

	/* Process input in chunks between characters we must escape */
	prev_off = off = 0;
	while (off < len) {
		/* Must escape '&', '<', and '>' */
		if (string[off] == '&' || string[off] == '<' ||
				string[off] == '>') {
			if (off - prev_off > 0) {
				/* Emit chunk */
				in = string + prev_off;
				inlen = off - prev_off;
				ret = utf8_convert_html_chunk(cd, in, inlen,
						&out, &outlen);
				if (ret != UTF8_CONVERT_OK) {
					free(origout);
					iconv_close(cd);
					return ret;
				}
			}

			/* Emit mandatory escape */
			esclen = snprintf(escape, sizeof(escape),
					"&#x%06x;", string[off]);
			pescape = escape;
			ret = utf8_convert_html_chunk(cd, pescape, esclen,
					&out, &outlen);
			if (ret != UTF8_CONVERT_OK) {
				free(origout);
				iconv_close(cd);
				return ret;
			}

			prev_off = off = utf8_next(string, len, off);
		} else {
			off = utf8_next(string, len, off);
		}
	}

	/* Process final chunk */
	if (prev_off < len) {
		in = string + prev_off;
		inlen = len - prev_off;
		ret = utf8_convert_html_chunk(cd, in, inlen, &out, &outlen);
		if (ret != UTF8_CONVERT_OK) {
			free(origout);
			iconv_close(cd);
			return ret;
		}
	}

	iconv_close(cd);

	/* Shrink-wrap */
	*result = realloc(origout, origoutlen - outlen + 4);
	if (*result == NULL) {
		free(origout);
		return UTF8_CONVERT_NOMEM;
	}
	memset(*result + (origoutlen - outlen), 0, 4);

	return UTF8_CONVERT_OK;
}