00001 #include "main.h"
00002
00003
00004 Gui::Gui(IRender& render, IPhysic& physic, pMouseDevice mouse, const MouseMap& mouseMap)
00005 : m_render(render), m_physic(physic), m_mouse(mouse), m_mouseMap(mouseMap)
00006 {
00007 m_numControls = 0;
00008 }
00009
00010 Gui::~Gui(void)
00011 {
00012 }
00013
00014 void Gui::update()
00015 {
00016 if(m_render.guiIsShown()) {
00017 if (m_mouse->isDown(m_mouseMap.mouseL)) {
00018 int mouseX = m_mouse->getScreenX();
00019 int mouseY = m_mouse->getScreenY();
00020 for(int i = 0; i < m_numControls; i++) {
00021 m_controls[i]->hitTest(mouseX, mouseY);
00022 }
00023 }
00024 }
00025 }
00026
00027 void Gui::addControl(pIControl control)
00028 {
00029 m_controls.push_back(control);
00030 m_numControls++;
00031
00032 m_render.createGuiDrawCall(control);
00033 }
00034
00035 void Gui::setGuiTexture(wchar* textureColor)
00036 {
00037 TextureData textureData;
00038
00039 if(!loadTextureData(textureColor, textureColor, textureColor, textureData)) {
00040 printf("Can't load texture data");
00041 exit(0xff);
00042 }
00043
00044 m_guiTexture = m_render.createTexture(textureData);
00045 }
00046
00047 pIControl Gui::createLabel(float x, float y, float width, float height, int textureIndex)
00048 {
00049
00050
00051 MeshData meshData;
00052 float uvX1 = 1.0f, uvX2 = 1.0f;
00053 float uvY1 = 1.0f, uvY2 = 1.0f;
00054 if(textureIndex < 6) {
00055 uvX1 = (float)(textureIndex % 2) * (256.0f / 512.0f);
00056 uvX2 = uvX1 + (256.0f / 512.0f);
00057 uvY1 = 1.0f - (float)(textureIndex / 2) * (128.0f / 512.0f);
00058 uvY2 = uvY1 - (128.0f / 512.0f);
00059 } else if(textureIndex == 10) {
00060 uvX1 = 16.0f / 512.0f;
00061 uvX2 = 32.0f / 512.0f;
00062 uvY1 = 1.0f - 3 * (128.0f / 512.0f);
00063 uvY2 = uvY1 - (32.0f / 512.0f);
00064 } else if(textureIndex == 98) {
00065 uvX1 = 0.0f;
00066 uvX2 = 176.0f / 512.0f;
00067 uvY1 = 1.0f - 3 * (128.0f / 512.0f) - (32.0f / 512.0f);
00068 uvY2 = uvY1 - (32.0f / 512.0f);
00069 } else if(textureIndex == 99) {
00070 uvX1 = 0.0f;
00071 uvX2 = 15.0f / 512.0f;
00072 uvY1 = 1.0f - 3 * (128.0f / 512.0f);
00073 uvY2 = uvY1 - (31.0f / 512.0f);
00074 } else if(textureIndex == 100) {
00075 uvX1 = 0.0f;
00076 uvX2 = 80.0f / 512.0f;
00077 uvY1 = 64.0f / 512.0f;
00078 uvY2 = 32.0f / 512.0f;
00079 } else if(textureIndex == 101) {
00080 uvX1 = 0.0f;
00081 uvX2 = 96.0f / 512.0f;
00082 uvY1 = 32.0f / 512.0f;
00083 uvY2 = 0.0f;
00084 } else if(textureIndex = 102) {
00085 uvX1 = 0.5;
00086 uvX2 = 1.0f;
00087 uvY1 = 64.0f / 512.0f;
00088 uvY2 = 0.0f;
00089 } else if(textureIndex > 199) {
00090 int iconIndex = textureIndex - 200;
00091 uvX1 = 0.5 + ((float)(iconIndex % 4) * (64.0f / 512.0f));
00092 uvX2 = uvX1 + 64.0f / 512.0f;
00093 uvY1 = 0.5f - ((int)(iconIndex / 4)) * (64.0f / 512.0f);
00094 uvY2 = uvY1 - 64.0f / 512.0f;
00095 }
00096
00097 void* memory = malloc(sizeof(Vertex) * 4 + sizeof(ushort) * 6);
00098 Vertex* vertices = (Vertex*)memory;
00099 ushort* indices = (ushort*)&vertices[4];
00100
00101
00102 vertices[0].position[0] = x; vertices[0].position[1] = y;
00103 vertices[0].position[2] = -1.0f; vertices[0].position[3] = 1.0f;
00104 vertices[0].color[0] = 0.0f; vertices[0].color[1] = 0.0f;
00105 vertices[0].color[2] = 0.0f; vertices[0].color[3] = 1.0f;
00106 vertices[0].uv[0] = uvX1; vertices[0].uv[1] = uvY1;
00107 vertices[0].uv[2] = 0.0f; vertices[0].uv[3] = 0.0f;
00108
00109
00110 vertices[1].position[0] = x + width; vertices[1].position[1] = y;
00111 vertices[1].position[2] = -1.0f; vertices[1].position[3] = 1.0f;
00112 vertices[1].color[0] = 0.0f; vertices[1].color[1] = 0.0f;
00113 vertices[1].color[2] = 0.0f; vertices[1].color[3] = 1.0f;
00114 vertices[1].uv[0] = uvX2; vertices[1].uv[1] = uvY1;
00115 vertices[1].uv[2] = 0.0f; vertices[1].uv[3] = 0.0f;
00116
00117
00118 vertices[2].position[0] = x + width; vertices[2].position[1] = y + height;
00119 vertices[2].position[2] = -1.0f; vertices[2].position[3] = 1.0f;
00120 vertices[2].color[0] = 0.0f; vertices[2].color[1] = 0.0f;
00121 vertices[2].color[2] = 0.0f; vertices[2].color[3] = 1.0f;
00122 vertices[2].uv[0] = uvX2; vertices[2].uv[1] = uvY2;
00123 vertices[2].uv[2] = 0.0f; vertices[2].uv[3] = 0.0f;
00124
00125
00126 vertices[3].position[0] = x; vertices[3].position[1] = y + height;
00127 vertices[3].position[2] = -1.0f; vertices[3].position[3] = 1.0f;
00128 vertices[3].color[0] = 0.0f; vertices[3].color[1] = 0.0f;
00129 vertices[3].color[2] = 0.0f; vertices[3].color[3] = 1.0f;
00130 vertices[3].uv[0] = uvX1; vertices[3].uv[1] = uvY2;
00131 vertices[3].uv[2] = 0.0f; vertices[3].uv[3] = 0.0f;
00132
00133 indices[0] = 0; indices[1] = 2;
00134 indices[2] = 1; indices[3] = 0;
00135 indices[4] = 3; indices[5] = 2;
00136
00137 meshData.vertexSize = sizeof(Vertex);
00138 meshData.vertexCount = 4;
00139 meshData.indexCount = 6;
00140 meshData.vertices = vertices;
00141 meshData.indices = indices;
00142
00143 pIGeometry geometry = m_render.createGeometry(meshData);
00144
00145 pIControl control = m_render.createControl(geometry, m_guiTexture);
00146 control->setX((int)x);
00147 control->setY((int)y);
00148 control->setWidth((int)width);
00149 control->setHeight((int)height);
00150
00151 return control;
00152
00153 }
00154
00155 pIControl Gui::createButton(float x, float y, float width, float height, void callback(pIControl), int textureIndex)
00156 {
00157
00158 MeshData meshData;
00159 float uvX1 = 1.0f, uvX2 = 1.0f;
00160 float uvY1 = 1.0f, uvY2 = 1.0f;
00161 if(textureIndex < 6) {
00162 uvX1 = (float)(textureIndex % 2) * (256.0f / 512.0f);
00163 uvX2 = uvX1 + (256.0f / 512.0f);
00164 uvY1 = 1.0f - (float)(textureIndex / 2) * (128.0f / 512.0f);
00165 uvY2 = uvY1 - (128.0f / 512.0f);
00166 }
00167
00168 void* memory = malloc(sizeof(Vertex) * 4 + sizeof(ushort) * 6);
00169 Vertex* vertices = (Vertex*)memory;
00170 ushort* indices = (ushort*)&vertices[4];
00171
00172 vertices[0].position[0] = x; vertices[0].position[1] = y;
00173 vertices[0].position[2] = -1.0f; vertices[0].position[3] = 1.0f;
00174 vertices[0].color[0] = 0.0f; vertices[0].color[1] = 0.0f;
00175 vertices[0].color[2] = 0.0f; vertices[0].color[3] = 0.0f;
00176 vertices[0].uv[0] = uvX1; vertices[0].uv[1] = uvY1;
00177 vertices[0].uv[2] = 0.0f; vertices[0].uv[3] = 0.0f;
00178
00179 vertices[1].position[0] = x + width; vertices[1].position[1] = y;
00180 vertices[1].position[2] = -1.0f; vertices[1].position[3] = 1.0f;
00181 vertices[1].color[0] = 0.0f; vertices[1].color[1] = 0.0f;
00182 vertices[1].color[2] = 0.0f; vertices[1].color[3] = 0.0f;
00183 vertices[1].uv[0] = uvX2; vertices[1].uv[1] = uvY1;
00184 vertices[1].uv[2] = 0.0f; vertices[1].uv[3] = 0.0f;
00185
00186 vertices[2].position[0] = x + width; vertices[2].position[1] = y + height;
00187 vertices[2].position[2] = -1.0f; vertices[2].position[3] = 1.0f;
00188 vertices[2].color[0] = 0.0f; vertices[2].color[1] = 0.0f;
00189 vertices[2].color[2] = 0.0f; vertices[2].color[3] = 0.0f;
00190 vertices[2].uv[0] = uvX2; vertices[2].uv[1] = uvY2;
00191 vertices[2].uv[2] = 0.0f; vertices[2].uv[3] = 0.0f;
00192
00193 vertices[3].position[0] = x; vertices[3].position[1] = y + height;
00194 vertices[3].position[2] = -1.0f; vertices[3].position[3] = 1.0f;
00195 vertices[3].color[0] = 0.0f; vertices[3].color[1] = 0.0f;
00196 vertices[3].color[2] = 0.0f; vertices[3].color[3] = 0.0f;
00197 vertices[3].uv[0] = uvX1; vertices[3].uv[1] = uvY2;
00198 vertices[3].uv[2] = 0.0f; vertices[3].uv[3] = 0.0f;
00199
00200 indices[0] = 0; indices[1] = 2;
00201 indices[2] = 1; indices[3] = 0;
00202 indices[4] = 3; indices[5] = 2;
00203
00204 meshData.vertexSize = sizeof(Vertex);
00205 meshData.vertexCount = 4;
00206 meshData.indexCount = 6;
00207 meshData.vertices = vertices;
00208 meshData.indices = indices;
00209
00210 pIGeometry geometry = m_render.createGeometry(meshData);
00211
00212 pIControl control = m_render.createButton(geometry, m_guiTexture, callback);
00213 control->setX((int)x);
00214 control->setY((int)y);
00215 control->setWidth((int)width);
00216 control->setHeight((int)height);
00217
00218 return control;
00219 }
00220
00221 void Gui::setUpStatusLabels()
00222 {
00223 for(int i = 0; i < 10; i++){
00224 m_statusLabels[i] = createLabel(10,10, 64, 64, i + 200);
00225 m_statusLabels[i]->setVisible(false);
00226 m_statusLabels[i]->setName(TEXT("HUD"));
00227 addControl(m_statusLabels[i]);
00228 }
00229
00230 m_fpsLabel[0] = createLabel(112, 10, 16, 32, 10);
00231 m_fpsLabel[1] = createLabel(96, 10, 16, 32, 10);
00232 m_fpsLabel[2] = createLabel(80, 10, 16, 32, 10);
00233
00234 for(int i = 0; i < 3; i++) {
00235 m_fpsLabel[i]->setVisible(false);
00236 m_fpsLabel[i]->setName(TEXT("HUD"));
00237 addControl(m_fpsLabel[i]);
00238 }
00239
00240 m_winnerLabel = createLabel(384, 362, 256, 64, 102);
00241 m_winnerLabel->setVisible(false);
00242 m_winnerLabel->setName(TEXT("HUD"));
00243 addControl(m_winnerLabel);
00244 }
00245
00246 void Gui::showStatusLabel(int index)
00247 {
00248 for(int i = 0; i < 10; i++) {
00249 if(i == index) m_statusLabels[i]->setVisible(true);
00250 else m_statusLabels[i]->setVisible(false);
00251 }
00252 }
00253
00254 void Gui::hideAllStatusLabels()
00255 {
00256 for(int i = 0; i < 10; i++) {
00257 m_statusLabels[i]->setVisible(false);
00258 }
00259 }
00260
00261 void Gui::showFPS()
00262 {
00263 for(int i = 0; i < 3; i++) { m_fpsLabel[i]->setVisible(true); }
00264 }
00265
00266 void Gui::hideFPS() {
00267 for(int i = 0; i <3; i++) { m_fpsLabel[i]->setVisible(false);}
00268 }
00269
00270 void Gui::setFPSValue(int fps)
00271 {
00272 for(int i = 0; i < 3; i++) {
00273 m_fpsLabel[i]->setIndex(fps % 10);
00274 fps /= 10;
00275 }
00276 }
00277
00278 bool Gui::loadTextureData(const wchar* colorFilename, const wchar* normalFilename, const wchar* heightFilename, TextureData& out)
00279 {
00280 Pixel* colorData = 0;
00281 Pixel* normalData = 0;
00282 Pixel* heightData = 0;
00283 int widthColor = 0, heightColor = 0;
00284 int widthDetail = 0, heightDetail = 0;
00285 bool ok = true;
00286
00287 ok = loadUnknown(colorFilename, widthColor, heightColor, 0);
00288 if(ok) ok = loadUnknown(colorFilename, widthColor, heightColor, &colorData);
00289 ok = loadUnknown(normalFilename, widthDetail, heightDetail, 0);
00290 if(ok) ok = loadUnknown(normalFilename, widthDetail, heightDetail, &normalData);
00291 if(ok) ok = loadUnknown(heightFilename, widthDetail, heightDetail, &heightData);
00292
00293 if(ok == false)
00294 {
00295 SAVEFREE(colorData);
00296 SAVEFREE(normalData);
00297 SAVEFREE(heightData);
00298 return false;
00299 }
00300
00301 int mipmapsColor = 0;
00302 int mipmapsDetail = 0;
00303 int mipmapPixelsColor = 0;
00304 int mipmapPixelsDetail = 0;
00305 MipMap* colorMipmaps;
00306 MipMap* detailMipmaps;
00307
00308 for(int w=widthColor; w>0; mipmapPixelsColor+=w*w, w/=2, mipmapsColor++);
00309 for(int w=widthDetail; w>0; mipmapPixelsDetail+=w*w, w/=2, mipmapsDetail++);
00310
00311 void* mem = malloc(sizeof(MipMap)*(mipmapsColor+mipmapsDetail) + sizeof(Pixel)*(mipmapPixelsColor+mipmapPixelsDetail));
00312
00313 colorMipmaps = (MipMap*)mem;
00314 detailMipmaps = &colorMipmaps[mipmapsColor];
00315 Pixel* colorPixels = (Pixel*)&detailMipmaps[mipmapsDetail];
00316 Pixel* detailPixels = &colorPixels[mipmapPixelsColor];
00317
00318 for(int i=0, w=widthColor, curPixel=0; i<mipmapsColor; curPixel+=w*w, w/=2, i++)
00319 {
00320 colorMipmaps[i].width = w;
00321 colorMipmaps[i].height = w;
00322 colorMipmaps[i].data = &colorPixels[curPixel];
00323 }
00324
00325 for(int i=0, w=widthDetail, curPixel=0; i<mipmapsDetail; curPixel+=w*w, w/=2, i++)
00326 {
00327 detailMipmaps[i].width = w;
00328 detailMipmaps[i].height = w;
00329 detailMipmaps[i].data = &detailPixels[curPixel];
00330 }
00331
00332
00333 for(int y=0; y<colorMipmaps[0].height; y++)
00334 {
00335 for(int x=0; x<colorMipmaps[0].width; x++)
00336 colorMipmaps[0].data[y*widthColor+x] = colorData[y*widthColor+x];
00337 }
00338
00339
00340 for(int i=0; i<mipmapsColor-1; i++)
00341 {
00342 for(int y=0; y<colorMipmaps[i+1].height; y++)
00343 {
00344 for(int x=0; x<colorMipmaps[i+1].width; x++)
00345 {
00346 int color[4];
00347 for(int c=0; c<4; color[c] = colorMipmaps[i].data[((y+0)* colorMipmaps[i].width + x + 0)*2].canal[c], c++);
00348 for(int c=0; c<4; color[c] += colorMipmaps[i].data[((y+0)* colorMipmaps[i].width + x + 1)*2].canal[c], c++);
00349 for(int c=0; c<4; color[c] += colorMipmaps[i].data[((y+1)* colorMipmaps[i].width + x + 0)*2].canal[c], c++);
00350 for(int c=0; c<4; color[c] += colorMipmaps[i].data[((y+1)* colorMipmaps[i].width + x + 1)*2].canal[c], c++);
00351 for(int c=0; c<4; colorMipmaps[i+1].data[y * colorMipmaps[i+1].width + x].canal[c] = uchar(color[c]/4), c++);
00352 }
00353 }
00354 }
00355
00356
00357 for(int y=0; y<detailMipmaps[0].height; y++)
00358 {
00359 for(int x=0; x<detailMipmaps[0].width; x++)
00360 {
00361 normalData[y*widthDetail+x].a = heightData[y*widthDetail+x].r;
00362 detailMipmaps[0].data[y*widthDetail+x] = normalData[y*widthDetail+x];
00363 }
00364 }
00365
00366
00367 for(int i=0; i<mipmapsDetail-1; i++)
00368 {
00369 for(int y=0; y<detailMipmaps[i].height/2; y++)
00370 {
00371 for(int x=0; x<detailMipmaps[i].width/2; x++)
00372 {
00373 int normal[4];
00374 for(int c=0; c<4; normal[c] = detailMipmaps[i].data[((y+0)* detailMipmaps[i].width + x + 0)*2].canal[c], c++);
00375 for(int c=0; c<4; normal[c] += detailMipmaps[i].data[((y+0)* detailMipmaps[i].width + x + 1)*2].canal[c], c++);
00376 for(int c=0; c<4; normal[c] += detailMipmaps[i].data[((y+1)* detailMipmaps[i].width + x + 0)*2].canal[c], c++);
00377 for(int c=0; c<4; normal[c] += detailMipmaps[i].data[((y+1)* detailMipmaps[i].width + x + 1)*2].canal[c], c++);
00378 for(int c=0; c<4; detailMipmaps[i+1].data[y * detailMipmaps[i+1].width + x].canal[c] = uchar(normal[c]/4), c++);
00379 }
00380 }
00381 }
00382
00383
00384 SAVEFREE(colorData);
00385 SAVEFREE(normalData);
00386 SAVEFREE(heightData);
00387
00388
00389 out.mipmapsColor = mipmapsColor;
00390 out.mipmapsDetail = mipmapsDetail;
00391 out.color = colorMipmaps;
00392 out.detail = detailMipmaps;
00393 return true;
00394 }
00395
00396
00397 bool Gui::loadUnknown(const wchar* filename, int& width, int& height, Pixel** outData)
00398 {
00399 bool ok = true;
00400 size_t filenameLength = wcslen(filename);
00401
00402 if(wcscmp(&filename[filenameLength-4], TEXT(".bmp")) == 0)
00403 ok = loadBMP(filename, width, height, outData);
00404
00405
00406 else
00407 return false;
00408
00409 if(outData == 0 && width != height)
00410 return false;
00411
00412 return ok;
00413 }
00414
00415 struct BMP_SIGNATURE {
00416 BMP_SIGNATURE() {
00417 this->c[0] = 'B';
00418 this->c[1] = 'M';
00419 }
00420 union {
00421 unsigned short int s;
00422 unsigned char c[2];
00423 };
00424 };
00425
00426 const BMP_SIGNATURE bmpSignature;
00427 const unsigned short int BITMAP_SIGNATURE = bmpSignature.s;
00428
00429 typedef struct {
00430 unsigned short int Signature;
00431 unsigned int Size;
00432 unsigned int Reserved;
00433 unsigned int BitsOffset;
00434 } BITMAP_FILEHEADER;
00435
00436 #define BITMAP_FILEHEADER_SIZE 14
00437
00438 typedef struct {
00439 unsigned int HeaderSize;
00440 int Width;
00441 int Height;
00442 unsigned short int Planes;
00443 unsigned short int BitCount;
00444 unsigned int Compression;
00445 unsigned int SizeImage;
00446 int PelsPerMeterX;
00447 int PelsPerMeterY;
00448 unsigned int ClrUsed;
00449 unsigned int ClrImportant;
00450 unsigned int RedMask;
00451 unsigned int GreenMask;
00452 unsigned int BlueMask;
00453 unsigned int AlphaMask;
00454 unsigned int CsType;
00455 unsigned int Endpoints[9];
00456 unsigned int GammaRed;
00457 unsigned int GammaGreen;
00458 unsigned int GammaBlue;
00459 } BITMAP_HEADER;
00460
00461 typedef struct {
00462 unsigned char Red;
00463 unsigned char Green;
00464 unsigned char Blue;
00465 unsigned char Alpha;
00466 } RGBA;
00467
00468 typedef struct {
00469 unsigned char Blue;
00470 unsigned char Green;
00471 unsigned char Red;
00472 unsigned char Alpha;
00473 } BGRA;
00474
00475 typedef struct {
00476 unsigned char Blue;
00477 unsigned char Green;
00478 unsigned char Red;
00479 } BGR;
00480
00481 typedef struct {
00482 unsigned short int Blue:5;
00483 unsigned short int Green:5;
00484 unsigned short int Red:5;
00485 unsigned short int Reserved:1;
00486 } BGR16;
00487
00488 uint Gui::ShiftRightByMask(uint Color, uint Mask, uint DistributeToBits ) {
00489 if (Mask == 0) return 0;
00490
00491 uint ShiftCount = 0;
00492 uint Test = 0x00000001;
00493
00494 while((ShiftCount<32) && !(Mask & Test)){
00495 Test <<= 1;
00496 ShiftCount++;
00497 }
00498
00499 uint BitCount = 32;
00500 Test = 0x80000000;
00501
00502 while(BitCount && !((Mask >> ShiftCount) & Test)){
00503 Test >>= 1;
00504 BitCount--;
00505 }
00506
00507 uint BaseColor = (Color & Mask) >> ShiftCount;
00508
00509 if(DistributeToBits > BitCount){
00510
00511 uint BitsToFill = DistributeToBits - BitCount;
00512 while(BitsToFill--) {
00513 BaseColor <<= 1;
00514 if(BaseColor & 1)
00515 BaseColor |= 1;
00516 }
00517 }else if(DistributeToBits < BitCount){
00518 BaseColor >>= (BitCount - DistributeToBits);
00519 }
00520 return BaseColor;
00521 }
00522
00523 bool Gui::loadBMP(const wchar* filename, int& width, int& height, Pixel** outData){
00524 FILE* file = 0;
00525 BITMAP_FILEHEADER m_BitmapFileHeader;
00526 BITMAP_HEADER m_BitmapHeader;
00527 RGBA* m_BitmapData = 0;
00528 uchar *Line = 0;
00529 uint m_BitmapSize = 0;
00530 BGRA m_ColorTable[256];
00531 uint m_ColorTableSize = 0;
00532 int bmpWidth = 0, bmpHeight = 0;
00533
00534 #define SAVEEXIT(rs) {\
00535 if(file){fclose(file);file=0;}\
00536 SAVEFREE(m_BitmapData);\
00537 SAVEFREE(Line);\
00538 return rs;}
00539
00540 if(_wfopen_s(&file, filename, TEXT("rb")) != 0)
00541 return false;
00542
00543 fread(&m_BitmapFileHeader, BITMAP_FILEHEADER_SIZE, 1, file);
00544 if(m_BitmapFileHeader.Signature != BITMAP_SIGNATURE)
00545 return false;
00546
00547 fread(&m_BitmapHeader, sizeof(BITMAP_HEADER), 1, file);
00548
00549
00550 fseek(file, BITMAP_FILEHEADER_SIZE + m_BitmapHeader.HeaderSize, SEEK_SET);
00551
00552 switch(m_BitmapHeader.BitCount){
00553 case 1: m_ColorTableSize = 2; break;
00554 case 4: m_ColorTableSize = 16; break;
00555 case 8: m_ColorTableSize = 256; break;
00556 default: break;
00557 }
00558
00559 if(m_ColorTableSize>0)
00560 fread(m_ColorTable, sizeof(BGRA), m_ColorTableSize, file);
00561
00562
00563 bmpWidth = m_BitmapHeader.Width < 0 ? -m_BitmapHeader.Width : m_BitmapHeader.Width;
00564 bmpHeight = m_BitmapHeader.Height < 0 ? -m_BitmapHeader.Height : m_BitmapHeader.Height;
00565
00566 if(width > 0 && height > 0 && width != bmpWidth && height != bmpHeight){
00567 fclose(file);
00568 return false;
00569 }
00570
00571 width = bmpWidth;
00572 height = bmpHeight;
00573
00574 if(outData == 0){
00575 fclose(file);
00576 return true;
00577 }
00578
00579 m_BitmapSize = bmpWidth * bmpHeight;
00580 m_BitmapData = (RGBA*)malloc(sizeof(RGBA)*m_BitmapSize);
00581
00582 uint LineWidth = (bmpWidth * m_BitmapHeader.BitCount/8 + 3) & ~3;
00583 Line = (uchar*)malloc(sizeof(uchar)*LineWidth);
00584
00585 fseek(file, m_BitmapFileHeader.BitsOffset, SEEK_SET);
00586
00587 int Index = 0;
00588
00589 switch(m_BitmapHeader.Compression){
00590
00591 case 0:{
00592 for (int i = 0; i < bmpHeight; i++) {
00593 fread(Line, LineWidth, 1, file);
00594 uchar *LinePtr = Line;
00595
00596 switch(m_BitmapHeader.BitCount) {
00597 case 1:
00598 for(int j = 0; j < bmpWidth; j++){
00599 uint Color = *((uchar*) LinePtr);
00600 for (int k = 0; k < 8; k++) {
00601 m_BitmapData[Index].Red = m_ColorTable[Color & 0x80 ? 1 : 0].Red;
00602 m_BitmapData[Index].Green = m_ColorTable[Color & 0x80 ? 1 : 0].Green;
00603 m_BitmapData[Index].Blue = m_ColorTable[Color & 0x80 ? 1 : 0].Blue;
00604 m_BitmapData[Index].Alpha = m_ColorTable[Color & 0x80 ? 1 : 0].Alpha;
00605 Index++;
00606 Color <<= 1;
00607 }
00608 LinePtr++;
00609 j += 7;
00610 }
00611 break;
00612 case 4:
00613 for(int j = 0; j < bmpWidth; j++){
00614 uint Color = *((uchar*) LinePtr);
00615 m_BitmapData[Index].Red = m_ColorTable[(Color >> 4) & 0x0f].Red;
00616 m_BitmapData[Index].Green = m_ColorTable[(Color >> 4) & 0x0f].Green;
00617 m_BitmapData[Index].Blue = m_ColorTable[(Color >> 4) & 0x0f].Blue;
00618 m_BitmapData[Index].Alpha = m_ColorTable[(Color >> 4) & 0x0f].Alpha;
00619 Index++;
00620 m_BitmapData[Index].Red = m_ColorTable[Color & 0x0f].Red;
00621 m_BitmapData[Index].Green = m_ColorTable[Color & 0x0f].Green;
00622 m_BitmapData[Index].Blue = m_ColorTable[Color & 0x0f].Blue;
00623 m_BitmapData[Index].Alpha = m_ColorTable[Color & 0x0f].Alpha;
00624 Index++;
00625 LinePtr++;
00626 j++;
00627 }
00628 break;
00629 case 8:
00630 for(int j = 0; j < bmpWidth; j++){
00631 uint Color = *((uchar*) LinePtr);
00632 m_BitmapData[Index].Red = m_ColorTable[Color].Red;
00633 m_BitmapData[Index].Green = m_ColorTable[Color].Green;
00634 m_BitmapData[Index].Blue = m_ColorTable[Color].Blue;
00635 m_BitmapData[Index].Alpha = m_ColorTable[Color].Alpha;
00636 Index++;
00637 LinePtr++;
00638 }
00639 break;
00640 case 16:
00641 for(int j = 0; j < bmpWidth; j++){
00642 uint Color = *((unsigned short int*) LinePtr);
00643 m_BitmapData[Index].Red = ((Color >> 10) & 0x1f) << 3;
00644 m_BitmapData[Index].Green = ((Color >> 5) & 0x1f) << 3;
00645 m_BitmapData[Index].Blue = (Color & 0x1f) << 3;
00646 m_BitmapData[Index].Alpha = 255;
00647 Index++;
00648 LinePtr += 2;
00649 }
00650 break;
00651 case 24:
00652 for(int j = 0; j < bmpWidth; j++){
00653 uint Color = *((uint*) LinePtr);
00654 m_BitmapData[Index].Blue = Color & 0xff;
00655 m_BitmapData[Index].Green = (Color >> 8) & 0xff;
00656 m_BitmapData[Index].Red = (Color >> 16) & 0xff;
00657 m_BitmapData[Index].Alpha = 255;
00658 Index++;
00659 LinePtr += 3;
00660 }
00661 break;
00662 case 32:
00663 for(int j = 0; j < bmpWidth; j++){
00664 uint Color = *((uint*) LinePtr);
00665 m_BitmapData[Index].Blue = Color & 0xff;
00666 m_BitmapData[Index].Green = (Color >> 8) & 0xff;
00667 m_BitmapData[Index].Red = (Color >> 16) & 0xff;
00668 m_BitmapData[Index].Alpha = Color >> 24;
00669 Index++;
00670 LinePtr += 4;
00671 }
00672 break;
00673 default:
00674 SAVEEXIT(false);
00675 }
00676 }
00677 break;
00678 }
00679
00680 case 1:{
00681 uchar Count = 0;
00682 uchar ColorIndex = 0;
00683 int x = 0, y = 0;
00684
00685 for(bool run = true; !feof(file) && run; ){
00686 fread(&Count, 1, 1, file);
00687 fread(&ColorIndex, 1, 1, file);
00688
00689 if (Count > 0) {
00690 Index = x + y * bmpWidth;
00691 for (int k = 0; k < Count; k++) {
00692 m_BitmapData[Index + k].Red = m_ColorTable[ColorIndex].Red;
00693 m_BitmapData[Index + k].Green = m_ColorTable[ColorIndex].Green;
00694 m_BitmapData[Index + k].Blue = m_ColorTable[ColorIndex].Blue;
00695 m_BitmapData[Index + k].Alpha = m_ColorTable[ColorIndex].Alpha;
00696 }
00697 x += Count;
00698 } else if (Count == 0) {
00699 int Flag = ColorIndex;
00700 switch(Flag){
00701 case 0: x = 0; y++; break;
00702 case 1: run = false; break;
00703 case 2:{
00704 char rx = 0;
00705 char ry = 0;
00706 fread(&rx, 1, 1, file);
00707 fread(&ry, 1, 1, file);
00708 x += rx;
00709 y += ry;
00710 break;
00711 }
00712 default:{
00713 Count = Flag;
00714 Index = x + y * bmpWidth;
00715 for(int k = 0; k < Count; k++){
00716 fread(&ColorIndex, 1, 1, file);
00717 m_BitmapData[Index + k].Red = m_ColorTable[ColorIndex].Red;
00718 m_BitmapData[Index + k].Green = m_ColorTable[ColorIndex].Green;
00719 m_BitmapData[Index + k].Blue = m_ColorTable[ColorIndex].Blue;
00720 m_BitmapData[Index + k].Alpha = m_ColorTable[ColorIndex].Alpha;
00721 }
00722 x += Count;
00723 if (ftell(file) & 1) fseek(file, 1, SEEK_CUR);
00724 break;
00725 }
00726 }
00727 }
00728 }
00729 break;
00730 }
00731
00732
00733
00734 case 3:{
00735
00736 for(int i=0; i<bmpHeight; i++){
00737 fread(Line, LineWidth, 1, file);
00738 uchar *LinePtr = Line;
00739
00740 for(int j=0; j < bmpWidth; j++){
00741 uint Color = 0;
00742
00743 if (m_BitmapHeader.BitCount == 16) {
00744 Color = *((unsigned short int*) LinePtr);
00745 LinePtr += 2;
00746 } else if (m_BitmapHeader.BitCount == 32) {
00747 Color = *((uint*) LinePtr);
00748 LinePtr += 4;
00749 }
00750 m_BitmapData[Index].Red = ShiftRightByMask(Color, m_BitmapHeader.RedMask);
00751 m_BitmapData[Index].Green = ShiftRightByMask(Color, m_BitmapHeader.GreenMask);
00752 m_BitmapData[Index].Blue = ShiftRightByMask(Color, m_BitmapHeader.BlueMask);
00753 m_BitmapData[Index].Alpha = ShiftRightByMask(Color, m_BitmapHeader.AlphaMask);
00754
00755 Index++;
00756 }
00757 }
00758 break;
00759 }
00760 default:
00761 SAVEEXIT(false);
00762 }
00763
00764 SAVEFREE(Line);
00765 fclose(file);
00766
00767 *outData = (Pixel*)m_BitmapData;
00768 return true;
00769 #undef SAVEEXIT
00770 }