⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 util.cpp

📁 上面上传的autotools一文(也就是《使用GNU autotools 改造一个软件项目》)配套的示例程序源代码。
💻 CPP
字号:
//
// Copyright (c) 2005, Wei Mingzhi <whistler@openoffice.org>
// Portions Copyright (c) 2001, Gregory Velichansky <hmaon@bumba.net>
// All Rights Reserved.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA
// 02110-1301, USA
//

#include "main.h"

void trim(char *str)
{
   int pos = 0;
   char *dest = str;

   // skip leading blanks
   while (str[pos] <= ' ' && str[pos] > 0)
      pos++;

   while (str[pos]) {
      *(dest++) = str[pos];
      pos++;
   }

   *(dest--) = '\0'; // store the null

   // remove trailing blanks
   while (dest >= str && *dest <= ' ' && *dest > 0)
      *(dest--) = '\0';
}

// Does a varargs printf into a temp buffer, so we don't need to have
// varargs versions of all text functions.
char *va(const char *format, ...)
{
   static char string[256];
   va_list     argptr;

   va_start(argptr, format);
   vsnprintf(string, 256, format, argptr);
   va_end(argptr);

   return string;
}

static long glSeed = 0, glGen2 = 0, glGen1 = 0; // our random number generator's seed

// This function initializes the random seed based on the initial seed value passed in the
// initial_seed parameter.
static void lsrand(unsigned long initial_seed)
{
   // Pick two large integers such that one is double the other
   glGen2 = 3719;
   glGen1 = glGen2 / 2;

   // fill in the initial seed of the random number generator
   glSeed = (glGen1 * initial_seed) + glGen2;
}

// This function is the equivalent of the rand() standard C library function, except that
// whereas rand() works only with short integers (i.e. not above 32767), this function is
// able to generate 32-bit random numbers. Isn't that nice?
static long lrand(void)
{
   if (glSeed == 0) // if the random seed isn't initialized...
      lsrand(time(NULL)); // initialize it first
   glSeed = (glGen1 * glSeed) + glGen2; // do some twisted math
   return (glSeed > 0) ? glSeed : -glSeed; // and return absolute value of the result
}

// This function returns a random integer number between (and including) the starting and
// ending values passed by parameters from and to.
long RandomLong(long from, long to)
{
   if (to <= from)
      return from;

   return from + lrand() / (LONG_MAX / (to - from + 1));
}

// This function returns a random floating-point number between (and including) the starting
// and ending values passed by parameters from and to.
float RandomFloat(float from, float to)
{
   if (to <= from)
      return from;

   return from + (float)lrand() / (LONG_MAX / (to - from));
}

int log2(int val)
{
   int answer = 0;

   while ((val >>= 1) != 0) {
      answer++;
   }

   return answer;
}

// This function terminates the game because of an error and
// prints the message string pointed to by fmt both in the
// console and in a messagebox.
void TerminateOnError(const char *fmt, ...)
{
   va_list argptr;
   char string[256];

   // concatenate all the arguments in one string
   va_start(argptr, fmt);
   vsnprintf(string, sizeof(string), fmt, argptr);
   va_end(argptr);

   fprintf(stderr, "\nFATAL ERROR: %s\n", string);

#ifdef _WIN32
   MessageBox(0, string, "ERROR", MB_ICONERROR);
#endif

   assert(!"TerminateOnError()"); // allows jumping to debugger
   exit(1);
}

char *UTIL_StrGetLine(const char *buf, int width, int &length)
{
   int w = 0, i, index = 0;
   static char str[256];

   str[0] = '\0';
   length = 0;

   while (buf != NULL && *buf != '\0' && (*buf == '\r' || *buf == '\n')) {
      buf++;
      length++;
   }

   while (buf != NULL && *buf != '\0') {
      if (w >= width) {
         break;
      }
      if ((unsigned char)*buf >= 0x7f) {
         if (strlen(buf) < 3 || w + 2 > width) {
            break;
         }
         for (i = 0; i < 3 && *buf; i++) {
            str[index++] = *buf++;
            length++;


         }
         w += 2;
      } else if (*buf == '\r' || *buf == '\n') {
         break;
      } else {
         str[index++] = *buf++;
         length++;
         w++;
      }
   }

   str[index] = '\0';
   return str;
}

//-------------------------------------------------------------

// Return the pixel value at (x, y)
// NOTE: The surface must be locked before calling this!
unsigned long UTIL_GetPixel(SDL_Surface *surface, int x, int y)
{
   int bpp = surface->format->BytesPerPixel;

   // Here p is the address to the pixel we want to retrieve
   unsigned char *p = (unsigned char *)surface->pixels + y * surface->pitch + x * bpp;

   switch (bpp) {
      case 1:
         return *p;

      case 2:
         return *(unsigned short *)p;

      case 3:
         if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
            return p[0] << 16 | p[1] << 8 | p[2];
         else
            return p[0] | p[1] << 8 | p[2] << 16;

      case 4:
         return *(unsigned long *)p;
   }

   return 0; // shouldn't happen, but avoids warnings
}

