diff options
Diffstat (limited to 'graphics/font.cpp')
-rw-r--r-- | graphics/font.cpp | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/graphics/font.cpp b/graphics/font.cpp new file mode 100644 index 0000000000..e57cb3aae1 --- /dev/null +++ b/graphics/font.cpp @@ -0,0 +1,156 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002-2004 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + */ + +#include "common/stdafx.h" +#include "graphics/font.h" + +namespace Graphics { + +int NewFont::getCharWidth(byte chr) const { + // If no width table is specified, return the maximum width + if (!width) + return maxwidth; + // If this character is not included in the font, use the default char. + if (chr < firstchar || firstchar + size < chr) { + if (chr == ' ') + return maxwidth / 2; + chr = defaultchar; + } + return width[chr - firstchar]; +} + +void NewFont::drawChar(const Surface *dst, byte chr, int x, int y, uint32 color) const { + assert(dst != 0); + byte *ptr = (byte *)dst->pixels + x * dst->bytesPerPixel + y * dst->pitch; + + assert(bits != 0 && maxwidth <= 16); + assert(dst->bytesPerPixel == 1 || dst->bytesPerPixel == 2); + + // If this character is not included in the font, use the default char. + if (chr < firstchar || chr >= firstchar + size) { + if (chr == ' ') + return; + chr = defaultchar; + } + + const int w = getCharWidth(chr); + chr -= firstchar; + const bitmap_t *tmp = bits + (offset ? offset[chr] : (chr * height)); + + for (y = 0; y < height; y++) { + const bitmap_t buffer = *tmp++; + bitmap_t mask = 0x8000; + for (x = 0; x < w; x++) { + if ((buffer & mask) != 0) { + if (dst->bytesPerPixel == 1) + ptr[x] = color; + else if (dst->bytesPerPixel == 2) + ((uint16 *)ptr)[x] = color; + } + mask >>= 1; + } + ptr += dst->pitch; + } +} + + +#pragma mark - + + +int Font::getStringWidth(const Common::String &str) const { + int space = 0; + + for (uint i = 0; i < str.size(); ++i) + space += getCharWidth(str[i]); + return space; +} + +void Font::drawString(const Surface *dst, const Common::String &s, int x, int y, int w, uint32 color, TextAlignment align, int deltax, bool useEllipsis) const { + assert(dst != 0); + const int leftX = x, rightX = x + w; + uint i; + int width = getStringWidth(s); + Common::String str; + + if (useEllipsis && width > w) { + // String is too wide. So we shorten it "intellegently", by replacing + // parts of it by an ellipsis ("..."). There are three possibilities + // for this: replace the start, the end, or the middle of the string. + // What is best really depends on the context; but unless we want to + // make this configurable, replacing the middle probably is a good + // compromise. + const int ellipsisWidth = getStringWidth("..."); + + // SLOW algorithm to remove enough of the middle. But it is good enough + // for now. + const int halfWidth = (w - ellipsisWidth) / 2; + int w2 = 0; + + for (i = 0; i < s.size(); ++i) { + int charWidth = getCharWidth(s[i]); + if (w2 + charWidth > halfWidth) + break; + w2 += charWidth; + str += s[i]; + } + // At this point we know that the first 'i' chars are together 'w2' + // pixels wide. We took the first i-1, and add "..." to them. + str += "..."; + + // The original string is width wide. Of those we already skipped past + // w2 pixels, which means (width - w2) remain. + // The new str is (w2+ellipsisWidth) wide, so we can accomodate about + // (w - (w2+ellipsisWidth)) more pixels. + // Thus we skip ((width - w2) - (w - (w2+ellipsisWidth))) = + // (width + ellipsisWidth - w) + int skip = width + ellipsisWidth - w; + for (; i < s.size() && skip > 0; ++i) { + skip -= getCharWidth(s[i]); + } + + // Append the remaining chars, if any + for (; i < s.size(); ++i) { + str += s[i]; + } + + width = getStringWidth(str); + + } else { + str = s; + } + + if (align == kTextAlignCenter) + x = x + (w - width - 1)/2; + else if (align == kTextAlignRight) + x = x + w - width; + x += deltax; + + for (i = 0; i < str.size(); ++i) { + w = getCharWidth(str[i]); + if (x+w > rightX) + break; + if (x >= leftX) + drawChar(dst, str[i], x, y, color); + x += w; + } +} + + +} // End of namespace Graphics |