From a382a425a9fd6fe43d91f508ff9545b2e18821ba Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Thu, 12 May 2011 02:10:40 +0200 Subject: [PATCH] ASFont: access font pixels efficiently. Previous commit ensures that the font surface is always 32 bpp. Therefore we can read font pixels directly through a pointer. --- src/asfont.cpp | 99 ++++++++++++++++++++------------------------------ src/asfont.h | 1 - 2 files changed, 39 insertions(+), 61 deletions(-) diff --git a/src/asfont.cpp b/src/asfont.cpp index 9f0f429..25dec70 100644 --- a/src/asfont.cpp +++ b/src/asfont.cpp @@ -8,39 +8,6 @@ #define SFONTPLUS_CHARSET "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~¡¿ÀÁÈÉÌÍÒÓÙÚÝÄËÏÖÜŸÂÊÎÔÛÅÃÕÑÆÇČĎĚĽĹŇÔŘŔŠŤŮŽàáèéìíòóùúýäëïöüÿâêîôûåãõñæçčďěľĺňôřŕšťžůðßÐÞþАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюяØøąćęłńśżźĄĆĘŁŃŚŻŹ" -Uint32 ASFont::getPixel(Sint32 x, Sint32 y) { - assert(x>=0); - assert(xw); - assert(y>=0); - assert(yh); - - Uint32 Bpp = surface->format->BytesPerPixel; - - // Get the pixel - switch(Bpp) { - case 1: - return *((Uint8 *)surface->pixels + y * surface->pitch + x); - break; - case 2: - return *((Uint16 *)surface->pixels + y * surface->pitch/2 + x); - break; - case 3: { // Format/endian independent - Uint8 *bits = ((Uint8 *)surface->pixels)+y*surface->pitch+x*Bpp; - Uint8 r, g, b; - r = *((bits)+surface->format->Rshift/8); - g = *((bits)+surface->format->Gshift/8); - b = *((bits)+surface->format->Bshift/8); - return SDL_MapRGB(surface->format, r, g, b); - } - break; - case 4: - return *((Uint32 *)surface->pixels + y * surface->pitch/4 + x); - break; - } - - return 0; -} - ASFont::ASFont(const std::string &fontImagePath) : characters(SFONTPLUS_CHARSET) { @@ -73,41 +40,53 @@ ASFont::ASFont(const std::string &fontImagePath) surface = SDL_ConvertSurface(buf, &format32, SDL_SRCALPHA); SDL_FreeSurface(buf); } + assert(surface->format->BytesPerPixel == 4); - Uint32 pink = SDL_MapRGB(surface->format, 255,0,255); - unsigned c = 0; SDL_LockSurface(surface); - for (unsigned x=0; x<(unsigned)surface->w && cformat, 255, 0, 255); + Uint32 *topLine = static_cast(surface->pixels); + const unsigned width = surface->w; + unsigned x = 0; + unsigned c = 0; + while (c < characters.length()) { + while (x < width && topLine[x] != pink) x++; + unsigned startx = x; + x++; + while (x < width && topLine[x] == pink) x++; + + charpos.push_back(startx); + charpos.push_back(x); + if (c > 0 && utf8Code(characters[c - 1])) { + // UTF8 character + charpos.push_back(startx); charpos.push_back(x); - - x++; - while (x<(unsigned)surface->w && getPixel(x,0) == pink) x++; - charpos.push_back(x); - - //utf8 characters - if (c>0 && utf8Code(characters[c-1])) { - charpos.push_back(startx); - charpos.push_back(x); - c++; - } - c++; } + c++; } - SDL_UnlockSurface(surface); - Uint32 colKey = getPixel(0,surface->h-1); - std::string::size_type pos = characters.find("0")*2; - SDL_Rect srcrect = {charpos[pos], 1, charpos[pos+2] - charpos[pos], surface->h - 1}; + + // Scan height of "0" glyph. + std::string::size_type pos = characters.find("0") * 2; + SDL_Rect srcrect = { + charpos[pos], 1, charpos[pos + 2] - charpos[pos], surface->h - 1 + }; + const unsigned alphaMask = surface->format->Amask; unsigned y = srcrect.h; - bool nonKeyFound = false; - while (y-- > 0 && !nonKeyFound) { - unsigned x = srcrect.w; - while (x-- > 0 && !nonKeyFound) - nonKeyFound = getPixel(x+srcrect.x,y+srcrect.y) != colKey; + bool nonTransparentFound = false; + while (!nonTransparentFound && y-- > 0) { + Uint32 *line = reinterpret_cast( + reinterpret_cast(surface->pixels) + + (srcrect.y + y) * surface->pitch + ); + for (unsigned x = 0; !nonTransparentFound && x < srcrect.w; x++) { + nonTransparentFound = (line[srcrect.x + x] & alphaMask) != 0; + } } - lineHeight = y+1; + lineHeight = y + 1; + + SDL_UnlockSurface(surface); } ASFont::~ASFont() { diff --git a/src/asfont.h b/src/asfont.h index 4e30cdc..850ab20 100644 --- a/src/asfont.h +++ b/src/asfont.h @@ -35,7 +35,6 @@ public: void write(Surface* surface, const std::string& text, int x, int y, HAlign halign = HAlignLeft, VAlign valign = VAlignTop); private: - Uint32 getPixel(Sint32 x, Sint32 y); void write(SDL_Surface *surface, const std::string &text, int x, int y); void write(SDL_Surface *surface, const std::string &text, int x, int y, HAlign halign); void write(SDL_Surface *surface, const std::string &text, int x, int y, HAlign halign, VAlign valign);