void GUITable::setTextList(const std::vector<std::string> &content, bool transparent) { clear(); if (transparent) { m_background.setAlpha(0); m_border = false; } m_is_textlist = true; s32 empty_string_index = allocString(""); m_rows.resize(content.size()); for (s32 i = 0; i < (s32) content.size(); ++i) { Row *row = &m_rows[i]; row->cells = new Cell[1]; row->cellcount = 1; row->indent = 0; row->visible_index = i; m_visible_rows.push_back(i); Cell *cell = row->cells; cell->xmin = 0; cell->xmax = 0x7fff; // something large enough cell->xpos = 6; cell->content_type = COLUMN_TYPE_TEXT; cell->content_index = empty_string_index; cell->tooltip_index = empty_string_index; cell->color.set(255, 255, 255, 255); cell->color_defined = false; cell->reported_column = 1; // parse row content (color) const std::string &s = content[i]; if (s[0] == '#' && s[1] == '#') { // double # to escape cell->content_index = allocString(s.substr(2)); } else if (s[0] == '#' && s.size() >= 7 && parseColorString( s.substr(0,7), cell->color, false)) { // single # for color cell->color_defined = true; cell->content_index = allocString(s.substr(7)); } else { // no #, just text cell->content_index = allocString(s); } } allocationComplete(); // Clamp scroll bar position updateScrollBar(); }
virtual video::SColor getItemstackColor(const ItemStack &stack, Client *client) const { // Look for direct color definition const std::string &colorstring = stack.metadata.getString("color", 0); video::SColor directcolor; if (!colorstring.empty() && parseColorString(colorstring, directcolor, true)) return directcolor; // See if there is a palette Palette *palette = getPalette(stack.name, client); const std::string &index = stack.metadata.getString("palette_index", 0); if (palette && !index.empty()) return (*palette)[mystoi(index, 0, 255)]; // Fallback color return get(stack.name).color; }
bool read_color(lua_State *L, int index, video::SColor *color) { if (lua_istable(L, index)) { *color = read_ARGB8(L, index); } else if (lua_isnumber(L, index)) { color->set(lua_tonumber(L, index)); } else if (lua_isstring(L, index)) { video::SColor parsed_color; if (!parseColorString(lua_tostring(L, index), parsed_color, true)) return false; *color = parsed_color; } else { return false; } return true; }
void GUITable::setTable(const TableOptions &options, const TableColumns &columns, std::vector<std::string> &content) { clear(); // Naming conventions: // i is always a row index, 0-based // j is always a column index, 0-based // k is another index, for example an option index // Handle a stupid error case... (issue #1187) if (columns.empty()) { TableColumn text_column; text_column.type = "text"; TableColumns new_columns; new_columns.push_back(text_column); setTable(options, new_columns, content); return; } // Handle table options video::SColor default_color(255, 255, 255, 255); s32 opendepth = 0; for (size_t k = 0; k < options.size(); ++k) { const std::string &name = options[k].name; const std::string &value = options[k].value; if (name == "color") parseColorString(value, m_color, false); else if (name == "background") parseColorString(value, m_background, false); else if (name == "border") m_border = is_yes(value); else if (name == "highlight") parseColorString(value, m_highlight, false); else if (name == "highlight_text") parseColorString(value, m_highlight_text, false); else if (name == "opendepth") opendepth = stoi(value); else errorstream<<"Invalid table option: \""<<name<<"\"" <<" (value=\""<<value<<"\")"<<std::endl; } // Get number of columns and rows // note: error case columns.size() == 0 was handled above s32 colcount = columns.size(); assert(colcount >= 1); // rowcount = ceil(cellcount / colcount) but use integer arithmetic s32 rowcount = (content.size() + colcount - 1) / colcount; assert(rowcount >= 0); // Append empty strings to content if there is an incomplete row s32 cellcount = rowcount * colcount; while (content.size() < (u32) cellcount) content.push_back(""); // Create temporary rows (for processing columns) struct TempRow { // Current horizontal position (may different between rows due // to indent/tree columns, or text/image columns with width<0) s32 x; // Tree indentation level s32 indent; // Next cell: Index into m_strings or m_images s32 content_index; // Next cell: Width in pixels s32 content_width; // Vector of completed cells in this row std::vector<Cell> cells; // Stores colors and how long they last (maximum column index) std::vector<std::pair<video::SColor, s32> > colors; TempRow(): x(0), indent(0), content_index(0), content_width(0) {} }; TempRow *rows = new TempRow[rowcount]; // Get em width. Pedantically speaking, the width of "M" is not // necessarily the same as the em width, but whatever, close enough. s32 em = 6; if (m_font) em = m_font->getDimension(L"M").Width; s32 default_tooltip_index = allocString(""); std::map<s32, s32> active_image_indices; // Process content in column-major order for (s32 j = 0; j < colcount; ++j) { // Check column type ColumnType columntype = COLUMN_TYPE_TEXT; if (columns[j].type == "text") columntype = COLUMN_TYPE_TEXT; else if (columns[j].type == "image") columntype = COLUMN_TYPE_IMAGE; else if (columns[j].type == "color") columntype = COLUMN_TYPE_COLOR; else if (columns[j].type == "indent") columntype = COLUMN_TYPE_INDENT; else if (columns[j].type == "tree") columntype = COLUMN_TYPE_TREE; else errorstream<<"Invalid table column type: \"" <<columns[j].type<<"\""<<std::endl; // Process column options s32 padding = myround(0.5 * em); s32 tooltip_index = default_tooltip_index; s32 align = 0; s32 width = 0; s32 span = colcount; if (columntype == COLUMN_TYPE_INDENT) { padding = 0; // default indent padding } if (columntype == COLUMN_TYPE_INDENT || columntype == COLUMN_TYPE_TREE) { width = myround(em * 1.5); // default indent width } for (size_t k = 0; k < columns[j].options.size(); ++k) { const std::string &name = columns[j].options[k].name; const std::string &value = columns[j].options[k].value; if (name == "padding") padding = myround(stof(value) * em); else if (name == "tooltip") tooltip_index = allocString(value); else if (name == "align" && value == "left") align = 0; else if (name == "align" && value == "center") align = 1; else if (name == "align" && value == "right") align = 2; else if (name == "align" && value == "inline") align = 3; else if (name == "width") width = myround(stof(value) * em); else if (name == "span" && columntype == COLUMN_TYPE_COLOR) span = stoi(value); else if (columntype == COLUMN_TYPE_IMAGE && !name.empty() && string_allowed(name, "0123456789")) { s32 content_index = allocImage(value); active_image_indices.insert(std::make_pair( stoi(name), content_index)); } else { errorstream<<"Invalid table column option: \""<<name<<"\"" <<" (value=\""<<value<<"\")"<<std::endl; } } // If current column type can use information from "color" columns, // find out which of those is currently active if (columntype == COLUMN_TYPE_TEXT) { for (s32 i = 0; i < rowcount; ++i) { TempRow *row = &rows[i]; while (!row->colors.empty() && row->colors.back().second < j) row->colors.pop_back(); } } // Make template for new cells Cell newcell; memset(&newcell, 0, sizeof newcell); newcell.content_type = columntype; newcell.tooltip_index = tooltip_index; newcell.reported_column = j+1; if (columntype == COLUMN_TYPE_TEXT) { // Find right edge of column s32 xmax = 0; for (s32 i = 0; i < rowcount; ++i) { TempRow *row = &rows[i]; row->content_index = allocString(content[i * colcount + j]); const core::stringw &text = m_strings[row->content_index]; row->content_width = m_font ? m_font->getDimension(text.c_str()).Width : 0; row->content_width = MYMAX(row->content_width, width); s32 row_xmax = row->x + padding + row->content_width; xmax = MYMAX(xmax, row_xmax); } // Add a new cell (of text type) to each row for (s32 i = 0; i < rowcount; ++i) { newcell.xmin = rows[i].x + padding; alignContent(&newcell, xmax, rows[i].content_width, align); newcell.content_index = rows[i].content_index; newcell.color_defined = !rows[i].colors.empty(); if (newcell.color_defined) newcell.color = rows[i].colors.back().first; rows[i].cells.push_back(newcell); rows[i].x = newcell.xmax; } } else if (columntype == COLUMN_TYPE_IMAGE) { // Find right edge of column s32 xmax = 0; for (s32 i = 0; i < rowcount; ++i) { TempRow *row = &rows[i]; row->content_index = -1; // Find content_index. Image indices are defined in // column options so check active_image_indices. s32 image_index = stoi(content[i * colcount + j]); std::map<s32, s32>::iterator image_iter = active_image_indices.find(image_index); if (image_iter != active_image_indices.end()) row->content_index = image_iter->second; // Get texture object (might be NULL) video::ITexture *image = NULL; if (row->content_index >= 0) image = m_images[row->content_index]; // Get content width and update xmax row->content_width = image ? image->getOriginalSize().Width : 0; row->content_width = MYMAX(row->content_width, width); s32 row_xmax = row->x + padding + row->content_width; xmax = MYMAX(xmax, row_xmax); } // Add a new cell (of image type) to each row for (s32 i = 0; i < rowcount; ++i) { newcell.xmin = rows[i].x + padding; alignContent(&newcell, xmax, rows[i].content_width, align); newcell.content_index = rows[i].content_index; rows[i].cells.push_back(newcell); rows[i].x = newcell.xmax; } active_image_indices.clear(); } else if (columntype == COLUMN_TYPE_COLOR) { for (s32 i = 0; i < rowcount; ++i) { video::SColor cellcolor(255, 255, 255, 255); if (parseColorString(content[i * colcount + j], cellcolor, true)) rows[i].colors.push_back(std::make_pair(cellcolor, j+span)); } } else if (columntype == COLUMN_TYPE_INDENT || columntype == COLUMN_TYPE_TREE) { // For column type "tree", reserve additional space for +/- // Also enable special processing for treeview-type tables s32 content_width = 0; if (columntype == COLUMN_TYPE_TREE) { content_width = m_font ? m_font->getDimension(L"+").Width : 0; m_has_tree_column = true; } // Add a new cell (of indent or tree type) to each row for (s32 i = 0; i < rowcount; ++i) { TempRow *row = &rows[i]; s32 indentlevel = stoi(content[i * colcount + j]); indentlevel = MYMAX(indentlevel, 0); if (columntype == COLUMN_TYPE_TREE) row->indent = indentlevel; newcell.xmin = row->x + padding; newcell.xpos = newcell.xmin + indentlevel * width; newcell.xmax = newcell.xpos + content_width; newcell.content_index = 0; newcell.color_defined = !rows[i].colors.empty(); if (newcell.color_defined) newcell.color = rows[i].colors.back().first; row->cells.push_back(newcell); row->x = newcell.xmax; } } } // Copy temporary rows to not so temporary rows if (rowcount >= 1) { m_rows.resize(rowcount); for (s32 i = 0; i < rowcount; ++i) { Row *row = &m_rows[i]; row->cellcount = rows[i].cells.size(); row->cells = new Cell[row->cellcount]; memcpy((void*) row->cells, (void*) &rows[i].cells[0], row->cellcount * sizeof(Cell)); row->indent = rows[i].indent; row->visible_index = i; m_visible_rows.push_back(i); } } if (m_has_tree_column) { // Treeview: convert tree to indent cells on leaf rows for (s32 i = 0; i < rowcount; ++i) { if (i == rowcount-1 || m_rows[i].indent >= m_rows[i+1].indent) for (s32 j = 0; j < m_rows[i].cellcount; ++j) if (m_rows[i].cells[j].content_type == COLUMN_TYPE_TREE) m_rows[i].cells[j].content_type = COLUMN_TYPE_INDENT; } // Treeview: close rows according to opendepth option std::set<s32> opened_trees; for (s32 i = 0; i < rowcount; ++i) if (m_rows[i].indent < opendepth) opened_trees.insert(i); setOpenedTrees(opened_trees); } // Delete temporary information used only during setTable() delete[] rows; allocationComplete(); // Clamp scroll bar position updateScrollBar(); }
int main(int argc, char *argv[]) { Irrtum irrtum; float opt_size = 16; u32 opt_color = 0xffffffUL; float opt_dpi = 72; int opt_outwidth = 0; int opt_outheight = 0; IntervalList opt_ranges; struct poptOption poptopts[] = { {"size", 's', POPT_ARG_FLOAT, &opt_size, 0, "Set font size in points", "POINTS"}, {"color", 'c', POPT_ARG_STRING, 0, 'c', "Set output color", "NAME|RRGGBB"}, {"dpi", 'd', POPT_ARG_FLOAT, &opt_dpi, 0, "Set DPI value", "DPI"}, {"outwidth", 'w', POPT_ARG_INT, &opt_outwidth, 0, "Set width of output image", "PIXELS"}, {"outheight", 'h', POPT_ARG_INT, &opt_outheight, 0, "Set height of output image. Ignored if --outwidth is not set.", "PIXELS"}, {"range", 'r', POPT_ARG_STRING, 0, 'r', "Add character range", "START-END"}, {"version", 'V', 0, 0, 'V', "Display version number and exit", 0}, POPT_AUTOHELP POPT_TABLEEND }; poptContext poptcon = poptGetContext("irrtum", argc, const_cast<const char**>(argv), poptopts, 0); poptSetOtherOptionHelp(poptcon, "[OPTION...] FILE..."); int rc; while ((rc = poptGetNextOpt(poptcon)) > 0) { if (rc == 'c') { const char *color_str = poptGetOptArg(poptcon); if (!parseColorString(color_str, &opt_color)) { cerr << color_str << ": invalid color (must be a color name or RRGGBB)" << endl; return 1; } } else if (rc == 'r') { const char *range_str = poptGetOptArg(poptcon); s32 from, to; if (opt_ranges.parseInterval(range_str, from, to)) { opt_ranges.addInterval(from, to); } else { cerr << range_str << ": invalid range (must be FROM-TO)" << endl; return 1; } } else if (rc == 'V') { return version(irrtum); } } if (rc < -1) { /* an error occurred during option processing */ cerr << poptBadOption(poptcon, POPT_BADOPTION_NOALIAS) << ": " << poptStrerror(rc) << endl; return 1; } // Clean character range if (opt_ranges.isEmpty()) { opt_ranges.addInterval(32, 255); } if (opt_ranges.getMin() < IRRTUM_CHAR_MIN) { cerr << "warning: character ranges below " << IRRTUM_CHAR_MIN << " are ignored" << endl; opt_ranges.removeBelow(IRRTUM_CHAR_MIN); } if (opt_ranges.getMax() > IRRTUM_CHAR_MAX) { cerr << "warning: character ranges above " << IRRTUM_CHAR_MAX << " are ignored" << endl; opt_ranges.removeAbove(IRRTUM_CHAR_MAX); } if (opt_ranges.isEmpty()) { cerr << "error: all specified character ranges are ignored, exiting" << endl; return 1; } if (!irrtum.initLibpng()) { cerr << "Unable to initialize libpng: " << irrtum.getLastError() << endl; return 1; } if (!irrtum.initFreetype()) { cerr << "Unable to initialize freetype: " << irrtum.getLastError() << endl; return 1; } irrtum.setColor(opt_color); irrtum.setCharacterRanges(opt_ranges); const char* filename = poptGetArg(poptcon); if (!filename) { cerr << "irrtum: no input files" << endl; return 1; } while (filename) { // stage 1: loading the font face cerr << "Loading font face: " << filename << endl; if (!irrtum.loadFace(filename, opt_size, opt_dpi)) { cerr << filename << ": Unable to load font: " << irrtum.getLastError() << endl; return 1; } // stage 2: building the layout if (!irrtum.layout(opt_outwidth, opt_outheight)) { cerr << filename << ": Unable to create layout: " << irrtum.getLastError() << endl; return 1; } // stage 3: drawing an intermediate grayscale bitmap if (!irrtum.drawGrayscaleBitmap()) { cerr << filename << ": Unable to draw bitmap font: " << irrtum.getLastError() << endl; return 1; } // stage 4: converting to ARGB and writing the PNG file std::string outputFilename = irrtum.getOutputFilename(filename); cout << "Writing " << irrtum.getLayoutWidth() << "x" << irrtum.getLayoutHeight() << " PNG image: " << outputFilename << endl; if (!irrtum.outputPNG(outputFilename)) { cerr << outputFilename << ": Unable to write PNG: " << irrtum.getLastError() << endl; return 1; } filename = poptGetArg(poptcon); } poptFreeContext(poptcon); return 0; }
void getCurrentScheduleLighting(float result[]) { int now=Time.hour()*60+Time.minute(); int i=getScheduleRowForTime(now,0); parseColorString(schedule[i].color,result); }
void initiateSchedule(int i, int fadeMS) { currentSchedule=i; float a[LEDS]; parseColorString(schedule[i].color,a); setTarget2(a,fadeMS); }