//----------------------------------------------------------------------------- // Velmi jednoduchy prohlizec souboru typu SLD (Slide) // // Autor: Pavel Tisnovsky // //----------------------------------------------------------------------------- #ifdef __BORLANDC__ #include <windows.h> #endif #include <GL/glut.h> // hlavickovy soubor funkci GLUTu a OpenGL #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <ctype.h> #define WINDOW_TITLE "simple SVG viewer" // titulek okna #define WINDOW_WIDTH 800 // pocatecni velikost okna #define WINDOW_HEIGHT 600 // typ prikazu typedef enum { ABSOLUTE_VECTOR, OFFSET_VECTOR, SOLID_FILL, END_POINT, NEW_COLOR } Command; typedef struct AbsoluteVector { short int x1; short int y1; short int x2; short int y2; } AbsoluteVector; typedef struct OffsetVector { signed char x1; signed char y1; signed char x2; signed char y2; } OffsetVector; typedef struct SolidFill { } SolidFill; typedef struct EndPoint { signed char x; signed char y; } EndPoint; typedef struct NewColor { unsigned char color; } NewColor; // jeden zaznam ziskany ze souboru HPGL typedef struct Item { Command cmd; // prikaz struct Item *next; // vazba v linearnim seznamu union { // anonymni unie AbsoluteVector *absoluteVector; OffsetVector *offsetVector; SolidFill *solidFill; EndPoint *endPoint; NewColor *newColor; }; } Item; double scale=1.0; double xpos=0.0; double ypos=0.0; int redraw=1; Item *p_first; // ukazatele v linearnim seznamu Item *p_last; // informace o okne struct { int width; int height; } window={WINDOW_WIDTH, WINDOW_HEIGHT}; // informace o mysi struct { int status; int xtran0, xtran1, xtran2; int ytran0, ytran1, ytran2; int ztran0, ztran1, ztran2; } mouse={0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; //----------------------------------------------------------------------------- // Inicializace linearniho seznamu //----------------------------------------------------------------------------- void initItem(void) { p_first=NULL; p_last=NULL; } //----------------------------------------------------------------------------- // Vlozeni polozky do linearniho seznamu //----------------------------------------------------------------------------- void addAbsoluteVector(AbsoluteVector *absoluteVector) { Item *item=(Item*)malloc(sizeof(Item)); item->cmd=ABSOLUTE_VECTOR; item->next=NULL; // prvek bude umisten na konci seznamu item->absoluteVector=absoluteVector; // seznam je prazdny if (p_first==NULL) { p_first=item; // prvni i posledni prvek p_last=item; // seznamu jsou shodne } // pridani polozky do neprazdneho seznamu else { p_last->next=item; // zretezeni prvku na konec seznamu p_last=item; // aktualizace ukazatele na posledni prvek } } //----------------------------------------------------------------------------- // Vlozeni polozky do linearniho seznamu //----------------------------------------------------------------------------- void addOffsetVector(OffsetVector *offsetVector) { Item *item=(Item*)malloc(sizeof(Item)); item->cmd=OFFSET_VECTOR; item->next=NULL; // prvek bude umisten na konci seznamu item->offsetVector=offsetVector; // seznam je prazdny if (p_first==NULL) { p_first=item; // prvni i posledni prvek p_last=item; // seznamu jsou shodne } // pridani polozky do neprazdneho seznamu else { p_last->next=item; // zretezeni prvku na konec seznamu p_last=item; // aktualizace ukazatele na posledni prvek } } //----------------------------------------------------------------------------- // Vlozeni polozky do linearniho seznamu //----------------------------------------------------------------------------- void addSolidFill(SolidFill *solidFill) { Item *item=(Item*)malloc(sizeof(Item)); item->cmd=SOLID_FILL; item->next=NULL; // prvek bude umisten na konci seznamu item->solidFill=solidFill; // seznam je prazdny if (p_first==NULL) { p_first=item; // prvni i posledni prvek p_last=item; // seznamu jsou shodne } // pridani polozky do neprazdneho seznamu else { p_last->next=item; // zretezeni prvku na konec seznamu p_last=item; // aktualizace ukazatele na posledni prvek } } //----------------------------------------------------------------------------- // Vlozeni polozky do linearniho seznamu //----------------------------------------------------------------------------- void addEndPoint(EndPoint *endPoint) { Item *item=(Item*)malloc(sizeof(Item)); item->cmd=END_POINT; item->next=NULL; // prvek bude umisten na konci seznamu item->endPoint=endPoint; // seznam je prazdny if (p_first==NULL) { p_first=item; // prvni i posledni prvek p_last=item; // seznamu jsou shodne } // pridani polozky do neprazdneho seznamu else { p_last->next=item; // zretezeni prvku na konec seznamu p_last=item; // aktualizace ukazatele na posledni prvek } } //----------------------------------------------------------------------------- // Vlozeni polozky do linearniho seznamu //----------------------------------------------------------------------------- void addNewColor(NewColor *newColor) { Item *item=(Item*)malloc(sizeof(Item)); item->cmd=NEW_COLOR; item->next=NULL; // prvek bude umisten na konci seznamu item->newColor=newColor; // seznam je prazdny if (p_first==NULL) { p_first=item; // prvni i posledni prvek p_last=item; // seznamu jsou shodne } // pridani polozky do neprazdneho seznamu else { p_last->next=item; // zretezeni prvku na konec seznamu p_last=item; // aktualizace ukazatele na posledni prvek } } //----------------------------------------------------------------------------- // Precteni SLD souboru //----------------------------------------------------------------------------- int readItems(char *fileName) { char header[31]; FILE *fin=fopen(fileName, "rb"); if (!fin) return 0; // nacteni hlavicky //printf("%d\n", ftell(fin)); fread(header, 31, 1, fin); //printf("%d\n", ftell(fin)); puts(header); // smycka, ve ktere se zanalyzuje cely soubor typu SLD while(1) { int b1; int b2; b1=fgetc(fin); b2=fgetc(fin); // test na ukonceni smycky -> konec souboru if (b1==EOF || b2==EOF) break; printf("(%6d) %02x %02x\t", ftell(fin), b1, b2); if (b2>=0x00 && b2<=0x7f) { unsigned char array[6]; AbsoluteVector *a=(AbsoluteVector*)malloc(sizeof(AbsoluteVector)); puts("absolute vector"); fread(array, 6, 1, fin); a->x1=(b2<<8)+b1; a->y1=array[0]+(array[1]<<8); a->x2=array[2]+(array[3]<<8); a->y2=array[4]+(array[5]<<8); addAbsoluteVector(a); } else { switch (b2) { case 0xfb: // offset vektor puts("offset"); signed char array[3]; OffsetVector *o=(OffsetVector*)malloc(sizeof(OffsetVector)); fread(array, 3, 1, fin); o->x1=b1; o->y1=array[0]; o->x2=array[1]; o->y2=array[2]; addOffsetVector(o); break; case 0xfc: // konec souboru puts("end of file"); break; case 0xfd: // vypln - neimplementovano puts("solid fill"); fread(header, 4, 1, fin); break; case 0xfe: // koncovy bod vektoru (relativni) puts("endpoint vector"); signed char y=fgetc(fin); EndPoint *e=(EndPoint*)malloc(sizeof(EndPoint)); e->x=b1; e->y=y; addEndPoint(e); break; case 0xff: puts("new color"); NewColor *c=(NewColor*)malloc(sizeof(NewColor)); c->color=b1; addNewColor(c); break; default: puts("undefined"); break; } } } fclose(fin); return 1; } //----------------------------------------------------------------------------- // Prekresleni vektorove kresby //----------------------------------------------------------------------------- void redrawDrawing(double scale, // meritko obrazce double xpos, // posun obrazce double ypos) { // velmi zjednodusena paleta static float palette[][3]={ {1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}, {0.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, {1.0, 0.0, 1.0}, {1.0, 1.0, 0.0}, {0.5, 0.5, 0.5}, }; Item *item=p_first; int x1=0, y1=0, x2=0, y2=0; float r=1.0, g=1.0, b=1.0; // barva kresliciho pera float scale2=mouse.ztran0/100.0+1.0; // zmena meritka zadana mysi unsigned char c; // posun a zmena meritka kresby glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(xpos, ypos, 0); // posun zadany klavesnici glTranslatef(mouse.xtran0, -mouse.ytran0, 0); // posun zadany mysi // posunuti pocatku (pro zmenu meritka vuci stredu okna // je nutna mala programova uprava) glTranslatef(window.width/2, window.height/2, 0); glScalef(scale, scale, scale); // zmena meritka zadana klavesnici glScalef(scale2, scale2, scale2); // zmena meritka zadana mysi glScalef(0.1, 0.1, 0.1); glTranslatef(-window.width/2, -window.height/2, 0); glColor3f(1.0, 1.0, 1.0); // projit celym seznamem a aplikovat v nem ulozene prikazy while (item!=NULL) { Command cmd=item->cmd; // nacist prikaz switch (cmd) { case ABSOLUTE_VECTOR: // absolutni vektor - dva body x1=item->absoluteVector->x1; y1=item->absoluteVector->y1; x2=item->absoluteVector->x2; y2=item->absoluteVector->y2; glBegin(GL_LINES); glVertex2i((int)x1, (int)y1); glVertex2i((int)x2, (int)y2); glEnd(); break; case OFFSET_VECTOR: // relativni vektor - dva body x2=x1+item->offsetVector->x1; y2=y1+item->offsetVector->y1; x1=x1+item->offsetVector->x1; y1=y1+item->offsetVector->y1; glBegin(GL_LINES); glVertex2i((int)x1, (int)y1); glVertex2i((int)x2, (int)y2); glEnd(); break; case END_POINT: // koncovy bod vektoru x2=x1+item->endPoint->x; y2=y1+item->endPoint->y; glBegin(GL_LINES); glVertex2i((int)x1, (int)y1); glVertex2i((int)x2, (int)y2); glEnd(); x1=x2; y1=y2; break; case SOLID_FILL: // neimplementovano break; case NEW_COLOR: // nastaveni barvy c=item->newColor->color; r=palette[c & 0x07][0]; g=palette[c & 0x07][1]; b=palette[c & 0x07][2]; glColor3f(r, g, b); break; default: // ostatni prikazy ignorujeme break; } item=item->next; // prechod na dalsi polozku } } //----------------------------------------------------------------------------- // Funkce volana pro inicializaci vykreslovani //----------------------------------------------------------------------------- void onInit(void) { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // barva pozadi glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // mod ulozeni pixelu glPointSize(1.0f); glLineWidth(1.0f); glEnable(GL_POINT_SMOOTH); glEnable(GL_LINE_SMOOTH); } //----------------------------------------------------------------------------- // Nastaveni souradneho systemu v zavislosti na velikosti okna //----------------------------------------------------------------------------- void onResize(int w, int h) // argumenty w a h reprezentuji novou velikost okna { glViewport(0, 0, w, h); // viditelna oblast pres cele okno glMatrixMode(GL_PROJECTION); // zacatek modifikace projekcni matice glLoadIdentity(); // vymazani projekcni matice (=identita) glOrtho(0, w, 0, h, -1, 1); // mapovani abstraktnich souradnic do souradnic okna window.width=w; window.height=h; } //----------------------------------------------------------------------------- // Tato callback funkce je zavolana pri kazdem prekresleni okna //----------------------------------------------------------------------------- void onDisplay(void) { glClear(GL_COLOR_BUFFER_BIT); // vymazani vsech bitovych rovin barvoveho bufferu glDrawBuffer(GL_BACK); // pixmapa se bude kreslit do zadniho barvoveho bufferu redrawDrawing(scale, xpos, ypos); glFlush(); // provedeni a vykresleni vsech zmen glutSwapBuffers(); } //----------------------------------------------------------------------------- // Tato callback funkce je zavolana pri stlaceni ASCII klavesy //----------------------------------------------------------------------------- #ifdef __BORLANDC__ #pragma option -w-par #endif void onKeyboard(unsigned char key, int x, int y) { key=(key>='A' && key<='Z') ? key-'A'+'a': key; if (key>='0' && key<='9') { glutPostRedisplay(); } // nastaveni barvove palety switch (key) { case 27: // pokud byla stlacena klavesa ESC, konec programu case 'q': exit(0); break; // totez co klavesa ESC default: break; } } #ifdef __BORLANDC__ #pragma option -w+par #endif //----------------------------------------------------------------------------- // Tato callback funkce je zavolana pri stlaceni non-ASCII klavesy //----------------------------------------------------------------------------- #ifdef __BORLANDC__ #pragma option -w-par #endif void onSpecial(int key, int x, int y) { // posun kresby a zmena meritka switch (key) { case GLUT_KEY_LEFT: xpos-=5; redraw=1; glutPostRedisplay(); break; case GLUT_KEY_RIGHT: xpos+=5; redraw=1; glutPostRedisplay(); break; case GLUT_KEY_UP: ypos+=5; redraw=1; glutPostRedisplay(); break; case GLUT_KEY_DOWN: ypos-=5; redraw=1; glutPostRedisplay(); break; case GLUT_KEY_PAGE_UP: scale*=1.1; redraw=1; glutPostRedisplay(); break; case GLUT_KEY_PAGE_DOWN: scale/=1.1; redraw=1; glutPostRedisplay(); break; default: break; } } #ifdef __BORLANDC__ #pragma option -w+par #endif //----------------------------------------------------------------------------- // Tato callback funkce je zavolana pri stlaceni ci pusteni tlacitka mysi //----------------------------------------------------------------------------- void onMouse(int button, int state, int x, int y) { switch (button) { case GLUT_LEFT_BUTTON: // posun kresby if (state==GLUT_DOWN) { mouse.status=1; mouse.xtran1=x; mouse.ytran1=y; } else { mouse.status=0; mouse.xtran2=mouse.xtran0; mouse.ytran2=mouse.ytran0; } break; case GLUT_RIGHT_BUTTON: // zmena meritka kresby if (state==GLUT_DOWN) { mouse.status=2; mouse.ztran1=y; } else { mouse.status=0; mouse.ztran2=mouse.ztran0; } break; default: break; } } //----------------------------------------------------------------------------- // Tato callback funkce je zavolana pri posunu kurzoru mysi //----------------------------------------------------------------------------- void onMouseMotion(int x, int y) { switch (mouse.status) { case 1: // posun kresby mouse.xtran0=mouse.xtran2+x-mouse.xtran1; mouse.ytran0=mouse.ytran2+y-mouse.ytran1; glutPostRedisplay(); break; case 2: // zmena meritka kresby mouse.ztran0=mouse.ztran2+y-mouse.ztran1; glutPostRedisplay(); break; default: break; } } //----------------------------------------------------------------------------- // Hlavni funkce konzolove aplikace //----------------------------------------------------------------------------- int main(int argc, char **argv) { glutInit(&argc, argv); // inicializace knihovny GLUT glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutCreateWindow(WINDOW_TITLE); // vytvoreni okna pro kresleni glutReshapeWindow(WINDOW_WIDTH, WINDOW_HEIGHT);// zmena velikosti okna glutPositionWindow(100, 100); // pozice leveho horniho rohu okna glutDisplayFunc(onDisplay); // registrace funkce volane pri prekreslovani okna glutReshapeFunc(onResize); // registrace funkce volane pri zmene velikosti okna glutKeyboardFunc(onKeyboard); // registrace funkce volane pri stlaceni klavesy glutSpecialFunc(onSpecial); // registrace funkce volane pri stlaceni specialni klavesy glutMouseFunc(onMouse); // funkce volana pri stlaceni tlacitka mysi glutMotionFunc(onMouseMotion); // funkce volana pri posunu mysi onInit(); // inicializace vykreslovani if (!readItems(argv[1])) return 0; // nacteni celeho souboru s kresbou glutMainLoop(); // nekonecna smycka, kde se volaji zaregistrovane funkce return 0; // navratova hodnota vracena operacnimu systemu } //----------------------------------------------------------------------------- // finito //-----------------------------------------------------------------------------