 |
» |
|
|
 |
If you want to store a display list on file for later retrieval,
you can do so. One basic approach is the following: Determine how many segments there are in the display
list via the routine inq_segment_count. In an array of sufficient size, get a list of the
segment numbers viainq_segment_list. For each segment: Write the segment number to the file. For each element in the segment: Determine the amount of space (in
32-bit words) the element consumes. This information is gotten via
the procedure inq_ele_size. Write the element size to the file. Convert the display list element into an integer
array via inq_ele. Write the integer array to the file.
Write a zero to the file to signal the end of the
segment.
To read in a display list archived by the above procedure,
follow this procedure: While not at end-of-file, do the following: Using the segment number just read from the file,
open the segment. This creates a new, empty segment. Read the element size from the file. While the element size is nonzero, do: Read the integer array from file. Convert the integer array into an element by using
interpret_ele. Read the next element size from the file.
 |  |  |  |  | NOTE: This simple routine does not store/restore segment-
and element-control flags; segments and elements will be restored
with default control flags. If you wish to archive and retrieve
segment- and element-control flags, modify the routine as desired. |  |  |  |  |
The syntax for the routines mentioned above is: inq_segment_count(〈fildes〉,
〈count〉); inq_segment_list(〈fildes〉,
〈list〉); inq_ele_size(〈fildes〉,
〈size〉); inq_ele(〈fildes〉,
〈ele〉); interpret_ele(〈fildes〉,
〈ele〉);
where: 〈count〉
is a pointer to an integer. The returned value specifies how many
segments exist in the display list associated with 〈fildes〉. 〈list〉
is an array of integers into which the list of segment numbers goes. 〈size〉
is a pointer to an integer. The returned value specifies how many
32-bit words are required to contain the integer-array representation
of the element. 〈ele〉
is an array of integers that contains the integer-array representation
of a display list element.
In the following example, the display list (containing the
house) is drawn on the screen. The display list is stored on a file,
the display and the display list are cleared,
the display list is recreated from the data on the file, and it
is then redrawn: In code, it looks like this: refresh_segment(fildes, House); /* draw the house */ write_display_list(fildes, "MyDL"); /* archive display list to a file */ printf("\\n%s\\n%s\\n%s\\n%s\\n", "The display list has been written to a file. When you press [Return],", "both the display and the display list will be erased. After two", "seconds, the display list will be read from the file and redrawn as it", "was before."); getchar(); clear_view_surface(fildes); /* clear the screen */ delete_all_segments(fildes); /* erase the whole display list */ sleep(2); /* satisfy user the image is gone */ read_display_list(fildes, "MyDL"); /* read display list from file */ refresh_segment(fildes, House); /* draw retrieved display list */ |
Here is the whole program:  |
#include <starbase.c.h> /* get Starbase definitions */ #include <dl.c.h> /* get Display List definitions */ #include <stdio.h> /* get standard I/O functions */ #define AppendOff FALSE /* sent to "open_segment" */ #define AppendOn TRUE /* sent to "open_segment" */ #define DisplayOff FALSE /* sent to "open_segment" */ #define DisplayOn TRUE /* sent to "open_segment" */ #define AlwaysCurrent FALSE /* sent to "buffer_mode" */ #define Edges TRUE /* sent to "interior_style" */ #define NoFlags FALSE /* sent to "polygon2d" */ #define House 1 /* \\ */ #define Wall 11 /* \\ */ #define WallSurface 111 /* \\ These mnemonic tokens */ #define Door 112 /* \\ are associated with */ #define Window 113 /* \\ segment numbers that */ #define Frame 1131 /* / indicate the house's */ #define Panes 1132 /* / hierarchical */ #define Roof 12 /* / structure. */ #define RoofSurface 121 /* / */ #define Chimney 122 /* / */ main() /* program "ArchiveDL.c" */ { int fildes; /* file descriptor */ if ((fildes = gopen(getenv("SB_OUTDEV"), OUTDEV, NULL, INIT)) == -1) { fprintf(stderr, "%s %s\\n", "Error: gopen failed using environment", "variable SB_OUTDEV."); exit(-1); } buffer_mode(fildes, AlwaysCurrent); vdc_extent(fildes, 0.0, 0.0, 0.0, 1.25, 1.0, 0.0); view_window(fildes, 0.0, 0.0, 10.0, 8.0); interior_style(fildes, INT_HOLLOW, Edges); /*=== define the display list segments comprising the house ========*/ /*- Section 1: Define the house's structure */ open_segment(fildes, House, AppendOff, DisplayOff); call_segment(fildes, Wall); call_segment(fildes, Roof); close_segment(fildes); /*- Section 1.1: Define the wall's structure -*/ open_segment(fildes, Wall, AppendOff, DisplayOff); call_segment(fildes, WallSurface); call_segment(fildes, Door); call_segment(fildes, Window); close_segment(fildes); /*- Section 1.1.1: Define the wall surface's structure -*/ open_segment(fildes, WallSurface, AppendOff, DisplayOff); rectangle(fildes, 2.0, 1.0, 8.0, 5.0); close_segment(fildes); /*- Section 1.1.2: Define the door's structure -*/ open_segment(fildes, Door, AppendOff, DisplayOff); rectangle(fildes, 2.5, 1.0, 4.2, 4.2); ellipse(fildes, 0.06, 0.06, 2.65, 2.3); close_segment(fildes); /*- Section 1.1.3: Define the window's structure -*/ open_segment(fildes, Window, AppendOff, DisplayOff); call_segment(fildes, Frame); call_segment(fildes, Panes); close_segment(fildes); |
 |
 |
