/* fonts can be up to 16 bits wide */ static void DrawChar(char const Char, unsigned char Op) { unsigned int MaskBit = BIT0; //src unsigned char Rows = GetCurrentFontHeight(); unsigned char CharWidth = GetCharacterWidth(Char); unsigned int bitmap[MAX_FONT_ROWS]; GetCharacterBitmap(Char, (unsigned int *)&bitmap); /* do things bit by bit */ unsigned char i; unsigned char row; for (i = 0; i < CharWidth && gColumn < BYTES_PER_LINE; i++) { for (row = 0; row < Rows; row++) { // if ((MaskBit & bitmap[row])) pMyBuffer[gRow+row].Data[gColumn] |= gBitColumnMask; BitOp(&pMyBuffer[gRow+row].Data[gColumn], gBitColumnMask, MaskBit & bitmap[row], Op); } /* the shift direction seems backwards... */ MaskBit <<= 1; gBitColumnMask <<= 1; if (gBitColumnMask == 0) { gBitColumnMask = BIT0; gColumn++; } } }
float Font::GetTextWidth(const std::string& s) { AMJU_CALL_STACK; float f = 0; int chars = s.size(); for (int i = 0; i < chars; i++) { f += GetCharacterWidth(s[i]); } return f; }
void CFontManager::GetTextSize(vgui::HFont font, const wchar_t *text, int &wide, int &tall) { wide = 0; tall = 0; if (!text) return; tall = GetFontTall(font); int xx = 0; for (int i = 0; ; i++) { wchar_t ch = text[i]; if (ch == 0) { break; } else if (ch == '\n') { tall += GetFontTall(font); xx = 0; } else if (ch == '&') { // underscore character, so skip } else { xx += GetCharacterWidth(font, ch); if (xx > wide) wide = xx; } } }
/** * Compute tiny_step_height and column_size * @return Total width required for the group list. */ uint ComputeGroupInfoSize() { this->column_size[VGC_NAME] = maxdim(GetStringBoundingBox(STR_GROUP_DEFAULT_TRAINS + this->vli.vtype), GetStringBoundingBox(STR_GROUP_ALL_TRAINS + this->vli.vtype)); /* We consider the max average length of characters to be the one of "a" */ this->column_size[VGC_NAME].width = max(GetCharacterWidth(FS_NORMAL, 97) * (MAX_LENGTH_GROUP_NAME_CHARS - 4), this->column_size[VGC_NAME].width); this->tiny_step_height = max(11U, this->column_size[VGC_NAME].height); this->column_size[VGC_PROTECT] = GetSpriteSize(SPR_GROUP_REPLACE_PROTECT); this->tiny_step_height = max(this->tiny_step_height, this->column_size[VGC_PROTECT].height); this->column_size[VGC_AUTOREPLACE] = GetSpriteSize(SPR_GROUP_REPLACE_ACTIVE); this->tiny_step_height = max(this->tiny_step_height, this->column_size[VGC_AUTOREPLACE].height); this->column_size[VGC_PROFIT].width = 0; this->column_size[VGC_PROFIT].height = 0; static const SpriteID profit_sprites[] = {SPR_PROFIT_NA, SPR_PROFIT_NEGATIVE, SPR_PROFIT_SOME, SPR_PROFIT_LOT}; for (uint i = 0; i < lengthof(profit_sprites); i++) { Dimension d = GetSpriteSize(profit_sprites[i]); this->column_size[VGC_PROFIT] = maxdim(this->column_size[VGC_PROFIT], d); } this->tiny_step_height = max(this->tiny_step_height, this->column_size[VGC_PROFIT].height); SetDParamMaxValue(0, GroupStatistics::Get(this->vli.company, ALL_GROUP, this->vli.vtype).num_vehicle, 3, FS_SMALL); this->column_size[VGC_NUMBER] = GetStringBoundingBox(STR_TINY_COMMA); this->tiny_step_height = max(this->tiny_step_height, this->column_size[VGC_NUMBER].height); this->tiny_step_height += WD_MATRIX_TOP; this->tiny_step_height = GetMinSizing(NWST_STEP, this->tiny_step_height); return WD_FRAMERECT_LEFT + 8 + this->column_size[VGC_NAME].width + 2 + this->column_size[VGC_PROTECT].width + 2 + this->column_size[VGC_AUTOREPLACE].width + 2 + this->column_size[VGC_PROFIT].width + 2 + this->column_size[VGC_NUMBER].width + 2 + WD_FRAMERECT_RIGHT; }
TriList* Font::MakeTriList(float x, float y, const char* text, float scaleX) { AMJU_CALL_STACK; #ifdef FONT_DEBUG std::cout << "Font::MakeTriList: x: " << x << " y: " << y << " \"" << text << "\"\n"; #endif Assert(text); AmjuGL::Tris tris; if (*text == 0) { // Empty string return Amju::MakeTriList(tris); } float oldSizeX = m_textureSequence.GetSizeX(); float sizeY = m_textureSequence.GetSizeY(); m_textureSequence.SetSize(oldSizeX * scaleX, sizeY); // TODO TEMP TEST float xOff = x; float yOff = y; int i = 0; while (unsigned char c = text[i++]) { AmjuGL::Tri t[2]; m_textureSequence.MakeTris(c - (char)m_startChar, m_size, t, xOff, yOff); tris.push_back(t[0]); tris.push_back(t[1]); xOff += GetCharacterWidth(c) * scaleX; } m_textureSequence.SetSize(oldSizeX, sizeY); return Amju::MakeTriList(tris); }
/** * Construct a new line with a maximum width. * @param max_width The maximum width of the string. * @return A Line, or NULL when at the end of the paragraph. */ const ParagraphLayouter::Line *FallbackParagraphLayout::NextLine(int max_width) { /* Simple idea: * - split a line at a newline character, or at a space where we can break a line. * - split for a visual run whenever a new line happens, or the font changes. */ if (this->buffer == NULL) return NULL; FallbackLine *l = new FallbackLine(); if (*this->buffer == '\0') { /* Only a newline. */ this->buffer = NULL; *l->Append() = new FallbackVisualRun(this->runs.Begin()->second, this->buffer, 0, 0); return l; } const WChar *begin = this->buffer; const WChar *last_space = NULL; const WChar *last_char = begin; int width = 0; int offset = this->buffer - this->buffer_begin; FontMap::iterator iter = this->runs.Begin(); while (iter->first <= offset) { iter++; assert(iter != this->runs.End()); } const FontCache *fc = iter->second->fc; const WChar *next_run = this->buffer_begin + iter->first; for (;;) { WChar c = *this->buffer; last_char = this->buffer; if (c == '\0') { this->buffer = NULL; break; } if (this->buffer == next_run) { int w = l->GetWidth(); *l->Append() = new FallbackVisualRun(iter->second, begin, this->buffer - begin, w); iter++; assert(iter != this->runs.End()); next_run = this->buffer_begin + iter->first; begin = this->buffer; last_space = NULL; } if (IsWhitespace(c)) last_space = this->buffer; if (IsPrintable(c) && !IsTextDirectionChar(c)) { int char_width = GetCharacterWidth(fc->GetSize(), c); width += char_width; if (width > max_width) { /* The string is longer than maximum width so we need to decide * what to do with it. */ if (width == char_width) { /* The character is wider than allowed width; don't know * what to do with this case... bail out! */ this->buffer = NULL; return l; } if (last_space == NULL) { /* No space has been found. Just terminate at our current * location. This usually happens for languages that do not * require spaces in strings, like Chinese, Japanese and * Korean. For other languages terminating mid-word might * not be the best, but terminating the whole string instead * of continuing the word at the next line is worse. */ last_char = this->buffer; } else { /* A space is found; perfect place to terminate */ this->buffer = last_space + 1; last_char = last_space; } break; } } this->buffer++; } if (l->Length() == 0 || last_char - begin != 0) { int w = l->GetWidth(); *l->Append() = new FallbackVisualRun(iter->second, begin, last_char - begin, w); } return l; }
// **************************************************************************** // // Function Name: RFont::GetCompensationAmount( ) // // Description: Return the compensation amount of the font // // Returns: The requested compensation amount // // Exceptions: Nothing // // **************************************************************************** // YKernSize RFont::GetCompensationAmount( ) { return( ( GetCharacterWidth( RCharacter( 0x20 ) ) / 4 ) ); // REVEIW RAH will this do? }