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