Пример #1
0
bool gfxr_font_calculate_size(Common::Array<TextFragment> &fragments, gfx_bitmap_font_t *font, int max_width,
	const char *text, int *width, int *height, int *line_height_p, int *last_offset_p, int flags) {

	int maxheight = font->line_height;
	int last_breakpoint = 0;
	int last_break_width = 0;
	int maxwidth = 0, localmaxwidth = 0;
	const char *breakpoint_ptr = NULL;
	unsigned char curChar;

	if (line_height_p)
		*line_height_p = font->line_height;


	fragments.push_back(TextFragment(text));

	while ((curChar = *text++)) {
		if (curChar >= font->chars_nr) {
			error("Invalid char 0x%02x (max. 0x%02x) encountered in text string '%s', font %04x",
			        curChar, font->chars_nr, text, font->ID);
			if (font->chars_nr > ' ')
				curChar = ' ';
			else {
				return false;
			}
		}

		if (((curChar == '\n') || (curChar == 0x0d)) && !(flags & kFontNoNewlines)) {
			fragments.back().length = text - 1 - fragments.back().offset;

			if (*text)
				maxheight += font->line_height;

			if (curChar == 0x0d && *text == '\n')
				text++; // Interpret DOS-style CR LF as single NL

			fragments.push_back(TextFragment(text));

			if (localmaxwidth > maxwidth)
				maxwidth = localmaxwidth;

			localmaxwidth = 0;

		} else { // curChar != '\n'
			localmaxwidth += font->widths[curChar];

			if (localmaxwidth > max_width) {
				int blank_break = 1; // break is at a blank char, i.e. not within a word

				maxheight += font->line_height;

				if (last_breakpoint == 0) { // Text block too long and without whitespace?
					last_breakpoint = localmaxwidth - font->widths[curChar];
					last_break_width = 0;
					--text;
					blank_break = 0; // non-blank break
				} else {
					text = breakpoint_ptr + 1;
					assert(breakpoint_ptr);
				}

				if (last_breakpoint == 0) {
					warning("[GFX] maxsize %d too small for '%s'", max_width, text);
				}

				if (last_breakpoint > maxwidth)
					maxwidth = last_breakpoint;

				fragments.back().length = text - blank_break - fragments.back().offset;
				fragments.push_back(TextFragment(text));

				localmaxwidth = localmaxwidth - last_breakpoint;
				if (!(flags & kFontCountWhitespace))
					localmaxwidth -= last_break_width;
				last_breakpoint = localmaxwidth = 0;

			} else if (*text == ' ') {
				last_breakpoint = localmaxwidth;
				last_break_width = font->widths[curChar];
				breakpoint_ptr = text;
			}

		}
	}

	if (localmaxwidth > maxwidth)
		*width = localmaxwidth;
	else
		*width = maxwidth;

	if (last_offset_p)
		*last_offset_p = localmaxwidth;

	if (height)
		*height = maxheight;

	fragments.back().length = text - fragments.back().offset - 1;

	return true;
}
Пример #2
0
static uint tableRegionToRegion(lua_State *L, const char *className) {
#ifdef DEBUG
	int __startStackDepth = lua_gettop(L);
#endif

	// You can define a region in Lua in two ways:
	// 1. A table that defines a polygon (polgon = table with numbers, which define
	// two consecutive numbers per vertex)
	// 2. A table containing more polygon definitions
	// Then the first polygon is the contour of the region, and the following are holes
	// defined in the first polygon.

	// It may be passed only one parameter, and this must be a table
	if (lua_gettop(L) != 1 || !lua_istable(L, -1)) {
		luaL_error(L, "First and only parameter has to be of type \"table\".");
		return 0;
	}

	uint regionHandle = 0;
	if (!strcmp(className, REGION_CLASS_NAME)) {
		regionHandle = Region::create(Region::RT_REGION);
	} else if (!strcmp(className, WALKREGION_CLASS_NAME)) {
		regionHandle = WalkRegion::create(Region::RT_WALKREGION);
	} else {
		assert(false);
	}

	assert(regionHandle);

	// If the first element of the parameter is a number, then case 1 is accepted
	// If the first element of the parameter is a table, then case 2 is accepted
	// If the first element of the parameter has a different type, there is an error
	lua_rawgeti(L, -1, 1);
	int firstElementType = lua_type(L, -1);
	lua_pop(L, 1);

	switch (firstElementType) {
	case LUA_TNUMBER: {
		Polygon polygon;
		tablePolygonToPolygon(L, polygon);
		RegionRegistry::instance().resolveHandle(regionHandle)->init(polygon);
	}
	break;

	case LUA_TTABLE: {
		lua_rawgeti(L, -1, 1);
		Polygon polygon;
		tablePolygonToPolygon(L, polygon);
		lua_pop(L, 1);

		int polygonCount = luaL_getn(L, -1);
		if (polygonCount == 1)
			RegionRegistry::instance().resolveHandle(regionHandle)->init(polygon);
		else {
			Common::Array<Polygon> holes;
			holes.reserve(polygonCount - 1);

			for (int i = 2; i <= polygonCount; i++) {
				lua_rawgeti(L, -1, i);
				holes.resize(holes.size() + 1);
				tablePolygonToPolygon(L, holes.back());
				lua_pop(L, 1);
			}
			assert((int)holes.size() == polygonCount - 1);

			RegionRegistry::instance().resolveHandle(regionHandle)->init(polygon, &holes);
		}
	}
	break;

	default:
		luaL_error(L, "Illegal region definition.");
		return 0;
	}

#ifdef DEBUG
	assert(__startStackDepth == lua_gettop(L));
#endif

	return regionHandle;
}