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; }
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; }