00001
00002
00003
00004
00005
00006
00007
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include <math.h>
00011 #include <setjmp.h>
00012 #include <windows.h>
00013 #include <commctrl.h>
00014
00015 #include "struct.h"
00016 #include "callback.h"
00017 #include "dstruct.h"
00018
00019 #include "trace.h"
00020
00021 typedef struct tagMENUHELPDATA{
00022 int iCode;
00023 char *str;
00024 } MENUHELPDATA;
00025
00026 #if __X__MIPS__
00027 BOOL WINAPI _CRT_INIT(HINSTANCE ,DWORD , LPVOID );
00028 #endif
00029
00030 #define DESELECTED 0
00031 #define SELECTED 1
00032
00033 #define FI_DIB 0
00034 #define FI_GIF 1
00035 #define FI_TGA 2
00036
00037 #define PALVERSION 0x300
00038 #define MAXPALETTE 256
00039 #define MAXTEXT 256
00040
00041 extern short read_gif_image(char *, short);
00042 extern unsigned char p_red[],p_green[],p_blue[];
00043 extern int colourmap_size,x_size,y_size,gif_iLace;
00044
00045 static HWND hParent,hInfo;
00046 static HINSTANCE hThisInstance;
00047 static HPALETTE hpalCurrent = NULL;
00048 static HBITMAP hbmCurrent = NULL;
00049 static RGBQUAD *pRgb = NULL;
00050 static LPSTR lpBitmapHeader = NULL;
00051 static LPSTR lpBitmapBits = NULL;
00052
00053 #define BOUND(x,min,max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
00054 #define SWAP(x,y) ((x)^=(y)^=(x)^=(y))
00055 #define MIN(x,y) (((x) <= (y)) : x ? y)
00056 #define StartWait() hcurSave = SetCursor(LoadCursor(NULL,IDC_WAIT))
00057 #define EndWait() SetCursor(hcurSave)
00058
00059 #define ISDIB(bft) ((bft) == BFT_BITMAP)
00060
00061 #define ALIGNULONG(i) ((i+3)/4*4)
00062
00063 #define WIDTHBYTES(i) ((i+31)/32*4)
00064
00065 static char *szViewClass="OFX:TraceClass";
00066 static char ghFilename[255];
00067 static SYSTEM_INFO sys_info;
00068 static int DisplayWidth,DisplayHeight,DisplayBits,DisplayPlanes,
00069 xScreen,yScreen,rowcount,rowinc,x4_size,file_format=FI_GIF;
00070 static LPSTR pixels;
00071 static POINT ptSize;
00072 static DWORD fdwStyle = WS_POPUP | WS_CAPTION | ! WS_SYSMENU |
00073 WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME;
00074 static HCURSOR hcurSave;
00075
00076 static int pen=0,stretched=1,tracetool=0;
00077 static long Lv= -1,Fv= -1,Nv=0,Ne=0;
00078 static struct TVLIST {BOOL inc; int x,y; long id;} *TVlist=NULL;
00079 static struct TELIST {BOOL inc; int v1,v2;} *TElist=NULL;
00080 #define NMENUHELPDATA 12
00081 static MENUHELPDATA MenuHelpData[NMENUHELPDATA]={
00082 0xFFFF, " ",
00083 IDM_PEN_RED, "Draw vertices and edges with RED pen",
00084 IDM_PEN_WHITE, "Draw vertices and edges with WHITE pen",
00085 IDM_PEN_BLACK, "Draw vertices and edges with BLACK pen",
00086 IDM_PEN_CYAN, "Draw vertices and edges with CYAN pen",
00087 IDM_ADD, "Click to add vertex, click RIGHT button to end sequence",
00088 IDM_MOVE, "Click on vertex to pick it up, drag to new position, click to put it down",
00089 IDM_DELETE, "Click on vertex to delete it",
00090 IDM_INSERT, "Click on vertex to break in two edges attached to vertex",
00091 IDM_EXIT, "Finish and make the draw edges and vertices",
00092 IDM_ABORT, "Cancel the function and to NOT make the edges and vertices",
00093 IDM_STRETCH, "Stretch the image to fill the window or draw it actual size"
00094 };
00095
00096 static int identify_file_format(void);
00097 static int ErrMsg(char *sz,...);
00098 static void PutMsg(char *s);
00099 static LRESULT CALLBACK MainWndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam);
00100 static BOOL MenuCommand(HWND hWnd, WORD id);
00101 static int identify_file_format(void);
00102 static void FreeDib(void);
00103 static void SizeWindow(HWND hWnd);
00104 static HPALETTE CreateImagePalette(LPBITMAPINFOHEADER lpbi);
00105 static WORD NumColours(LPBITMAPINFOHEADER lpbi);
00106 static void AppPaint(HWND hWnd, HDC hDC, int x, int y);
00107 static HBITMAP BitmapFromDib(LPSTR lpHeader,LPSTR lpBits,HPALETTE hpal);
00108
00109 static BOOL Viewer(void);
00110 static void DrawRubberLine(HWND hwnd, int x, int y);
00111 static void DrawRubberLines(HWND hwnd, int x, int y);
00112 static void DrawList(HWND hwnd, HDC hDC);
00113 static void AddTraceVertex(int x,int y);
00114 static int GetVertexAtCursor(int x, int y);
00115 static void MoveVertex(HWND hWnd, int x, int y);
00116 static void TraceSubdivide(long v);
00117 static void BuildFromTrace(HWND hWnd);
00118
00119 static BOOL Viewer(void){
00120 MSG msg;
00121 HWND hDesktopWnd,hWnd;
00122 HDC hDCcaps;
00123 WNDCLASS wndclass;
00124 TVlist=NULL; TElist=NULL; Nv=0; Ne=0;
00125 hDesktopWnd = GetDesktopWindow();
00126 hDCcaps = GetDC(hDesktopWnd);
00127 DisplayWidth= GetDeviceCaps(hDCcaps,HORZRES);
00128 DisplayHeight= GetDeviceCaps(hDCcaps,VERTRES);
00129 DisplayBits= GetDeviceCaps(hDCcaps,BITSPIXEL);
00130 DisplayPlanes= GetDeviceCaps(hDCcaps,PLANES);
00131 ReleaseDC(hDesktopWnd,hDCcaps);
00132 GetSystemInfo(&sys_info);
00133 wndclass.style = 0;
00134 wndclass.lpfnWndProc = (WNDPROC)MainWndProc;
00135 wndclass.cbClsExtra = 0 ;
00136 wndclass.cbWndExtra = 0 ;
00137 wndclass.hInstance = hThisInstance ;
00138 wndclass.hIcon = NULL;
00139 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
00140 wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
00141 wndclass.lpszMenuName = "tracemenu" ;
00142 wndclass.lpszClassName = szViewClass;
00143 if (!RegisterClass (&wndclass)) return FALSE ;
00144 xScreen = GetSystemMetrics (SM_CXSCREEN) ;
00145 yScreen = GetSystemMetrics (SM_CYSCREEN) ;
00146 hWnd = CreateWindow(
00147 szViewClass,
00148 "Image Trace Utility",
00149 fdwStyle,
00150 25,
00151 25,
00152 xScreen-50,
00153 yScreen-50,
00154 hParent,
00155 NULL,
00156 hThisInstance,
00157 NULL) ;
00158 if(hWnd == NULL)return FALSE;
00159 ShowWindow (hWnd,SW_SHOWNA);
00160 PostMessage(hWnd,WM_COMMAND,(WPARAM)IDM_DRAWIT,0);
00161 while(GetMessage (&msg,NULL,0,0)){
00162 TranslateMessage (&msg);
00163 DispatchMessage (&msg);
00164 }
00165 DestroyWindow(hWnd);
00166 UnregisterClass(wndclass.lpszClassName,wndclass.hInstance);
00167 if(TVlist != NULL)X__Free(TVlist); TVlist=NULL; Nv=0;
00168 if(TElist != NULL)X__Free(TElist); TElist=NULL; Ne=0;
00169 return TRUE;
00170 }
00171
00172 LRESULT CALLBACK MainWndProc(HWND hWnd,UINT iMessage,WPARAM wParam,
00173 LPARAM lParam){
00174 static BOOL bToolCaptured=FALSE;
00175 static HCURSOR hCursorSave;
00176 static POINT LastPt;
00177 PAINTSTRUCT ps;
00178 HDC hDC;
00179 int i;
00180 RECT rc;
00181 POINT pt;
00182 switch (iMessage) {
00183 case WM_DESTROY:
00184 FreeDib();
00185 break;
00186 case WM_COMMAND:
00187 return MenuCommand(hWnd,LOWORD(wParam));
00188 break;
00189 case WM_MENUSELECT: {
00190 HMENU hmenu;
00191 UINT fuFlags,uItem,id;
00192 hmenu=(HMENU)lParam;
00193 fuFlags=(UINT)HIWORD(wParam);
00194 uItem=(UINT)LOWORD(wParam);
00195 id=0;
00196 if(fuFlags == 0xFFFF)id=0;
00197 else if(fuFlags & MF_POPUP){;}
00198 else{
00199 for(i=0;i<NMENUHELPDATA;i++){
00200 if(uItem == MenuHelpData[i].iCode){id=(UINT)i; break;}
00201 }
00202 }
00203 SendMessage(hInfo,SB_SETTEXT,(WPARAM)0,(LPARAM)MenuHelpData[id].str);
00204 }
00205 break;
00206 case WM_RBUTTONUP:
00207 if(!bToolCaptured)break;
00208 if(tracetool == 1)DrawRubberLine(hWnd,LOWORD(lParam),HIWORD(lParam));
00209 if(tracetool == 2){
00210 DrawRubberLines(hWnd,LOWORD(lParam),HIWORD(lParam));
00211 MoveVertex(hWnd,LOWORD(lParam),HIWORD(lParam));
00212 }
00213 SetCursor(hCursorSave);
00214 ClipCursor(NULL);
00215 ReleaseCapture();
00216 bToolCaptured=FALSE;
00217 Lv= -1;
00218 break;
00219 case WM_LBUTTONDOWN:
00220 if(tracetool == 0 || bToolCaptured)break;
00221 else if(tracetool == 2){
00222 if((Fv=GetVertexAtCursor(LOWORD(lParam),HIWORD(lParam))) < 0)break;
00223 }
00224 else if(tracetool == 3){
00225 if((Fv=GetVertexAtCursor(LOWORD(lParam),HIWORD(lParam))) >= 0){
00226 if(Ne > 0 && TElist != NULL)for(i=0;i<Ne;i++){
00227 if(TElist[i].v1 == Fv || TElist[i].v2 == Fv)TElist[i].inc=FALSE;
00228 }
00229 TVlist[Fv].inc=FALSE;
00230 InvalidateRect(hWnd,NULL,FALSE);
00231 Fv= -1;
00232 }
00233 break;
00234 }
00235 else if(tracetool == 4){
00236 if((Fv=GetVertexAtCursor(LOWORD(lParam),HIWORD(lParam))) >= 0){
00237 TraceSubdivide(Fv);
00238 InvalidateRect(hWnd,NULL,FALSE);
00239 Fv= -1;
00240 }
00241 break;
00242 }
00243 bToolCaptured=TRUE;
00244 SetCapture(hWnd);
00245 hCursorSave=SetCursor(LoadCursor(NULL,IDC_SIZE));
00246 GetClientRect(hWnd,&rc);
00247 pt.x=rc.left; pt.y=rc.top;
00248 ClientToScreen(hWnd,&pt);
00249 rc.left=pt.x; rc.top=pt.y;
00250 pt.x=rc.right; pt.y=rc.bottom;
00251 ClientToScreen(hWnd,&pt);
00252 rc.right=pt.x; rc.bottom=pt.y;
00253 ClipCursor(&rc);
00254 break;
00255 case WM_MOUSEMOVE:
00256 if(!bToolCaptured)break;
00257 if(tracetool == 1){
00258 DrawRubberLine(hWnd,(int)LastPt.x,(int)LastPt.y);
00259 LastPt.x=LOWORD(lParam); LastPt.y=HIWORD(lParam);
00260 DrawRubberLine(hWnd,(int)LastPt.x,(int)LastPt.y);
00261 }
00262 if(tracetool == 2){
00263 DrawRubberLines(hWnd,(int)LastPt.x,(int)LastPt.y);
00264 LastPt.x=LOWORD(lParam); LastPt.y=HIWORD(lParam);
00265 DrawRubberLines(hWnd,(int)LastPt.x,(int)LastPt.y);
00266 }
00267 break;
00268 case WM_LBUTTONUP:
00269 if(!bToolCaptured)break;
00270 if(tracetool == 1){
00271 LastPt.x=LOWORD(lParam); LastPt.y=HIWORD(lParam);
00272 if(Lv >= 0)DrawRubberLine(hWnd,(int)LastPt.x,(int)LastPt.y);
00273 AddTraceVertex((int)LOWORD(lParam),(int)HIWORD(lParam));
00274 DrawList(hWnd,NULL);
00275 DrawRubberLine(hWnd,(int)LastPt.x,(int)LastPt.y);
00276 }
00277 else if(tracetool == 2){
00278 if(Lv < 0){
00279 Lv=Fv; Fv=-1;
00280 LastPt.x=LOWORD(lParam); LastPt.y=HIWORD(lParam);
00281 DrawRubberLines(hWnd,(int)LastPt.x,(int)LastPt.y);
00282 }
00283 else{
00284 DrawRubberLines(hWnd,LOWORD(lParam),HIWORD(lParam));
00285 MoveVertex(hWnd,LOWORD(lParam),HIWORD(lParam));
00286 SetCursor(hCursorSave);
00287 ClipCursor(NULL);
00288 ReleaseCapture();
00289 bToolCaptured=FALSE;
00290 Lv= -1;
00291 }
00292 }
00293 break;
00294 case WM_PAINT:
00295 hDC = BeginPaint(hWnd, &ps);
00296 AppPaint(hWnd,hDC,0,0);
00297 DrawList(hWnd,hDC);
00298 EndPaint(hWnd,&ps);
00299 break ;
00300 case WM_SIZE:
00301 InvalidateRect(hWnd,NULL,FALSE);
00302 return 0;
00303 case WM_QUERYNEWPALETTE:{
00304 HDC hDC;
00305 HPALETTE hpalT;
00306 if(hpalCurrent == NULL)break;
00307 hDC=GetDC(hWnd);
00308 hpalT = SelectPalette(hDC,hpalCurrent,FALSE);
00309 if(RealizePalette (hDC) > 0)InvalidateRect (hWnd, (LPRECT) (NULL),FALSE);
00310 SelectPalette(hDC,hpalT,FALSE);
00311 ReleaseDC(hWnd,hDC);
00312 return TRUE;
00313 }
00314 case WM_PALETTECHANGED:
00315 if ((HWND)wParam != hWnd ){
00316 HDC hDC;
00317 HPALETTE hpalT;
00318 if(hpalCurrent == NULL)break;
00319 hDC=GetDC(hWnd);
00320 hpalT = SelectPalette(hDC,hpalCurrent,FALSE);
00321 if(RealizePalette (hDC) > 0)InvalidateRect (hWnd, (LPRECT) (NULL),FALSE);
00322 SelectPalette(hDC,hpalT,FALSE);
00323 ReleaseDC(hWnd,hDC);
00324 }
00325 break;
00326 default:
00327 return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
00328 }
00329 return 0L ;
00330 }
00331
00332 BOOL MenuCommand (HWND hWnd, WORD id){
00333 int i;
00334 char lpMessage[MAXTEXT],lpCaption[64];
00335 switch (id) {
00336 case IDM_DRAWIT:
00337 StartWait();
00338 file_format=identify_file_format();
00339 switch(file_format){
00340 case FI_GIF:
00341 if(gifview(hWnd,ghFilename))InvalidateRect (hWnd, NULL, FALSE);
00342 else PostMessage(hWnd,WM_COMMAND,(WPARAM)IDM_ABORT,0);
00343 break;
00344 case FI_TGA:
00345 if(tgaview(hWnd,ghFilename))InvalidateRect (hWnd, NULL, FALSE);
00346 else PostMessage(hWnd,WM_COMMAND,(WPARAM)IDM_ABORT,0);
00347 break;
00348
00349
00350
00351
00352 default:
00353 case FI_DIB:
00354 if(bmpview(hWnd,ghFilename))InvalidateRect (hWnd, NULL, FALSE);
00355 else PostMessage(hWnd,WM_COMMAND,(WPARAM)IDM_ABORT,0);
00356 break;
00357 break;
00358 }
00359 EndWait();
00360 break;
00361 case IDM_PEN_RED : pen=0; goto PENID;
00362 case IDM_PEN_WHITE: pen=1; goto PENID;
00363 case IDM_PEN_BLACK: pen=2; goto PENID;
00364 case IDM_PEN_CYAN : pen=3; goto PENID;
00365 PENID:
00366 CheckMenuItem(GetMenu(hWnd),IDM_PEN_RED,MF_UNCHECKED);
00367 CheckMenuItem(GetMenu(hWnd),IDM_PEN_WHITE,MF_UNCHECKED);
00368 CheckMenuItem(GetMenu(hWnd),IDM_PEN_BLACK,MF_UNCHECKED);
00369 CheckMenuItem(GetMenu(hWnd),IDM_PEN_CYAN,MF_UNCHECKED);
00370 if(pen == 0)CheckMenuItem(GetMenu(hWnd),IDM_PEN_RED,MF_CHECKED);
00371 if(pen == 1)CheckMenuItem(GetMenu(hWnd),IDM_PEN_WHITE,MF_CHECKED);
00372 if(pen == 2)CheckMenuItem(GetMenu(hWnd),IDM_PEN_BLACK,MF_CHECKED);
00373 if(pen == 3)CheckMenuItem(GetMenu(hWnd),IDM_PEN_CYAN,MF_CHECKED);
00374 DrawList(hWnd,NULL);
00375 break;
00376 case IDM_STRETCH:
00377 stretched ^= 1;
00378 if(stretched)ModifyMenu(GetMenu(hWnd),IDM_STRETCH,MF_BYCOMMAND|MF_STRING,
00379 IDM_STRETCH,"&Actual Size");
00380 else ModifyMenu(GetMenu(hWnd),IDM_STRETCH,MF_BYCOMMAND|MF_STRING,
00381 IDM_STRETCH,"&Stretch to fit");
00382 InvalidateRect (hWnd, (LPRECT) (NULL), FALSE);
00383 break;
00384 case IDM_ADD:
00385 Lv= -1;
00386 EnableMenuItem(GetMenu(hWnd),IDM_ADD,MF_GRAYED);
00387 EnableMenuItem(GetMenu(hWnd),IDM_MOVE,MF_ENABLED);
00388 EnableMenuItem(GetMenu(hWnd),IDM_DELETE,MF_ENABLED);
00389 EnableMenuItem(GetMenu(hWnd),IDM_INSERT,MF_ENABLED);
00390 DrawMenuBar(hWnd);
00391 tracetool=1;
00392 break;
00393 case IDM_MOVE:
00394 Lv= -1;
00395 EnableMenuItem(GetMenu(hWnd),IDM_ADD,MF_ENABLED);
00396 EnableMenuItem(GetMenu(hWnd),IDM_MOVE,MF_GRAYED);
00397 EnableMenuItem(GetMenu(hWnd),IDM_DELETE,MF_ENABLED);
00398 EnableMenuItem(GetMenu(hWnd),IDM_INSERT,MF_ENABLED);
00399 DrawMenuBar(hWnd);
00400 tracetool=2;
00401 break;
00402 case IDM_DELETE:
00403 Lv= -1;
00404 EnableMenuItem(GetMenu(hWnd),IDM_ADD,MF_ENABLED);
00405 EnableMenuItem(GetMenu(hWnd),IDM_MOVE,MF_ENABLED);
00406 EnableMenuItem(GetMenu(hWnd),IDM_DELETE,MF_GRAYED);
00407 EnableMenuItem(GetMenu(hWnd),IDM_INSERT,MF_ENABLED);
00408 DrawMenuBar(hWnd);
00409 tracetool=3;
00410 break;
00411 case IDM_INSERT:
00412 Lv= -1;
00413 EnableMenuItem(GetMenu(hWnd),IDM_ADD,MF_ENABLED);
00414 EnableMenuItem(GetMenu(hWnd),IDM_MOVE,MF_ENABLED);
00415 EnableMenuItem(GetMenu(hWnd),IDM_DELETE,MF_ENABLED);
00416 EnableMenuItem(GetMenu(hWnd),IDM_INSERT,MF_GRAYED);
00417 DrawMenuBar(hWnd);
00418 tracetool=4;
00419 break;
00420 case IDM_EXIT:
00421 BuildFromTrace(hWnd);
00422 case IDM_ABORT:
00423 PostQuitMessage(0);
00424 break;
00425 default:
00426 break;
00427 }
00428 return TRUE;
00429 }
00430
00431 static void FreeDib(void){
00432 if (hpalCurrent) DeleteObject(hpalCurrent);
00433 if (hbmCurrent) DeleteObject(hbmCurrent);
00434 if(lpBitmapBits != NULL)X__Free((char *)lpBitmapBits);
00435 if(lpBitmapHeader != NULL)X__Free((char *)lpBitmapHeader);
00436 lpBitmapHeader = NULL;
00437 lpBitmapBits = NULL;
00438 hpalCurrent = NULL;
00439 hbmCurrent = NULL;
00440 pRgb = NULL;
00441 }
00442
00443 static int identify_file_format(void){
00444 int ff=FI_DIB;
00445 strupr(ghFilename);
00446 if (strstr(ghFilename,".GIF"))ff=FI_GIF;
00447
00448 else if(strstr(ghFilename,".TGA"))ff=FI_TGA;
00449 else if(strstr(ghFilename,".DIB") ||
00450 strstr(ghFilename,".BMP") ||
00451 strstr(ghFilename,".RLE"))ff=FI_DIB;
00452 return ff;
00453 }
00454
00455 static int ErrMsg(char *sz,...){
00456 char ach[128];
00457 va_list arg_ptr;
00458 va_start(arg_ptr,sz);
00459 vsprintf(ach,sz,arg_ptr);
00460 va_end(arg_ptr);
00461 MessageBox (NULL, ach, NULL, MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL);
00462 return FALSE;
00463 }
00464
00465 static void PutMsg(char *s){
00466 MessageBox (NULL,s, "Trace", MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL);
00467 }
00468
00469 static void SizeWindow(HWND hWnd){
00470 char Title[120];
00471 RECT Rectangle;
00472 int dx,dy;
00473 POINT pt;
00474 LPBITMAPINFOHEADER bi;
00475 if((bi=(LPBITMAPINFOHEADER)lpBitmapHeader) == NULL)return;
00476 sprintf(Title,
00477 "%s (%s %ldx%ldx%ld)",
00478 "View",
00479 ghFilename,
00480 (long)x_size,
00481 (long)bi->biHeight,
00482 (long)bi->biBitCount);
00483 SetWindowText(hWnd,Title);
00484 InvalidateRect(hWnd,NULL,FALSE);
00485 }
00486
00487 int out_line(unsigned char *linepixels, int linelen){
00488 register long l;
00489 l = (long)(y_size - 1 - rowcount)*(long)(x4_size);
00490 memcpy(pixels + l, linepixels, linelen);
00491 rowcount+=abs(rowinc);
00492 if(rowcount >= y_size){
00493 if (rowinc == -8){rowinc=8; rowcount=4;}
00494 else if(rowinc == 8){rowinc=4; rowcount=2;}
00495 else if(rowinc == 4){rowinc=2; rowcount=1;}
00496 }
00497 return 0;
00498 }
00499
00500 static int gifview(HWND hWnd,char *temp){
00501 int i;
00502 long imagesize;
00503 LPBITMAPINFOHEADER lpbi;
00504 FreeDib();
00505 rowcount=0;
00506 rowinc=1;
00507 if(read_gif_image(temp,1) < 0){
00508 ErrMsg("'%ls' is NOT a valid GIF file", (LPSTR)temp);
00509 return 0;
00510 }
00511 if(gif_iLace)rowinc = -8;
00512 x4_size = ALIGNULONG(x_size);
00513 lpBitmapHeader = (LPSTR)X__Malloc((long)sizeof(BITMAPINFOHEADER)
00514 +256L*sizeof(RGBQUAD));
00515 if(lpBitmapHeader == NULL){
00516 ErrMsg("Out of memory");
00517 return 0;
00518 }
00519 lpbi=(LPBITMAPINFOHEADER)lpBitmapHeader;
00520 lpbi->biSize=sizeof(BITMAPINFOHEADER);
00521 lpbi->biWidth=(DWORD)x4_size;
00522 lpbi->biHeight=(DWORD)y_size;
00523 lpbi->biPlanes=1;
00524 lpbi->biBitCount=8;
00525 lpbi->biCompression=BI_RGB;
00526 imagesize = lpbi->biSizeImage = (DWORD)x4_size*(DWORD)y_size;
00527 lpbi->biXPelsPerMeter=0;
00528 lpbi->biYPelsPerMeter=0;
00529 lpbi->biClrUsed=256;
00530 lpbi->biClrImportant=256;
00531 pRgb=(RGBQUAD *)((LPSTR)lpbi + lpbi->biSize);
00532 for(i=0;i<256;i++){
00533 pRgb[i].rgbRed = p_red[i] << 2;
00534 pRgb[i].rgbGreen = p_green[i] << 2;
00535 pRgb[i].rgbBlue = p_blue[i] << 2;
00536 }
00537 hpalCurrent=CreateImagePalette(lpbi);
00538 lpBitmapBits=(LPSTR)X__Malloc(imagesize);
00539 if(lpBitmapBits == NULL){
00540 ErrMsg("Out of memory");
00541 FreeDib();
00542 return 0;
00543 }
00544 memset(lpBitmapBits,0,imagesize);
00545 pixels=lpBitmapBits;
00546 if(read_gif_image(temp,0) < 0){
00547 PutMsg("Error reading GIF file");
00548 FreeDib();
00549 return 0;
00550 }
00551 hbmCurrent=BitmapFromDib(lpBitmapHeader,lpBitmapBits,hpalCurrent);
00552 if(hbmCurrent == NULL)ErrMsg("Could not create bitmap");
00553 SizeWindow(hWnd);
00554 return 1;
00555 }
00556
00557 static int bmpview(HWND hWnd,char *temp){
00558 int i,nc,bits;
00559 long imagesize;
00560 LPBITMAPINFOHEADER lpbi;
00561 BITMAPFILEHEADER bmfh;
00562 FILE *t24;
00563 FreeDib();
00564 lpBitmapHeader = (LPSTR)X__Malloc((long)sizeof(BITMAPINFOHEADER)
00565 +256L*sizeof(RGBQUAD));
00566 if(lpBitmapHeader == NULL){
00567 ErrMsg("Out of memory");
00568 return 0;
00569 }
00570 lpbi=(LPBITMAPINFOHEADER)lpBitmapHeader;
00571 lpbi->biSize=sizeof(BITMAPINFOHEADER);
00572 pRgb=(RGBQUAD *)((LPSTR)lpbi + lpbi->biSize);
00573 t24=fopen((char *)temp,"rb");
00574 if(t24 == NULL)return 0;
00575 fread((char *)&bmfh,sizeof(BITMAPFILEHEADER),1,t24);
00576 fread((char *)lpbi,sizeof(BITMAPINFOHEADER),1,t24);
00577 if(lpbi->biClrUsed != 0)nc=lpbi->biClrUsed;
00578 else{
00579 bits = lpbi->biBitCount;
00580 switch (bits){
00581 case 1: nc=2; break;
00582 case 4: nc=16; break;
00583 case 8: nc=256; break;
00584 default: nc=0; break;
00585 }
00586 }
00587 x_size=lpbi->biWidth;
00588 y_size=lpbi->biHeight;
00589 x4_size = ALIGNULONG(x_size);
00590 imagesize=bmfh.bfSize-bmfh.bfOffBits;
00591
00592
00593 if(nc > 0)fread((char *)pRgb,nc*sizeof(RGBQUAD),1,t24);
00594 if((lpBitmapBits=(unsigned char *)X__Malloc(imagesize)) == NULL){
00595 fclose(t24);
00596 FreeDib();
00597 return 0;
00598 }
00599 memset(lpBitmapBits,0,imagesize);
00600 fread((char *)lpBitmapBits,imagesize,1,t24);
00601 fclose(t24);
00602 hpalCurrent=CreateImagePalette(lpbi);
00603 hbmCurrent=BitmapFromDib(lpBitmapHeader,lpBitmapBits,hpalCurrent);
00604 if(hbmCurrent == NULL)ErrMsg("Could not create bitmap");
00605 SizeWindow(hWnd);
00606 return 1;
00607 }
00608
00609 static HPALETTE CreateImagePalette(LPBITMAPINFOHEADER lpbi){
00610 LOGPALETTE *pPal;
00611 HPALETTE hpal = NULL;
00612 WORD nNumColors;
00613 BYTE red;
00614 BYTE green;
00615 BYTE blue;
00616 int i;
00617 RGBQUAD *pRgb;
00618 if(lpbi == NULL)return NULL;
00619 if(lpbi->biSize != sizeof(BITMAPINFOHEADER))return NULL;
00620
00621 pRgb = (RGBQUAD *)((LPSTR)lpbi + (WORD)lpbi->biSize);
00622 nNumColors = NumColours(lpbi);
00623 if(nNumColors){
00624 pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
00625 if(pPal == NULL)return NULL;
00626 pPal->palNumEntries = nNumColors;
00627 pPal->palVersion = PALVERSION;
00628
00629
00630 for (i = 0; i < nNumColors; i++){
00631 pPal->palPalEntry[i].peRed = pRgb[i].rgbRed;
00632 pPal->palPalEntry[i].peGreen = pRgb[i].rgbGreen;
00633 pPal->palPalEntry[i].peBlue = pRgb[i].rgbBlue;
00634 pPal->palPalEntry[i].peFlags = (BYTE)0;
00635 }
00636 hpal = CreatePalette(pPal);
00637 LocalFree((HANDLE)pPal);
00638 }
00639 else if (lpbi->biBitCount == 24){
00640
00641
00642 nNumColors = MAXPALETTE;
00643 pPal=(LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
00644 if(pPal == NULL)return NULL;
00645 pPal->palNumEntries = nNumColors;
00646 pPal->palVersion = PALVERSION;
00647 red = green = blue = 0;
00648
00649 for (i = 0; i < pPal->palNumEntries; i++){
00650 pPal->palPalEntry[i].peRed = red;
00651 pPal->palPalEntry[i].peGreen = green;
00652 pPal->palPalEntry[i].peBlue = blue;
00653 pPal->palPalEntry[i].peFlags = (BYTE)0;
00654 if (!(red += 32))if (!(green += 32)) blue += 64;
00655 }
00656 hpal = CreatePalette(pPal);
00657 LocalFree((HANDLE)pPal);
00658 }
00659 return hpal;
00660 }
00661
00662 static WORD NumColours(LPBITMAPINFOHEADER lpbi){
00663 WORD bits;
00664 if (lpbi->biClrUsed != 0)return (WORD)lpbi->biClrUsed;
00665 bits = lpbi->biBitCount;
00666 switch (bits){
00667 case 1: return 2;
00668 case 4: return 16;
00669 case 8: return 256;
00670 default: return 0;
00671 }
00672 }
00673
00674 static void AppPaint(HWND hWnd,HDC hDC,int x,int y){
00675 RECT rc;
00676 HPALETTE hpalT;
00677 POINT Origin;
00678 HDC hDCbits;
00679 BITMAP bm;
00680 GetClientRect(hWnd,&rc);
00681 if(hpalCurrent != NULL){
00682 hpalT = SelectPalette(hDC,hpalCurrent,FALSE);
00683 RealizePalette (hDC);
00684 if(hbmCurrent != NULL){
00685 hDCbits = CreateCompatibleDC(hDC);
00686 GetObject(hbmCurrent,sizeof(BITMAP),(LPSTR)&bm);
00687 SelectObject(hDCbits,hbmCurrent);
00688 if(stretched && (GetDeviceCaps(hDC,RASTERCAPS) & RC_STRETCHBLT) == RC_STRETCHBLT)
00689 StretchBlt(hDC,0,0,rc.right,rc.bottom,hDCbits,0,0,
00690 bm.bmWidth,bm.bmHeight,SRCCOPY);
00691 else{
00692 PatBlt(hDC,0,0,rc.right,rc.bottom,PATCOPY);
00693 BitBlt(hDC,0,0,bm.bmWidth,bm.bmHeight,hDCbits,0,0,SRCCOPY);
00694 }
00695 DeleteDC(hDCbits);
00696 }
00697 else {
00698 if(lpBitmapHeader != NULL && lpBitmapBits != NULL){
00699 StretchDIBits(hDC,
00700 0,0,
00701 rc.right,
00702 rc.top,
00703 0,0,
00704 (WORD)((LPBITMAPINFOHEADER)lpBitmapHeader)->biWidth,
00705 (WORD)((LPBITMAPINFOHEADER)lpBitmapHeader)->biHeight,
00706 lpBitmapBits,
00707 (LPBITMAPINFO)lpBitmapHeader,
00708 DIB_RGB_COLORS,
00709 SRCCOPY);
00710 }
00711 }
00712 SelectPalette(hDC,hpalT,FALSE);
00713 }
00714 }
00715
00716 static HBITMAP BitmapFromDib(LPSTR lpHeader,LPSTR lpBits,HPALETTE hpal){
00717 HDC hdc;
00718 HBITMAP hbm;
00719 HPALETTE hpalT;
00720 if (lpHeader == NULL || lpBits == NULL)return NULL;
00721 hdc = GetDC(NULL);
00722 if(hpal != NULL){
00723 hpalT = SelectPalette(hdc,hpal,FALSE);
00724 RealizePalette(hdc);
00725 }
00726 hbm = CreateDIBitmap(hdc,
00727 (LPBITMAPINFOHEADER)lpHeader,
00728 (LONG)CBM_INIT,
00729 lpBits,
00730 (LPBITMAPINFO)lpHeader,
00731 DIB_RGB_COLORS );
00732 if(hpalCurrent)SelectPalette(hdc,hpalT,FALSE);
00733 ReleaseDC(NULL,hdc);
00734 return hbm;
00735 }
00736
00737
00738 static void DrawRubberLine(HWND hwnd, int x, int y){
00739 HPEN hOldPen,MyPen;
00740 int oldROP;
00741 HDC hDClocal;
00742 if(Lv < 0)return;
00743 hDClocal=GetDC(hwnd);
00744 if(pen == 0)MyPen=CreatePen(PS_SOLID,0,RGB(255,0,0));
00745 if(pen == 1)MyPen=CreatePen(PS_SOLID,0,RGB(255,255,255));
00746 if(pen == 2)MyPen=CreatePen(PS_SOLID,0,RGB(0,0,0));
00747 if(pen == 3)MyPen=CreatePen(PS_SOLID,0,RGB(0,255,255));
00748 hOldPen=SelectObject(hDClocal,MyPen);
00749 oldROP=SetROP2(hDClocal,R2_NOT);
00750 MoveToEx(hDClocal,x,y,NULL);
00751 LineTo(hDClocal,TVlist[Lv].x,TVlist[Lv].y);
00752 SetROP2(hDClocal,oldROP);
00753 SelectObject(hDClocal,hOldPen);
00754 DeleteObject(MyPen);
00755 ReleaseDC(hwnd,hDClocal);
00756 }
00757
00758 static void DrawRubberLines(HWND hwnd, int x, int y){
00759 int i,v1,v2;
00760 HPEN hOldPen;
00761 int oldROP;
00762 HDC hDClocal;
00763 if(Lv < 0 || Ne == 0)return;
00764 hDClocal=GetDC(hwnd);
00765 hOldPen=SelectObject(hDClocal,GetStockObject(WHITE_PEN));
00766 oldROP=SetROP2(hDClocal,R2_NOT);
00767 for(i=0;i<Ne;i++){
00768 if(!TElist[i].inc)continue;
00769 v1=TElist[i].v1; v2=TElist[i].v2;
00770 if(TVlist[v1].inc && v1 == Lv){
00771 MoveToEx(hDClocal,x,y,NULL);
00772 LineTo(hDClocal,TVlist[v2].x,TVlist[v2].y);
00773 }
00774 else if(TVlist[v2].inc && v2 == Lv){
00775 MoveToEx(hDClocal,x,y,NULL);
00776 LineTo(hDClocal,TVlist[v1].x,TVlist[v1].y);
00777 }
00778 }
00779 SetROP2(hDClocal,oldROP);
00780 SelectObject(hDClocal,hOldPen);
00781 ReleaseDC(hwnd,hDClocal);
00782 }
00783
00784 static void DrawList(HWND hwnd, HDC hDC){
00785 int i,x,y;
00786 HPEN hOldPen,MyPen;
00787 HBRUSH hOldBrush;
00788 HDC hDClocal;
00789 if(hDC == NULL){
00790 hDClocal=GetDC(hwnd);
00791 }
00792 else hDClocal=hDC;
00793 if(pen == 0)MyPen=CreatePen(PS_SOLID,0,RGB(255,0,0));
00794 if(pen == 1)MyPen=CreatePen(PS_SOLID,0,RGB(255,255,255));
00795 if(pen == 2)MyPen=CreatePen(PS_SOLID,0,RGB(0,0,0));
00796 if(pen == 3)MyPen=CreatePen(PS_SOLID,0,RGB(0,255,255));
00797 hOldPen=SelectObject(hDClocal,MyPen);
00798 hOldBrush=SelectObject(hDClocal,GetStockObject(BLACK_BRUSH));
00799 if(Ne > 0 && TElist != NULL){
00800 for(i=0;i<Ne;i++){
00801 if(!TElist[i].inc)continue;
00802 x=TVlist[TElist[i].v1].x; y=TVlist[TElist[i].v1].y;
00803 MoveToEx(hDClocal,x,y,NULL);
00804 x=TVlist[TElist[i].v2].x; y=TVlist[TElist[i].v2].y;
00805 LineTo(hDClocal,x,y);
00806 }
00807 }
00808 if(Nv > 0 && TVlist != NULL){
00809 for(i=0;i<Nv;i++)if(TVlist[i].inc)Rectangle(hDClocal,
00810 TVlist[i].x-2,TVlist[i].y-2,TVlist[i].x+2,TVlist[i].y+2);
00811 }
00812 SelectObject(hDClocal,hOldPen);
00813 SelectObject(hDClocal,hOldBrush);
00814 DeleteObject(MyPen);
00815 if(hDC == NULL){
00816 ReleaseDC(hwnd,hDClocal);
00817 }
00818 }
00819
00820 static void AddTraceVertex(int x,int y){
00821 int i,id,found=0,flag=0;
00822 struct TVLIST *v;
00823 struct TELIST *e;
00824 if(Nv > 0){
00825 for(i=0;i<Nv;i++){
00826 if(TVlist[i].inc && abs(x-TVlist[i].x) < 4 && abs(y-TVlist[i].y) < 4){
00827 found=1;
00828 if(Lv >= 0)flag=1;
00829 id=i;
00830 }
00831 }
00832 }
00833 if(!found){
00834 if(TVlist == NULL){
00835 if((v=(struct TVLIST *)X__Malloc(sizeof(struct TVLIST))) == NULL)return;
00836 }
00837 else{
00838 if((v=(struct TVLIST *)X__Realloc(TVlist,(Nv+1)*sizeof(struct TVLIST))) == NULL)return;
00839 }
00840 TVlist=v;
00841 v[Nv].x=x; v[Nv].y=y; v[Nv].inc=TRUE;
00842 id=Nv;
00843 Nv++;
00844 }
00845 if(Lv < 0){
00846 Lv=id;
00847 }
00848 else{
00849 if(TElist == NULL){
00850 if((e=(struct TELIST *)X__Malloc(sizeof(struct TELIST))) == NULL)return;
00851 }
00852 else{
00853 if((e=(struct TELIST *)X__Realloc(TElist,(Ne+1)*sizeof(struct TELIST))) == NULL)return;
00854 }
00855 TElist=e;
00856 e[Ne].v1=id; e[Ne].v2=Lv; e[Ne].inc=TRUE;
00857 Lv=id;
00858 Ne++;
00859 }
00860 if(flag)Lv= -1;
00861 }
00862
00863 static void MoveVertex(HWND hWnd,int x, int y){
00864 if(Lv < 0)return;
00865 TVlist[Lv].x=x; TVlist[Lv].y=y;
00866 InvalidateRect(hWnd,NULL,FALSE);
00867 return;
00868 }
00869
00870 int GetVertexAtCursor(int x, int y){
00871 int i,id= -1;
00872 if(Nv > 0)for(i=0;i<Nv;i++){
00873 if(TVlist[i].inc && abs(x-TVlist[i].x) < 4 && abs(y-TVlist[i].y) < 4)id=i;
00874 }
00875 return id;
00876 }
00877
00878 static void TraceSubdivide(long vv){
00879 struct TVLIST *v;
00880 struct TELIST *e;
00881 int ne1,i,x,y;
00882 if(Nv == 0 || Ne == 0 || TVlist == NULL || TElist == NULL)return;
00883 ne1=Ne; for(i=0;i<ne1;i++){
00884 if(!TElist[i].inc)continue;
00885 x=(TVlist[TElist[i].v1].x+TVlist[TElist[i].v2].x)/2;
00886 y=(TVlist[TElist[i].v1].y+TVlist[TElist[i].v2].y)/2;
00887 if(TElist[i].v1 == vv){
00888 if((v=(struct TVLIST *)X__Realloc(TVlist,(Nv+1)*sizeof(struct TVLIST))) == NULL)return;
00889 TVlist=v; v[Nv].x=x; v[Nv].y=y; v[Nv].inc=TRUE;
00890 TElist[i].v1=Nv;
00891 if((e=(struct TELIST *)X__Realloc(TElist,(Ne+1)*sizeof(struct TELIST))) == NULL)return;
00892 TElist=e; e[Ne].v1=Nv; e[Ne].v2=vv; e[Ne].inc=TRUE;
00893 Ne++;
00894 Nv++;
00895 }
00896 else if(TElist[i].v2 == vv){
00897 if((v=(struct TVLIST *)X__Realloc(TVlist,(Nv+1)*sizeof(struct TVLIST))) == NULL)return;
00898 TVlist=v; v[Nv].x=x; v[Nv].y=y; v[Nv].inc=TRUE;
00899 TElist[i].v2=Nv;
00900 if((e=(struct TELIST *)X__Realloc(TElist,(Ne+1)*sizeof(struct TELIST))) == NULL)return;
00901 TElist=e; e[Ne].v1=Nv; e[Ne].v2=vv; e[Ne].inc=TRUE;
00902 Ne++;
00903 Nv++;
00904 }
00905 }
00906 }
00907
00908 static void BuildFromTrace(HWND hWnd){
00909 RECT rc;
00910 long Scale,v1,v2;
00911 int i,vc=0,ec=0;
00912 GetClientRect(hWnd,&rc);
00913 if(Nv == 0 || TVlist == NULL)return;
00914 Scale=100;
00915 for(i=0;i<Nv;i++){
00916 if(TVlist[i].inc)vc++;
00917 TVlist[i].id = -1;
00918 }
00919 if(vc == 0)return;
00920 UpdateVertexHeap(Nvert+vc);
00921 for(i=0;i<Nv;i++){
00922 if(!TVlist[i].inc)continue;
00923 CreateVertex();
00924 (MainVp+Nvert-1)->xyz[0]=TVlist[i].x*Scale;
00925 (MainVp+Nvert-1)->xyz[1]=NpointerY;
00926 (MainVp+Nvert-1)->xyz[2]=(rc.bottom-TVlist[i].y)*Scale;
00927 TVlist[i].id=Nvert-1;
00928 }
00929 if(Ne == 0)return;
00930 for(i=0;i<Ne;i++)if(TVlist[i].inc)ec++;
00931 if(ec == 0)return;
00932 UpdateEdgeHeap(Nedge+vc);
00933 for(i=0;i<Ne;i++){
00934 if(!TElist[i].inc)continue;
00935 v1=TVlist[TElist[i].v1].id; v2=TVlist[TElist[i].v2].id;
00936 if(v1 >= 0 && v2 >= 0)CreateEdge(v1,v2);
00937 }
00938 }
00939
00940
00941
00942 #include "trace1.c"
00943
00944 #if __WATCOMC__
00945 int APIENTRY LibMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00946 #else
00947 BOOL WINAPI DllMain(HANDLE hDLL, DWORD dwReason, LPVOID lpReserved){
00948 #endif
00949 switch (dwReason) {
00950 case DLL_PROCESS_ATTACH: {
00951 #if __X__MIPS__
00952 if(!_CRT_INIT(hDLL,dwReason,lpReserved))return(int)FALSE;
00953
00954 #endif
00955 hThisInstance=hDLL;
00956 break;
00957 }
00958 case DLL_PROCESS_DETACH:
00959 #if __X__MIPS__
00960 if(!_CRT_INIT(hDLL,dwReason,lpReserved))return(int)FALSE;
00961
00962 #endif
00963 break;
00964 }
00965 return TRUE;
00966 }
00967
00968 #if __SC__
00969 #pragma startaddress(DllMain)
00970 #endif
00971
00972 BOOL _TraceOutline(
00973 HWND parent_window, HWND info_window,
00974 char *filename,X__STRUCTURE *lpX__in){
00975 tracetool=0;
00976 hParent=parent_window;
00977 hInfo=info_window;
00978 lpEVI=lpX__in;
00979 #include "keyfile.c"
00980 strcpy(ghFilename,filename);
00981 return Viewer();
00982 }