Esempio n. 1
0
/**
 * Measure the width of a string.
 *
 * \param  fstyle  plot 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 nserror
ro_font_width(const plot_font_style_t *fstyle,
		const char *string, size_t length,
		int *width)
{
	const char *font_family;
	unsigned int font_size;
	rufl_style font_style;
	rufl_code code;

	nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
	if (font_size == 0) {
		*width = 0;
		return NSERROR_OK;
	}

	code = rufl_width(font_family, font_style, font_size,
			string, length,
			width);
	if (code != rufl_OK) {
		if (code == rufl_FONT_MANAGER_ERROR)
			LOG("rufl_width: rufl_FONT_MANAGER_ERROR: 0x%x: %s", rufl_fm_error->errnum, rufl_fm_error->errmess);
		else
			LOG("rufl_width: 0x%x", code);
/* 		ro_warn_user("MiscError", "font error"); */
		*width = 0;
		return NSERROR_INVALID;
	}

	*width /= 2;
	return NSERROR_OK;
}
Esempio n. 2
0
bool nsfont_split(const plot_font_style_t *fstyle,
		const char *string, size_t length,
		int x, size_t *char_offset, int *actual_x)
{
	const char *font_family;
	unsigned int font_size;
	rufl_style font_style;
	rufl_code code;

	nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
	if (font_size == 0) {
		*char_offset = 0;
		*actual_x = 0;
		return true;
	}

	code = rufl_split(font_family, font_style, font_size,
			string, length,
			x * 2, char_offset, actual_x);
	if (code != rufl_OK) {
		if (code == rufl_FONT_MANAGER_ERROR)
			LOG(("rufl_split: rufl_FONT_MANAGER_ERROR: "
					"0x%x: %s",
					rufl_fm_error->errnum,
					rufl_fm_error->errmess));
		else
			LOG(("rufl_split: 0x%x", code));
/* 		warn_user("MiscError", "font error"); */
		return false;
	}

	while (*char_offset && string[*char_offset] != ' ')
		(*char_offset)--;

	code = rufl_width(font_family, font_style, font_size,
			string, *char_offset,
			actual_x);
	if (code != rufl_OK) {
		if (code == rufl_FONT_MANAGER_ERROR)
			LOG(("rufl_width: rufl_FONT_MANAGER_ERROR: 0x%x: %s",
					rufl_fm_error->errnum,
					rufl_fm_error->errmess));
		else
			LOG(("rufl_width: 0x%x", code));
/* 		warn_user("MiscError", "font error"); */
		return false;
	}

	*actual_x /= 2;
	return true;
}
Esempio n. 3
0
static PyObject *
pyrufl_width(PyObject *self /* Not used */, PyObject *args)
{
	const char *font_family;
	rufl_style font_style;
	unsigned int font_size;
	const char *string;
	int length;
	int width = 0;

	if (!PyArg_ParseTuple(args, "siIs#",
			&font_family, &font_style, &font_size,
			&string, &length))
		return NULL;

	rufl_width(font_family, font_style, font_size, string, length,
			&width);

	return PyInt_FromLong(width);
}
Esempio n. 4
0
int main(void)
{
	char utf8_test[] = "Hello,	world! ὕαλον "
			"Uherské Hradiště. 𐀀";
	int width;
	size_t char_offset;
	int x;
	int actual_x;
	struct rufl_decomp_funcs funcs = { move_to, line_to, cubic_to };
	int bbox[4];

	try(rufl_init(), "rufl_init");
	rufl_dump_state();
	try(rufl_paint("NewHall", rufl_WEIGHT_400, 240,
			utf8_test, sizeof utf8_test - 1,
			1200, 1000, 0), "rufl_paint");
	try(rufl_width("NewHall", rufl_WEIGHT_400, 240,
			utf8_test, sizeof utf8_test - 1,
			&width), "rufl_width");
	printf("width: %i\n", width);
	for (x = 0; x < width + 100; x += 100) {
		try(rufl_x_to_offset("NewHall", rufl_WEIGHT_400, 240,
				utf8_test, sizeof utf8_test - 1,
				x, &char_offset, &actual_x),
				"rufl_x_to_offset");
		printf("x to offset: %i -> %i %zi \"%s\"\n", x, actual_x,
				char_offset, utf8_test + char_offset);
		try(rufl_split("NewHall", rufl_WEIGHT_400, 240,
				utf8_test, sizeof utf8_test - 1,
				x, &char_offset, &actual_x),
				"rufl_split");
		printf("split: %i -> %i %zi \"%s\"\n", x, actual_x,
				char_offset, utf8_test + char_offset);
	}
	try(rufl_decompose_glyph("Homerton", rufl_WEIGHT_400, 1280,
				"A", 1, &funcs, 0),
				"rufl_decompose_glyph");
	try(rufl_paint_callback("NewHall", rufl_WEIGHT_400, 240,
			utf8_test, sizeof utf8_test - 1,
			1200, 1000, callback, 0), "rufl_paint_callback");
	try(rufl_font_bbox("NewHall", rufl_WEIGHT_400, 240, bbox),
			"rufl_font_bbox");
	printf("bbox: %i %i %i %i\n", bbox[0], bbox[1], bbox[2], bbox[3]);
	rufl_quit();

	return 0;
}


