int Font::PrintInitial(int x, int y, const Region &rgn, ieWord currChar) const { const Sprite2D* glyph = GetCharSprite(currChar); core->GetVideoDriver()->BlitSprite(glyph, x + rgn.x, y + rgn.y, true, &rgn); x += glyph->Width; return x; }
int Font::CalcStringWidth(const char* string, bool NoColor) const { size_t ret = 0, len = strlen( string ); for (size_t i = 0; i < len; i++) { if (( ( unsigned char ) string[i] ) == '[' && !NoColor) { while(i<len && ((unsigned char) string[i]) != ']') { i++; } } ret += GetCharSprite((unsigned char)string[i])->Width; } return ( int ) ret; }
size_t Font::CalcStringWidth(const ieWord* string, bool NoColor) const { size_t ret = 0, len = dbStrLen(string); for (size_t i = 0; i < len; i++) { if (( string[i] ) == '[' && !NoColor) { i++; // cannot be ']' when it is '[' while(i<len && (string[i]) != ']') { i++; } } else { ret += GetCharSprite(string[i])->Width; } } return ret; }
size_t Font::CalcStringHeight(const ieWord* string, unsigned int len, bool NoColor) const { int h, max = 0; for (unsigned int i = 0; i < len; i++) { if (( string[i] ) == '[' && !NoColor) { i++; // cannot be ']' when it is '[' while(i<len && (string[i]) != ']') { i++; } } else { h = GetCharSprite(string[i])->Height; //the space check is here to hack around overly high frames //in some bg1 fonts that throw vertical alignment off if (h > max && string[i] != ' ') { max = h; } } } return max; }
void Font::PrintFromLine(int startrow, Region rgn, const unsigned char* string, Palette* hicolor, ieByte Alignment, Font* initials, Sprite2D* cursor, unsigned int curpos, bool NoColor) const { bool enablecap=false; int capital = 0; int initials_rows = 0; int last_initial_row = 0; int initials_x = 0; int initials_row = 0; ieWord currCap = 0; ieWord* tmp = NULL; size_t len = GetDoubleByteString(string, tmp); ieWord num_empty_rows = 0; if (initials && initials != this) { capital=1; enablecap=true; initials_rows = 1 + ((initials->maxHeight - 1) / maxHeight); // ceiling currCap = string[0]; if ((startrow > 0 && initials_rows > 0) || (len > 0 && isspace(currCap))) { // we need to look back to get the cap while(isspace(currCap) && num_empty_rows < len){//we cant cap whiteSpace so keep looking currCap = string[++num_empty_rows]; // WARNING: this assumes all preceeding whiteSpace is an empty line } last_initial_row = startrow - 1; // always the row before current since this cannot be the first row initials_rows = initials_rows - (startrow + 1) + num_empty_rows; // startrow + 1 because start row is 0 based, but initials_rows is 1 based } } unsigned int psx = IE_FONT_PADDING; Palette *pal = hicolor; if (!pal) { pal = palette; } Holder<Palette> blitPalette = pal; SetupString( tmp, rgn.w, NoColor, initials, enablecap ); if (startrow) enablecap=false; int ystep; if (Alignment & IE_FONT_SINGLE_LINE) { ystep = CalcStringHeight(tmp, len, NoColor); if (!ystep) ystep = maxHeight; } else { ystep = maxHeight; } int x = psx, y = ystep; size_t w = CalcStringWidth( tmp, NoColor ); if (Alignment & IE_FONT_ALIGN_CENTER) { x = ( rgn.w - w) / 2; } else if (Alignment & IE_FONT_ALIGN_RIGHT) { x = ( rgn.w - w ) - IE_FONT_PADDING; } if (Alignment & IE_FONT_ALIGN_MIDDLE) { int h = 0; for (size_t i = 0; i <= len; i++) { if (( tmp[i] == 0 ) || ( tmp[i] == '\n' )) h++; } h = h * ystep; y += ( rgn.h - h ) / 2; } else if (Alignment & IE_FONT_ALIGN_BOTTOM) { int h = 0; for (size_t i = 0; i <= len; i++) { if (( tmp[i] == 0 ) || ( tmp[i] == '\n' )) h++; } h = h * ystep; y += ( rgn.h - h ) - IE_FONT_PADDING; } else if (Alignment & IE_FONT_ALIGN_TOP) { y += IE_FONT_PADDING; } Video* video = core->GetVideoDriver(); const Sprite2D* currGlyph; ieWord currChar = '\0'; int row = 0; for (size_t i = 0; i < len; i++) { if (( tmp[i] ) == '[' && !NoColor) { i++; char tag[256]; tag[0]=0; for (size_t k = 0; k < 256 && i<len; k++) { if (tmp[i] == ']') { tag[k] = 0; break; } tag[k] = tmp[i++]; } if (strnicmp( tag, "capital=",8)==0) { sscanf( tag, "capital=%d", &capital); if (capital && (row>=startrow) ) { enablecap=true; } continue; } if (strnicmp( tag, "color=", 6 ) == 0) { unsigned int r,g,b; if (sscanf( tag, "color=%02X%02X%02X", &r, &g, &b ) != 3) continue; const Color c = {(unsigned char)r, (unsigned char)g, (unsigned char)b, 0}; Palette* newPal = core->CreatePalette( c, palette->back ); blitPalette = newPal; gamedata->FreePalette( newPal ); continue; } if (stricmp( tag, "/color" ) == 0) { blitPalette = pal; continue; } if (stricmp( "p", tag ) == 0) { psx = x; continue; } if (stricmp( "/p", tag ) == 0) { psx = IE_FONT_PADDING; } continue; } if (row < startrow) { if (tmp[i] == 0) { row++; } continue; } if (( tmp[i] == 0 ) || ( tmp[i] == '\n' )) { y += ystep; x = psx; size_t w = CalcStringWidth( &tmp[i + 1], NoColor ); if (initials_rows > 0) { initials_rows--; x += initials_x; w += initials_x; } if (Alignment & IE_FONT_ALIGN_CENTER) { x = ( rgn.w - w ) / 2; } else if (Alignment & IE_FONT_ALIGN_RIGHT) { x = ( rgn.w - w ); } continue; } currChar = tmp[i]; if (initials && capital && enablecap) { currCap = currChar; x = initials->PrintInitial( x, y, rgn, currChar ); initials_x = x; //how many more lines to be indented (one was already indented) initials_rows = (initials->maxHeight - 1) / maxHeight; initials_rows += num_empty_rows; initials_row = row; last_initial_row = initials_row; enablecap = false; continue; } else if (initials && currCap && row > last_initial_row && (row - num_empty_rows - initials_row) <= ((initials->maxHeight-1)/maxHeight)){ // means this row doesnt have a cap, but a preceeding one did and its overlapping this row int initY = y; if (!num_empty_rows || row > num_empty_rows) {// num_empty_rows is for scrolling text areas initY = (y - (maxHeight * (row - initials_row - num_empty_rows))); } x = initials->PrintInitial( x, initY, rgn, currCap ); initials_x = x; last_initial_row++; if (num_empty_rows && row <= num_empty_rows) continue; else x += psx; } if (i > 0) { // kerning x -= GetKerningOffset(tmp[i-1], currChar); } currGlyph = GetCharSprite(currChar); video->BlitSprite(currGlyph, x + rgn.x, y + rgn.y, true, &rgn, blitPalette.get()); if (cursor && ( i == curpos )) { video->BlitSprite( cursor, x + rgn.x, y + rgn.y, true, &rgn ); } x += currGlyph->Width; } if (cursor && ( curpos == len )) { video->BlitSprite( cursor, x + rgn.x, y + rgn.y, true, &rgn ); } blitPalette = NULL; free( tmp ); }
void Font::SetupString(ieWord* string, unsigned int width, bool NoColor, Font *initials, bool enablecap) const { size_t len = dbStrLen(string); unsigned int psx = IE_FONT_PADDING; size_t lastpos = 0; unsigned int x = psx, wx = 0; bool endword = false; int initials_rows = 0; int initials_x = 0; for (size_t pos = 0; pos < len; pos++) { if (x + wx > width) { // we wrapped, force a new line somewhere if (!endword && ( x == psx )) lastpos = pos; else string[lastpos] = 0; x = psx; if (initials_rows > 0) { initials_rows--; x += initials_x; } } if (string[pos] == 0) { continue; } endword = false; if (string[pos] == '\r') string[pos] = ' '; if (string[pos] == '\n') { // force a new line here string[pos] = 0; x = psx; wx = 0; if (initials_rows > 0) { initials_rows--; x += initials_x; } lastpos = pos; endword = true; continue; } if (( string[pos] ) == '[' && !NoColor) { pos++; if (pos>=len) break; char tag[256]; int k = 0; for (k = 0; k < 256; k++) { if (string[pos] == ']') { tag[k] = 0; break; } tag[k] = string[pos++]; } if (strnicmp( tag, "capital=",8)==0) { int capital = 0; sscanf( tag, "capital=%d", &capital); if (capital) { enablecap=true; } continue; } if (stricmp( "p", tag ) == 0) { psx = x; continue; } if (stricmp( "/p", tag ) == 0) { psx = IE_FONT_PADDING; continue; } continue; } if (initials && enablecap) { wx += initials->GetCharSprite(string[pos])->Width; enablecap=false; initials_x = wx + psx; //how many more lines to be indented (one was already indented) initials_rows = (initials->maxHeight - 1) / maxHeight; continue; } else { wx += GetCharSprite(string[pos])->Width; } if (( string[pos] == ' ' ) || ( string[pos] == '-' )) { x += wx; wx = 0; lastpos = pos; endword = true; } } }
void Font::Print(Region cliprgn, Region rgn, const unsigned char* string, Palette* hicolor, ieByte Alignment, bool anchor, Font* initials, Sprite2D* cursor, unsigned int curpos, bool NoColor) const { int capital = (initials) ? 1 : 0; unsigned int psx = IE_FONT_PADDING; Palette* pal = hicolor; if (!pal) { pal = palette; } if (initials==this) { initials = NULL; } Holder<Palette> blitPalette = pal; ieWord* tmp = NULL; size_t len = GetDoubleByteString(string, tmp); while (len > 0 && (tmp[len - 1] == '\n' || tmp[len - 1] == '\r')) { // ignore trailing newlines tmp[len - 1] = 0; len--; } SetupString( tmp, rgn.w, NoColor, initials, capital ); int ystep; if (Alignment & IE_FONT_SINGLE_LINE) { ystep = CalcStringHeight(tmp, len, NoColor); if (!ystep) ystep = maxHeight; } else { ystep = maxHeight; } int x = psx, y = ystep; Video* video = core->GetVideoDriver(); if (Alignment & IE_FONT_ALIGN_CENTER) { size_t w = CalcStringWidth( tmp, NoColor ); x = ( rgn.w - w ) / 2; } else if (Alignment & IE_FONT_ALIGN_RIGHT) { size_t w = CalcStringWidth( tmp, NoColor ); x = ( rgn.w - w ) - IE_FONT_PADDING; } if (Alignment & IE_FONT_ALIGN_MIDDLE) { int h = 0; for (size_t i = 0; i <= len; i++) { if (tmp[i] == 0) h++; } h = h * ystep; y += ( rgn.h - h ) / 2; } else if (Alignment & IE_FONT_ALIGN_BOTTOM) { int h = 0; for (size_t i = 0; i <= len; i++) { if (tmp[i] == 0) h++; } h = h * ystep; y += ( rgn.h - h ) - IE_FONT_PADDING; } else if (Alignment & IE_FONT_ALIGN_TOP) { y += IE_FONT_PADDING; } ieWord currChar = '\0'; const Sprite2D* currGlyph = NULL; for (size_t i = 0; i < len; i++) { if (( tmp[i] ) == '[' && !NoColor) { i++; char tag[256]; tag[0]=0; for (size_t k = 0; k < 256 && i<len; k++) { if (tmp[i] == ']') { tag[k] = 0; break; } tag[k] = tmp[i++]; } if (strnicmp( tag, "capital=",8)==0) { sscanf( tag, "capital=%d", &capital); continue; } if (strnicmp( tag, "color=", 6 ) == 0) { unsigned int r,g,b; if (sscanf( tag, "color=%02X%02X%02X", &r, &g, &b ) != 3) continue; const Color c = {(unsigned char)r, (unsigned char)g, (unsigned char)b, 0}; Palette* newPal = core->CreatePalette( c, palette->back ); blitPalette = newPal; gamedata->FreePalette( newPal ); continue; } if (stricmp( tag, "/color" ) == 0) { blitPalette = pal; continue; } if (stricmp( "p", tag ) == 0) { psx = x; continue; } if (stricmp( "/p", tag ) == 0) { psx = IE_FONT_PADDING; continue; } continue; } if (tmp[i] == 0) { y += ystep; x = psx; size_t w = CalcStringWidth( &tmp[i + 1], NoColor ); if (Alignment & IE_FONT_ALIGN_CENTER) { x = ( rgn.w - w ) / 2; } else if (Alignment & IE_FONT_ALIGN_RIGHT) { x = ( rgn.w - w ); } continue; } currChar = tmp[i]; currGlyph = GetCharSprite(currChar); if (initials && capital) { x = initials->PrintInitial( x, y, rgn, currChar ); continue; } if (i > 0) { // kerning x -= GetKerningOffset(tmp[i-1], currChar); } video->BlitSprite(currGlyph, x + rgn.x, y + rgn.y, anchor, &cliprgn, blitPalette.get()); if (cursor && ( curpos == i )) video->BlitSprite( cursor, x + rgn.x, y + rgn.y, anchor, &cliprgn ); x += currGlyph->Width; } if (cursor && ( curpos == len )) { video->BlitSprite( cursor, x + rgn.x, y + rgn.y, anchor, &cliprgn ); } blitPalette = NULL; free( tmp ); }