/*- Section 1.1.3.1: Define the window frame's structure -*/ open_segment(fildes, Frame, AppendOff, DisplayOff); rectangle(fildes, 5.0, 2.0, 7.0, 4.0); close_segment(fildes); /*- Section 1.1.3.2: Define the window panes' structure */ open_segment(fildes, Panes, AppendOff, DisplayOff); rectangle(fildes, 5.1, 2.1, 5.95, 2.95); rectangle(fildes, 6.05, 2.1, 6.9, 2.95); rectangle(fildes, 6.05, 3.05, 6.9, 3.9); rectangle(fildes, 5.1, 3.05, 5.95, 3.9); close_segment(fildes); /*- Section 1.2: Define the roof's structure -*/ open_segment(fildes, Roof, AppendOff, DisplayOff); call_segment(fildes, RoofSurface); call_segment(fildes, Chimney); close_segment(fildes); /*- Section 1.2.1: Define the roof surface's structure -*/ open_segment(fildes, RoofSurface, AppendOff, DisplayOff); { static float RoofStructure[3][2] = { 1.0, 5.0, 9.0, 5.0, 5.0, 7.0}; polygon2d(fildes, RoofStructure, 3, NoFlags); } close_segment(fildes); /*- Section 1.2.2: Define the chimney's structure */ open_segment(fildes, Chimney, AppendOff, DisplayOff); { static float ChimneyStructure[4][2] = { 6.0, 6.5, 7.0, 6.0, 7.0, 7.5, 6.0, 7.5}; polygon2d(fildes, ChimneyStructure, 4, NoFlags); } close_segment(fildes); refresh_segment(fildes, House); /* draw the house */ write_display_list(fildes, "MyDL"); /* archive display list to a file */ printf("\\n%s\\n%s\\n%s\\n%s\\n", "The display list has been written to a file. When you press [Return],", "both the display and the display list will be erased. After two", "seconds, the display list will be read from the file and redrawn as it", "was before."); getchar(); clear_view_surface(fildes); /* clear the screen */ delete_all_segments(fildes); /* erase the whole display list */ sleep(2); /* satisfy user the image is gone */ read_display_list(fildes, "MyDL"); /* read display list from file */ refresh_segment(fildes, House); /* draw retrieved display list */ gclose(fildes);
|
 |
 |
}/***************************************************************/ #define MaxSegments 100 #define MaxEleSize 10000 write_display_list(fildes, Pathname) int fildes; /* file descriptor */ char *Pathname; /* name of file on which to write */ { int NumSegments; /* the number of segments */ int Segments[MaxSegments]; /* holds a list of the segments */ int Size; /* how much memory the element needs */ int Element[MaxEleSize]; /* holds the element being written */ FILE *OutFile; /* file on which to put display list */ int AtTop, AtBottom; /* loop control variables */ int Segment; /* loop control variable */ if ((OutFile = fopen(Pathname, "w")) == NULL) { fprintf(stderr, "write_display_list: can't open file %s\\n", Pathname); exit(1); } inq_segment_count(fildes, &NumSegments); /* how many segments in DL? */ if (NumSegments > MaxSegments) { /* array too small? */ fprintf(stderr, "write_display_list: insufficient segment array\\n"); fclose(OutFile); exit(2); } inq_segment_list(fildes, Segments); /* get list of segments */ for (Segment = 0; Segment < NumSegments; Segment++) { fwrite(&Segments[Segment], sizeof(int), 1, OutFile); open_segment(fildes, Segments[Segment], AppendOff, DisplayOff); set_ele_ptr(fildes, 0); inq_ele_ptr_at_bound(fildes, &AtTop, &AtBottom); while (!AtBottom) { set_ele_ptr_relative(fildes, 1); inq_ele_size(fildes, &Size); if (Size > MaxEleSize) { fprintf(stderr, "write_display_list: %s\\n", "insufficient element array"); close_segment(fildes); fclose(OutFile); exit(3); } fwrite(&Size, sizeof(int), 1, OutFile); inq_ele(fildes, Element); fwrite(Element, sizeof(int), Size, OutFile); inq_ele_ptr_at_bound(fildes, &AtTop, &AtBottom); } close_segment(fildes); Size = 0; fwrite(&Size, sizeof(int), 1, OutFile); } fclose(OutFile); }
|
 |
 |
/**********************************************************************/ read_display_list(fildes, Pathname) int fildes; /* file descriptor */ char *Pathname; /* name of file from which to read */ { int Size; /* element size (in 32-bit words) */ int Element[MaxEleSize]; /* holds the element being written */ FILE *InFile; /* file on which to put display list */ int Segment; /* loop control variable */ if ((InFile = fopen(Pathname, "r")) == NULL) { fprintf(stderr, "read_display_list: can't open file %s\\n", Pathname); exit(1); } while (fread(&Segment, sizeof(int), 1, InFile) == 1) { open_segment(fildes, Segment, AppendOn, DisplayOff); fread(&Size, sizeof(int), 1, InFile); while (Size > 0) { if (Size > MaxEleSize) { fprintf(stderr, "read_display_list: %s\\n", "insufficient element array"); close_segment(fildes); fclose(InFile); exit(3); } fread(Element, sizeof(int), Size, InFile); interpret_ele(fildes, Element); fread(&Size, sizeof(int), 1, InFile); } close_segment(fildes); } fclose(InFile); } |
|