void try(rufl_code code, const char *context)
{
	if (code == rufl_OK)
		return;
	else if (code == rufl_OUT_OF_MEMORY)
		printf("error: %s: out of memory\n", context);
	else if (code == rufl_FONT_MANAGER_ERROR)
		printf("error: %s: Font Manager error %x %s\n", context,
				rufl_fm_error->errnum,
				rufl_fm_error->errmess);
	else if (code == rufl_FONT_NOT_FOUND)
		printf("error: %s: font not found\n", context);
	else if (code == rufl_IO_ERROR)
		printf("error: %s: io error: %i %s\n", context, errno,
				strerror(errno));
	else if (code == rufl_IO_EOF)
		printf("error: %s: eof\n", context);
	else
		printf("error: %s: unknown error\n", context);
	rufl_quit();
	exit(1);
}


int move_to(os_coord *to, void *user)
{
	(void) user;

	printf("Move to (%d,%d)\n", to->x, to->y);

	return 0;
}


int line_to(os_coord *to, void *user)
{
	(void) user;

	printf("Line to (%d,%d)\n", to->x, to->y);

	return 0;
}


int cubic_to(os_coord *control1, os_coord *control2, os_coord *to,
		void *user)
{
	(void) user;

	printf("Bezier to (%d,%d),(%d,%d),(%d,%d)\n",
			control1->x, control1->y,
			control2->x, control2->y,
			to->x, to->y);

	return 0;
}


void callback(void *context,
		const char *font_name, unsigned int font_size,
		const char *s8, unsigned short *s16, unsigned int n,
		int x, int y)
{
	(void) context;

	printf("callback: \"%s\", %u, ", font_name, font_size);
	if (s8)
		printf("s8 \"%.*s\" ", n, s8);
	else {
		printf("s16 \"");
		for (unsigned int i = 0; i != n; i++)
			printf("%x ", (unsigned int) s16[i]);
		printf("\" ");
	}
	printf("%i %i\n", x, y);
}
Esempio n. 5
0
/**
 * Find where to split a string to make it fit a width.
 *
 * \param  fstyle       style for this text
 * \param  string       UTF-8 string to measure
 * \param  length       length of string, in bytes
 * \param  x            width available
 * \param  char_offset  updated to offset in string of actual_x, [1..length]
 * \param  actual_x     updated to x coordinate of character closest to x
 * \return  true on success, false on error and error reported
 *
 * On exit, char_offset indicates first character after split point.
 *
 * Note: char_offset of 0 should never be returned.
 *
 *   Returns:
 *     char_offset giving split point closest to x, where actual_x <= x
 *   else
 *     char_offset giving split point closest to x, where actual_x > x
 *
 * Returning char_offset == length means no split possible
 */
static nserror
ro_font_split(const plot_font_style_t *fstyle,
		const char *string, size_t length,
		int x, size_t *char_offset, int *actual_x)
{
	const char *font_family;
	unsigned int font_size;
	rufl_style font_style;
	rufl_code code;

	nsfont_read_style(fstyle, &font_family, &font_size, &font_style);
	if (font_size == 0) {
		*char_offset = 0;
		*actual_x = 0;
		return NSERROR_OK;
	}

	code = rufl_split(font_family, font_style, font_size,
			string, length,
			x * 2, char_offset, actual_x);
	if (code != rufl_OK) {
		if (code == rufl_FONT_MANAGER_ERROR) {
			LOG("rufl_split: rufl_FONT_MANAGER_ERROR: ""0x%x: %s",
			    rufl_fm_error->errnum, rufl_fm_error->errmess);
		} else {
			LOG("rufl_split: 0x%x", code);
		}
/* 		ro_warn_user("MiscError", "font error"); */
		*char_offset = 0;
		*actual_x = 0;
		return NSERROR_INVALID;
	}

	if (*char_offset != length) {
		/* we found something to split at */
		size_t orig = *char_offset;

		/* ensure a space at <= the split point we found */
		while (*char_offset && string[*char_offset] != ' ') {
			(*char_offset)--;
		}

		/* nothing valid found <= split point, advance to next space */
		if (*char_offset == 0) {
			*char_offset = orig;
			while ((*char_offset != length) &&
			       (string[*char_offset] != ' ')) {
				(*char_offset)++;
			}
		}
	}

	code = rufl_width(font_family, font_style, font_size,
			string, *char_offset,
			actual_x);
	if (code != rufl_OK) {
		if (code == rufl_FONT_MANAGER_ERROR) {
			LOG("rufl_width: rufl_FONT_MANAGER_ERROR: 0x%x: %s",
			    rufl_fm_error->errnum, rufl_fm_error->errmess);
		} else {
			LOG("rufl_width: 0x%x", code);
		}
/* 		ro_warn_user("MiscError", "font error"); */
		*char_offset = 0;
		*actual_x = 0;
		return NSERROR_INVALID;
	}

	*actual_x /= 2;
	return NSERROR_OK;
}
Esempio n. 6
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;
	}
}
Esempio n. 7
0
void pencil_save_pass1(struct pencil_save_context *context,
		struct pencil_item *item, unsigned int depth)
{
	rufl_code code;
	struct pencil_item *child;