// Set the pixel at (x, y) to the given value
// NOTE: The surface must be locked before calling this!
void UTIL_PutPixel(SDL_Surface *surface, int x, int y, unsigned long pixel)
{
   int bpp = surface->format->BytesPerPixel;

   // Here p is the address to the pixel we want to set
   unsigned char *p = (unsigned char *)surface->pixels + y * surface->pitch + x * bpp;

   switch (bpp) {
      case 1:
         *p = pixel;
         break;


      case 2:
         *(unsigned short *)p = pixel;
         break;

      case 3:
         if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
             p[0] = (pixel >> 16) & 0xff;
             p[1] = (pixel >> 8) & 0xff;
             p[2] = pixel & 0xff;
         } else {
             p[0] = pixel & 0xff;
             p[1] = (pixel >> 8) & 0xff;
             p[2] = (pixel >> 16) & 0xff;
         }
         break;

     case 4:
        *(unsigned long *)p = pixel;
        break;
   }

}

void UTIL_RevertSurfaceX(SDL_Surface *s)
{
   unsigned long temp;
   bool locked = false;

   if (SDL_MUSTLOCK(s)) {
      SDL_LockSurface(s);
      locked = true;
   }

   for (int i = 0; i < s->h; i++) {
      for (int j = 0; j < s->w / 2; j++) {
         temp = UTIL_GetPixel(s, j, i);
         UTIL_PutPixel(s, j, i, UTIL_GetPixel(s, s->w - j - 1, i));
         UTIL_PutPixel(s, s->w - j - 1, i, temp);
      }
   }

   if (locked)
      SDL_UnlockSurface(s);
}

void UTIL_RevertSurfaceY(SDL_Surface *s)
{
   unsigned long temp;
   bool locked = false;

   if (SDL_MUSTLOCK(s)) {
      SDL_LockSurface(s);
      locked = true;
   }

   for (int i = 0; i < s->h / 2; i++) {
      for (int j = 0; j < s->w; j++) {
         temp = UTIL_GetPixel(s, j, i);
         UTIL_PutPixel(s, j, i, UTIL_GetPixel(s, j, s->h - i - 1));
         UTIL_PutPixel(s, j, s->h - i - 1, temp);
      }
   }

   if (locked)
      SDL_UnlockSurface(s);
}

void UTIL_RevertSurfaceXY(SDL_Surface *s)
{
   UTIL_RevertSurfaceX(s);
   UTIL_RevertSurfaceY(s);
}

int UTIL_GetPixel(SDL_Surface *f, int x, int y,
   unsigned char *r, unsigned char *g, unsigned char *b)
{
   unsigned long pixel;
   unsigned char *pp;

   int n; /* general purpose 'n'. */

   if (f == NULL)
      return -1;

   pp = (unsigned char *)f->pixels;

   if (x >= f->w || y >= f->h)
      return -1;

   pp += (f->pitch * y);
   pp += (x * f->format->BytesPerPixel);

   // we do not lock the surface here, it would be inefficient XXX
   // this reads the pixel as though it was a big-endian integer XXX
   // I'm trying to avoid reading part the end of the pixel data by
   // using a data-type that's larger than the pixels
   for (n = 0, pixel = 0; n < f->format->BytesPerPixel; ++n, ++pp) {
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
      pixel >>= 8;
      pixel |= *pp << (f->format->BitsPerPixel - 8);
#else
      pixel |= *pp;
      pixel <<= 8;
#endif
   }

   SDL_GetRGB(pixel, f->format, r, g, b);
   return 0;
}

int UTIL_PutPixel(SDL_Surface *f, int x, int y,
   unsigned char r, unsigned char g, unsigned char b)
{
   unsigned long pixel;
   unsigned char *pp;

   int n;

   if (f == NULL)
      return -1;

   pp = (unsigned char *)f->pixels;

   if (x >= f->w || y >= f->h)
      return -1;

   pp += (f->pitch * y);
   pp += (x * f->format->BytesPerPixel);

   pixel = SDL_MapRGB(f->format, r, g, b);

   for (n = 0; n < f->format->BytesPerPixel; ++n, ++pp) {
      *pp = (unsigned char)(pixel & 0xFF);
      pixel >>= 8;
   }

   return 0;
}

inline unsigned long ifloor(unsigned long i)
{
   return (i & 0xFFFF0000);
}

inline unsigned long iceil(unsigned long i)
{
   return (i & 0xFFFF) ? i : ifloor(i) + (1<<16);
}

