Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

XFuPrinter.cpp

Go to the documentation of this file.
00001 /*! \file
00002  * X-Forge Util <br>
00003  * Copyright 2000-2003 Fathammer Ltd
00004  *
00005  * \brief Primitive bitmap font printer class.
00006  * Needs some work (create instead of init; gl sprites instead
00007  * of the glsurface drawing currently in use.
00008  *
00009  * $Id: XFuPrinter.cpp,v 1.30 2003/08/12 13:34:08 lars Exp $
00010  * $Date: 2003/08/12 13:34:08 $
00011  * $Revision: 1.30 $
00012  */
00013 
00014 #include <stdlib.h>
00015 #include <xfcore/XFcCore.h>
00016 #include <xfutil/XFuPrinter.h>
00017 #include <xfcore/XFcPixelConverter.h>
00018 
00019 #define TORGB16(r,g,b) (unsigned short)(((((r) >> 3) & 0x1f) << 11) | ((((g) >> 3) & 0x1f) << 6) | ((((b) >> 3) & 0x1f)))
00020 
00021 XFuPrinter * XFuPrinter::create(const CHAR *aFname)
00022 {
00023     return create(aFname,0,REALi(1),REALi(1));
00024 }
00025 
00026 XFuPrinter * XFuPrinter::create(const CHAR *aFname, INT32 aAlphamask)
00027 {
00028     return create(aFname,aAlphamask,REALi(1),REALi(1));
00029 }
00030 
00031 XFuPrinter * XFuPrinter::create(const CHAR *aFname, INT32 aAlphamask, REAL aXScale, REAL aYScale)
00032 {
00033     INT32 wid, ht;
00034     UINT8 *pal;
00035     UINT16 *pal16;
00036     UINT8 *pic;
00037     INT32 i;
00038     INT paletted;
00039 
00040     UINT16 alphamask = (UINT16)(XFCPC_X888_TO_55X5(aAlphamask));
00041 
00042     XFcImageLoader::loadImageInfo(aFname, &wid, &ht, NULL, &paletted);
00043 
00044     if (!paletted) return NULL; // TODO: create non-paletted version too
00045     if (wid == 0) return NULL;
00046 
00047     XFcImageLoader::loadImagePaletted(aFname, &pal, &pic);
00048     if (pal == NULL || pic == NULL)
00049     {
00050         delete[] pic;
00051         delete[] pal;
00052         return NULL;
00053     }
00054 
00055     pal16 = new UINT16[256];
00056     for (i = 0; i < 256; ++i)
00057         pal16[i] = TORGB16(pal[i * 3 + 0], pal[i * 3 + 1], pal[i * 3 + 2]);
00058 
00059     XFuPrinter *p = new XFuPrinter();
00060 
00061     p->mLetterSpacing = 2; // default letter spacing
00062 
00063     p->mMaxletter = ht / wid;
00064     p->mLetter = new XFcGLSurface *[p->mMaxletter];
00065     for (i = 0; i < p->mMaxletter; ++i)
00066     {
00067         INT32 j, l;
00068         int letterofs = i * wid * wid;
00069         INT32 ls = wid, rs = 0;
00070         for (j = 0, l = 0; j < wid; ++j)
00071         {
00072             INT32 k;
00073             for (k = 0; k < wid; ++k, ++l)
00074             {
00075                 int c = pal16[pic[letterofs + l] & 0xff];
00076                 if (c == alphamask)
00077                 {
00078                 }
00079                 else
00080                 {
00081                     if (rs < k) rs = k;
00082                     if (ls > k) ls = k;
00083                 }
00084             }
00085         }
00086         int charwid = rs - ls + 1;
00087         if (charwid < 0)
00088         {
00089             charwid = 0; // empty character
00090             p->mLetter[i] = NULL;
00091         }
00092         else
00093         {
00094             XFcGLSurface *tSurface;
00095             tSurface = XFcGLSurface::create(charwid, wid);
00096             short *fb;
00097             tSurface->lock((void **)&fb);
00098             rs = wid - charwid;
00099             int m = 0, k;
00100             for (j = 0, l = ls; j < wid; ++j, l += rs)
00101             {
00102                 for (k = 0; k < charwid; ++k,++l,++m)
00103                 {
00104                     int c = pal16[pic[letterofs + l] & 0xff];
00105                     fb[m] = (INT16)c;
00106                 }
00107             }
00108             tSurface->unlock();
00109 
00110             if (aXScale != REALi(1) || aYScale != REALi(1))
00111             {
00112                 INT32 w = (INT32)(aXScale * (REAL)charwid);
00113                 INT32 h = (INT32)(aYScale * (REAL)wid);
00114                 XFcGLSurface *tSurface2 = XFcGLSurface::create(w,h);
00115                 if (tSurface2)
00116                 {
00117                     tSurface2->drawImage(tSurface,0,0,w,h);
00118                     delete tSurface;
00119                     tSurface = tSurface2;
00120                 }
00121             }
00122 
00123             p->mLetter[i] = tSurface;
00124             p->mLetter[i]->setColorKey(aAlphamask);
00125             p->mLetter[i]->enableColorKey(1);
00126         }
00127     }
00128 
00129     p->mLineSpacing = (INT32)(aXScale * (REAL)wid);
00130     p->mLineHeight = (INT32)(aYScale * (REAL)wid);
00131 
00132     if (p->mLetter['0' - 33])
00133         p->mSpaceWidth = p->mLetter['0' - 33]->getWidth() / 2;
00134     else
00135         p->mSpaceWidth = p->mLineHeight / 2;
00136 
00137     delete[] pic;
00138     delete[] pal;
00139     delete[] pal16;
00140     return p;
00141 
00142 }
00143 
00144 
00145 INT32 XFuPrinter::print(XFcGLSurface *aTarget, XFcRectangle *aTargetRect, const CHAR *aText,
00146                         INT32 aBlendType, INT32 aBlendValue, XFcRectangle *aClipRect)
00147 {
00148     XFCASSERT(aTarget);
00149 
00150     XFcRectangle rect;
00151 
00152     if (aTargetRect == NULL)
00153     {
00154         rect.mX = 0;
00155         rect.mY = 0;
00156         rect.mWidth = aTarget->getWidth();
00157         rect.mHeight = aTarget->getHeight();
00158     }
00159     else
00160     {
00161         rect = *aTargetRect;
00162     }
00163 
00164     // Find longest word
00165     INT32 i, j, longest = 0;
00166     i = 0;
00167     j = 0;
00168     while (aText[i] != 0)
00169     {
00170         i++;
00171         j++;
00172         if (aText[i] == ' ')
00173         {
00174             if (longest < j)
00175                 longest = j;
00176             j = 0;
00177         }
00178     }
00179 
00180     if (longest < j)
00181         longest = j;
00182 
00183     CHAR * temp = new CHAR[longest + 1];
00184 
00185     if (temp == NULL)
00186         return 0;
00187     
00188     INT32 ofsx, ofsy;
00189     ofsx = rect.mX;
00190     ofsy = rect.mY;
00191     i = 0;
00192     do
00193     {
00194         if (aText[i] == ' ')
00195         {
00196             // Only advance cursor if not at the start of line.
00197             if (ofsx != rect.mX)
00198             {
00199                 ofsx += mSpaceWidth + mLetterSpacing;
00200             }
00201             i++;
00202         }
00203         else if (aText[i] == '\n')
00204         {
00205             ofsx = rect.mX;
00206             ofsy += mLineSpacing;
00207             i++;
00208         }
00209         else
00210         {
00211             j = 0;
00212             while (aText[i] != 0 && aText[i] != ' ' && aText[i] != '\n')
00213             {
00214                 temp[j] = aText[i];
00215                 i++;
00216                 j++;
00217             }
00218             temp[j] = 0;
00219 
00220             INT32 tx, ty;
00221             stringMetrics(temp, tx, ty);
00222 
00223             if (tx + ofsx > (rect.mX + rect.mWidth) && ofsx != rect.mX)
00224             {
00225                 ofsx = rect.mX;
00226                 ofsy += mLineSpacing;
00227             }
00228 
00229             print(aTarget, ofsx, ofsy, temp, aBlendType, aBlendValue, aClipRect);
00230 
00231             ofsx += tx;
00232         }
00233 
00234     }
00235     while (aText[i] != 0);
00236 
00237     delete[] temp;
00238     
00239     return ofsy - rect.mY + mLineHeight;
00240 }
00241 
00242 
00243 void XFuPrinter::print(XFcGLSurface *aTarget, INT32 aX, INT32 aY, const CHAR *aText,
00244                        INT32 aBlendType, INT32 aBlendValue, XFcRectangle *aClipRect)
00245 {
00246     if ((aTarget != NULL) && (aText != NULL))
00247     {
00248         unsigned char *p = (unsigned char *)aText;
00249         int xo = 0;
00250         INT32 i;
00251 
00252         INT32 yMax = 0, xMax = 0;
00253         INT32 h = mLineHeight;
00254 
00255         if (aClipRect)
00256         {
00257             yMax = aClipRect->mY + aClipRect->mHeight;
00258             xMax = aClipRect->mX + aClipRect->mWidth;
00259         }
00260 
00261         while (*p)
00262         {
00263             if (*p == 32)
00264             {
00265                 xo += mSpaceWidth + mLetterSpacing;
00266             }
00267             else
00268             {
00269                 if (*p == '\n')
00270                 {
00271                     xo = 0;
00272                     aY += mLineSpacing;
00273                 }
00274                 else
00275                 {
00276                     i = ((UINT8)*p) - 33;
00277                     if (i >= 0 && i < mMaxletter)
00278                     {
00279                         if (mLetter[i] != NULL)
00280                         {
00281                             INT32 w = mLetter[i]->getWidth();
00282                             INT32 xp = aX + xo;
00283                             if (aClipRect == NULL)
00284                             {
00285                                 aTarget->drawImageBlend(
00286                                     mLetter[i], xp, aY,
00287                                     aBlendType, aBlendValue);
00288                             }
00289                             else
00290                             {
00291                                 XFcRectangle srcRect;
00292                                 srcRect.mX = aClipRect->mX - xp;
00293                                 srcRect.mY = aClipRect->mY - aY;
00294                                 INT32 endX = xMax - xp;
00295                                 INT32 endY = yMax - aY;
00296 
00297                                 if (srcRect.mX < w && endX >= 0 &&
00298                                     srcRect.mY < h && endY >= 0)
00299                                 {
00300                                     if (srcRect.mX < 0) srcRect.mX = 0;
00301                                     if (srcRect.mY < 0) srcRect.mY = 0;
00302                                     if (endX > w) endX = w;
00303                                     if (endY > h) endY = h;
00304                                     srcRect.mWidth = endX - srcRect.mX;
00305                                     srcRect.mHeight = endY - srcRect.mY;
00306                                     aTarget->drawImageBlend(
00307                                         mLetter[i], xp + srcRect.mX, aY + srcRect.mY, srcRect,
00308                                         aBlendType, aBlendValue);
00309                                 }
00310                             }
00311                             xo += w;
00312                         }
00313                         xo += mLetterSpacing;
00314                     }
00315                 }
00316             }
00317             ++p;
00318         }
00319     }
00320 }
00321 
00322 
00323 void XFuPrinter::stringMetrics(const CHAR *aText, INT32 &aWidth, INT32 &aHeight)
00324 {
00325     if (this == NULL) return;
00326     unsigned char *p = (unsigned char *)aText;
00327     int xo = 0, y = 0;
00328     int maxx = 0;
00329     INT32 i;
00330     while (*p)
00331     {
00332         if (*p == 32)
00333         {
00334             xo += mSpaceWidth;
00335             if (maxx < xo) maxx = xo;
00336             xo += mLetterSpacing;
00337         }
00338         else
00339         {
00340             if (*p == '\n')
00341             {
00342                 xo = 0;
00343                 y += mLineSpacing;
00344             }
00345             else
00346             {
00347                 i = ((UINT8)*p) - 33;
00348                 if ( i >= 0 && i < mMaxletter )
00349                 {
00350                     if (mLetter[i])
00351                         xo += mLetter[i]->getWidth();
00352                     if (maxx < xo) maxx = xo;
00353                     xo += mLetterSpacing;
00354                 }
00355             }
00356         }
00357 
00358         ++p;
00359 
00360     }
00361     y += mLineHeight;
00362     aHeight = y;
00363     aWidth = maxx;
00364 }
00365 
00366 
00367 INT32 XFuPrinter:: getCharWidth(CHAR aChar)
00368 {
00369     INT32 i = (INT32)(((UINT8)aChar) - 33);
00370     if (aChar == 32)
00371         return mSpaceWidth;
00372     else if (i < 0 || i >= mMaxletter || mLetter[i] == NULL)
00373         return 0;
00374     else
00375         return mLetter[i]->getWidth();
00376 }
00377 
00378 
00379 void XFuPrinter::setLetterSpacing(INT32 aSpacing)
00380 {
00381     mLetterSpacing = aSpacing;
00382 }
00383 
00384 
00385 INT32 XFuPrinter::getLetterSpacing()
00386 {
00387     return mLetterSpacing;
00388 }
00389 
00390 
00391 void XFuPrinter::setLineSpacing(INT32 aSpacing)
00392 {
00393     mLineSpacing = aSpacing;
00394 }
00395 
00396 
00397 INT32 XFuPrinter::getLineSpacing()
00398 {
00399     return mLineSpacing;
00400 }
00401 
00402 
00403 INT32 XFuPrinter::getLineHeight()
00404 {
00405     return mLineHeight;
00406 }
00407 
00408 
00409 void XFuPrinter::setSpaceWidth(INT32 aSpacing)
00410 {
00411     mSpaceWidth = aSpacing;
00412 }
00413 
00414 
00415 XFuPrinter::~XFuPrinter()
00416 {
00417     int i;
00418     if (mLetter)
00419     {
00420         for (i = 0; i < mMaxletter; ++i)
00421             delete mLetter[i];
00422     }
00423     delete[] mLetter;
00424 }
00425 
00426 
00427 XFuPrinter::XFuPrinter()
00428 {
00429     mLetter = NULL;
00430 }
00431 

   
X-Forge Documentation
Confidential
Copyright © 2002-2003 Fathammer
   
Documentation generated
with doxygen
by Dimitri van Heesch