	assert(item);

	/* Initialise item bounding box */
	item->bbox.x0 = INT_MAX;
	item->bbox.y0 = INT_MAX;
	item->bbox.x1 = INT_MIN;
	item->bbox.y1 = INT_MIN;

	for (child = item->children; child; child = child->next) {
		pencil_save_pass1(context, child, depth + 1);
		if (context->code != pencil_OK)
			return;

		/* Update item bounding box to include child */
		if (child->bbox.x0 < item->bbox.x0)
			item->bbox.x0 = child->bbox.x0;
		if (child->bbox.y0 < item->bbox.y0)
			item->bbox.y0 = child->bbox.y0;
		if (child->bbox.x1 > item->bbox.x1)
			item->bbox.x1 = child->bbox.x1;
		if (child->bbox.y1 > item->bbox.y1)
			item->bbox.y1 = child->bbox.y1;
	}

	switch (item->type) {
	case pencil_GROUP:
		if (!item->children || MAX_DEPTH <= depth ||
				(item->bbox.x0 == INT_MAX && 
				item->bbox.y0 == INT_MAX &&
				item->bbox.x1 == INT_MIN &&
				item->bbox.y1 == INT_MIN))
			break;

		context->size += 36;

		break;
	case pencil_TEXT:
	{
		int bbox[4];
		int width;

		code = rufl_paint_callback(item->font_family, item->font_style,
				item->font_size, item->text, strlen(item->text),
				item->x, item->y,
				pencil_save_pass1_text_callback, context);
		if (code != rufl_OK)
			context->code = code;
		if (context->code != pencil_OK)
			return;

		code = rufl_font_bbox(item->font_family, item->font_style,
				item->font_size, bbox);
		if (code != rufl_OK)
			context->code = code;
		if (context->code != pencil_OK)
			return;

		code = rufl_width(item->font_family, item->font_style,
				item->font_size, item->text, strlen(item->text),
				&width);
		if (code != rufl_OK)
			context->code = code;
		if (context->code != pencil_OK)
			return;

		item->bbox.x0 = item->x * 256;
		item->bbox.y0 = item->y * 256;
		item->bbox.x1 = (item->x + width) * 256;
		item->bbox.y1 = (item->y + (bbox[3] - bbox[1])) * 256;
	}
		break;
	case pencil_PATH:
		context->size += 24 + 16 + item->path_size * 4;
		if (item->pattern != pencil_SOLID)
			context->size += 12;

		/* Calculate bounding box */
		for (unsigned int i = 0; i != item->path_size; ) {
			switch (item->path[i]) {
			case 0:
			case 5:
				i++;
				break;
			case 2:
			case 6:
			case 8:
			{
				int points = item->path[i++] == 6 ? 3 : 1;

				for (; points > 0; points--) {
					int x = item->path[i++] * 256;
					int y = item->path[i++] * 256;

					if (x < item->bbox.x0)
						item->bbox.x0 = x;
					if (y < item->bbox.y0)
						item->bbox.y0 = y;
					if (x > item->bbox.x1)
						item->bbox.x1 = x;
					if (y > item->bbox.y1)
						item->bbox.y1 = y;
				}
			}
				break;
			default:
				assert(0);
			}
		}
		break;
	case pencil_SPRITE:
		context->size += 24 + ((const osspriteop_header *)
				item->sprite)->size;

		item->bbox.x0 = item->x * 256;
		item->bbox.y0 = item->y * 256;
		item->bbox.x1 = (item->x + item->width) * 256;
		item->bbox.y1 = (item->y + item->height) * 256;
		break;
	default:
		assert(0);
	}

	/* Update global bounding box */
	if (item->bbox.x0 < context->bbox.x0)
		context->bbox.x0 = item->bbox.x0;
	if (item->bbox.y0 < context->bbox.y0)
		context->bbox.y0 = item->bbox.y0;
	if (item->bbox.x1 > context->bbox.x1)
		context->bbox.x1 = item->bbox.x1;
	if (item->bbox.y1 > context->bbox.y1)
		context->bbox.y1 = item->bbox.y1;
}