int UTIL_ScaleBlit(SDL_Surface *src, SDL_Rect *sr, SDL_Surface *dst, SDL_Rect *dr)
{
   // This function is based on work done by Gregory Velichansky.

   unsigned char r, g, b;
   unsigned long rs, gs, bs; // sums.

   // temp storage for large int multiplies. Uint64 doen't exist anywhere
   double farea;
   unsigned long area;

   unsigned long sx, sy;
   unsigned long dsx, dsy;

   unsigned long wsx, wsy;

   unsigned long x, y; // x and y, for sub-area

   unsigned long tx, ty; // normal integers
   unsigned long lx, ly; // normal integers

   unsigned long w, e, n, s; // temp variables, named after compass directions

   bool locked = false;

   if (src == NULL || sr == NULL || dst == NULL || dr == NULL)
      return -1;

   if (!dr->w || !dr->h)
      return -1;

   if (SDL_MUSTLOCK(dst)) {
      SDL_LockSurface(dst);
      locked = true;
   }

   wsx = dsx = (sr->w << 16) / dr->w;
   if (!(wsx & 0xFFFF0000))
      wsx = 1 << 16;
   wsy = dsy = (sr->h << 16) / dr->h;
   if (!(wsy & 0xFFFF0000))
      wsy = 1 << 16;

   lx = dr->x + dr->w;
   ly = dr->y + dr->h;

   // lazy multiplication. Hey, it's only once per blit.
   farea = ((double)wsx) * ((double)wsy);
   farea /= (double)(1 << 16);
   area = (unsigned long)farea;

   for (ty = dr->y, sy = sr->y << 16; ty < ly; ++ty, sy += dsy) {
      for (tx = dr->x, sx = sr->x << 16; tx < lx; ++tx, sx += dsx) {
         rs = gs = bs = 0;
         for (y = ifloor(sy); iceil(sy + wsy) > y; y += (1<<16)) {
            for (x = ifloor(sx); iceil(sx + wsx) > x; x += (1<<16)) {
               w = (x > sx) ? 0 : sx - x;
               n = (y > sy) ? 0 : sy - y;

               e = (sx + wsx >= x + (1 << 16)) ? (1 << 16) : sx + wsx - x;
               s = (sy + wsy >= y + (1 << 16)) ? (1 << 16) : sy + wsy - y;

               if (w > e || s < n)
                  continue;

#define gsx ((int)(x >> 16) >= sr->x+sr->w ? sr->x+sr->w-1 : x >> 16)
#define gsy ((int)(y >> 16) >= sr->y+sr->h ? sr->y+sr->h-1 : y >> 16)

               UTIL_GetPixel(src, gsx, gsy, &r, &g, &b);

               rs += ((e - w) >> 8) * ((s - n)>>8) * r;
               gs += ((e - w) >> 8) * ((s - n)>>8) * g;
               bs += ((e - w) >> 8) * ((s - n)>>8) * b;
            }
         }


         rs /= area;
         gs /= area;
         bs /= area;

         if (rs >= 256 || gs >= 256 || bs >= 256) {
            fprintf(stderr, "fixed point weighted average overflow!");
            fprintf(stderr, "Values: %d, %d, %d\n", rs, gs, bs);
         }

         r = (unsigned char)rs;
         g = (unsigned char)gs;
         b = (unsigned char)bs;

         UTIL_PutPixel(dst, tx, ty, r, g, b);
      }
   }

   if (locked) {
      SDL_UnlockSurface(dst);
   }

   return 0;
#undef gsx
#undef gsy
}

SDL_Surface *UTIL_ScaleSurface(SDL_Surface *s, int w, int h)
{
   SDL_Surface *r = SDL_CreateRGBSurface(s->flags,
      w, h, s->format->BitsPerPixel, s->format->Rmask,
      s->format->Gmask, s->format->Bmask,
      s->format->Amask);

   SDL_Rect dstrect, dstrect2;

   dstrect.x = 0;
   dstrect.y = 0;
   dstrect.w = w;
   dstrect.h = h;

   dstrect2.x = 0;
   dstrect2.y = 0;
   dstrect2.w = s->w;
   dstrect2.h = s->h;

   UTIL_ScaleBlit(s, &dstrect2, r, &dstrect);
   return r;
}

SDL_Surface *UTIL_GrayStyle(SDL_Surface *s)
{
   SDL_Surface *t = SDL_CreateRGBSurface(s->flags,
      s->w, s->h, s->format->BitsPerPixel, s->format->Rmask,
      s->format->Gmask, s->format->Bmask,
      s->format->Amask);

   for (int i = 0; i < s->w; i++) {
      for (int j = 0; j < s->h; j++) {
         unsigned char r, g, b, n;
         int d = UTIL_GetPixel(s, i, j);
         SDL_GetRGB(d, s->format, &r, &g, &b);
         n = ((int)r + (int)g + (int)b) / 4;
         UTIL_PutPixel(t, i, j, n, n, n);
      }
   }

   return t;
}

void UTIL_Delay(int duration)
{
   unsigned int begin = SDL_GetTicks();

   while (SDL_GetTicks() - begin < (unsigned int)duration) {
      SDL_Event event;
      while (SDL_PollEvent(&event)) {
         if (event.type == SDL_KEYDOWN) {
            if (event.key.keysym.sym == SDLK_ESCAPE) {
               // Quit the program immediately if user pressed ESC
               UserQuit();
            }
            break;
         } else if (event.type == SDL_QUIT) {
            UserQuit();
         }
      }
      SDL_Delay(5);
   }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -