OSDN Git Service

イニシャルコミット。
[marathon/ShapeFusion.git] / Shapes / ShapesDocument.cpp
1 /*
2  * This file is part of ShapeFusion (Copyright 2000 Tito Dal Canton)
3  *
4  * ShapeFusion is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * ShapeFusion is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with ShapeFusion; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18
19 #include "wx/wxprec.h"
20
21 #ifndef WX_PRECOMP
22 #include "wx/wx.h"
23 #endif
24 #include "wx/datstrm.h"
25 #include "ShapesDocument.h"
26
27 IMPLEMENT_DYNAMIC_CLASS(ShapesDocument, wxDocument)
28
29 ShapesDocument::ShapesDocument():
30         wxDocument(), ShapesElement(false)
31 {
32
33 }
34
35 ShapesDocument::~ShapesDocument()
36 {
37
38 }
39
40 unsigned int ShapesDocument::CollectionCount(void) const
41 {
42         return mCollections.size();
43 }
44
45 // collection data access
46 int ShapesDocument::CollectionStatus(unsigned int id)
47 {
48         return mCollections[id]->Status();
49 }
50
51 unsigned int ShapesDocument::CollectionFlags(unsigned int id) const
52 {
53         return mCollections[id]->Flags();
54 }
55
56 bool ShapesDocument::CollectionDefined(unsigned int id, unsigned int chunk) const
57 {
58         return mCollections[id]->Defined(chunk);
59 }
60
61 int ShapesDocument::CollectionVersion(unsigned int id, unsigned int chunk) const
62 {
63         return mCollections[id]->Version(chunk);
64 }
65
66 int ShapesDocument::CollectionType(unsigned int id, unsigned int chunk) const
67 {
68         return mCollections[id]->Type(chunk);
69 }
70
71 unsigned int ShapesDocument::CollectionFlags(unsigned int id, unsigned int chunk) const
72 {
73         return mCollections[id]->Flags(chunk);
74 }
75
76 int ShapesDocument::CollectionScaleFactor(unsigned int id, unsigned int chunk) const
77 {
78         return mCollections[id]->ScaleFactor(chunk);
79 }
80
81 unsigned int ShapesDocument::CollectionBitmapCount(unsigned int id, unsigned int chunk) const
82 {
83         return mCollections[id]->BitmapCount(chunk);
84 }
85
86 unsigned int ShapesDocument::CollectionColorTableCount(unsigned int id, unsigned int chunk) const
87 {
88         return mCollections[id]->ColorTableCount(chunk);
89 }
90
91 unsigned int ShapesDocument::CollectionFrameCount(unsigned int id, unsigned int chunk) const
92 {
93         return mCollections[id]->FrameCount(chunk);
94 }
95
96 unsigned int ShapesDocument::CollectionSequenceCount(unsigned int id, unsigned int chunk) const
97 {
98         return mCollections[id]->SequenceCount(chunk);
99 }
100
101 ShapesColorTable *ShapesDocument::GetColorTable(unsigned int coll, unsigned int chunk, unsigned int ct) const
102 {
103         return mCollections[coll]->GetColorTable(chunk, ct);
104 }
105
106 ShapesBitmap *ShapesDocument::GetBitmap(unsigned int coll, unsigned int chunk, unsigned int bitmap) const
107 {
108         return mCollections[coll]->GetBitmap(chunk, bitmap);
109 }
110
111 ShapesFrame *ShapesDocument::GetFrame(unsigned int coll, unsigned int chunk, unsigned int frame) const
112 {
113         return mCollections[coll]->GetFrame(chunk, frame);
114 }
115
116 ShapesSequence *ShapesDocument::GetSequence(unsigned int coll, unsigned int chunk, unsigned int seq) const
117 {
118         return mCollections[coll]->GetSequence(chunk, seq);
119 }
120
121 ShapesChunk* ShapesDocument::GetChunk(unsigned int coll, unsigned int chunk) const
122 {
123         return mCollections[coll]->GetChunk(chunk);
124 }
125
126 // collection alteration
127 void ShapesDocument::InsertColorTable(ShapesColorTable *ct, unsigned int coll, unsigned int chunk)
128 {
129         mCollections[coll]->InsertColorTable(ct, chunk);
130 }
131
132 void ShapesDocument::DeleteColorTable(unsigned int coll, unsigned int chunk, unsigned int ct)
133 {
134         mCollections[coll]->DeleteColorTable(chunk, ct);
135 }
136
137 void ShapesDocument::InsertBitmap(ShapesBitmap *b, unsigned int coll, unsigned int chunk)
138 {
139         mCollections[coll]->InsertBitmap(b, chunk);
140 }
141
142 void ShapesDocument::DeleteBitmap(unsigned int coll, unsigned int chunk, unsigned int b)
143 {
144         mCollections[coll]->DeleteBitmap(chunk, b);
145 }
146
147 void ShapesDocument::InsertFrame(ShapesFrame *f, unsigned int coll, unsigned int chunk)
148 {
149         mCollections[coll]->InsertFrame(f, chunk);
150 }
151
152 void ShapesDocument::DeleteFrame(unsigned int coll, unsigned int chunk, unsigned int f)
153 {
154         mCollections[coll]->DeleteFrame(chunk, f);
155 }
156
157 void ShapesDocument::InsertSequence(ShapesSequence *s, unsigned int coll, unsigned int chunk)
158 {
159         mCollections[coll]->InsertSequence(s, chunk);
160 }
161
162 void ShapesDocument::DeleteSequence(unsigned int coll, unsigned int chunk, unsigned int s)
163 {
164         mCollections[coll]->DeleteSequence(chunk, s);
165 }
166
167 bool ShapesDocument::DoOpenDocument(const wxString& file)
168 {
169         bool wxOpen = wxDocument::DoOpenDocument(file);
170         
171         if (!(wxOpen && mGoodData)) {
172                 wxLogError(wxT("[ShapesDocument] There was an error while loading, see log"));
173                 return false;
174         }
175         return true;
176 }
177
178 #if wxUSE_STD_IOSTREAM
179 wxSTD ostream& ShapesDocument::SaveObject(wxSTD ostream& stream)
180 #else
181 wxOutputStream& ShapesDocument::SaveObject(wxOutputStream& stream)
182 #endif
183 {
184         unsigned int    collectionCount = CollectionCount();
185         
186         // compose and write the collection header block
187         BigEndianBuffer raw_headers(SIZEOF_collection_header * collectionCount);
188         long                    running_offset = SIZEOF_collection_header * collectionCount;
189
190         for (unsigned int i = 0; i < collectionCount; i++) {
191                 ShapesCollection        *coll = mCollections[i];
192
193                 raw_headers.WriteShort(coll->Status());
194                 raw_headers.WriteUShort(coll->Flags());
195                 // 8-bit version
196                 if (coll->Defined(COLL_VERSION_8BIT)) {
197                         unsigned int    collSize = coll->SizeInFile(COLL_VERSION_8BIT);
198
199                         raw_headers.WriteLong(running_offset);
200                         raw_headers.WriteLong(collSize);
201                         running_offset += collSize;
202                 } else {
203                         raw_headers.WriteLong(-1);
204                         raw_headers.WriteLong(0);
205                 }
206                 // truecolor version
207                 if (coll->Defined(COLL_VERSION_TRUECOLOR)) {
208                         unsigned int    collSize = coll->SizeInFile(COLL_VERSION_TRUECOLOR);
209
210                         raw_headers.WriteLong(running_offset);
211                         raw_headers.WriteLong(collSize);
212                         running_offset += collSize;
213                 } else {
214                         raw_headers.WriteLong(-1);
215                         raw_headers.WriteLong(0);
216                 }
217                 raw_headers.WriteZeroes(12);
218         }
219 #if wxUSE_STD_IOSTREAM
220         stream.write((char *)raw_headers.Data(), raw_headers.Size());
221 #else
222         stream.Write((char *)raw_headers.Data(), raw_headers.Size());
223 #endif
224         
225         // write collections
226         for (unsigned int i = 0; i < collectionCount; i++)
227                 mCollections[i]->SaveObject(stream);
228         
229         return stream;
230 }
231
232 #if wxUSE_STD_IOSTREAM
233 wxSTD ostream& ShapesDocument::SavePatch(wxSTD ostream& stream, const ShapesDocument& other)
234 #else
235 wxOutputStream& ShapesDocument::SavePatch(wxOutputStream& stream, const ShapesDocument& other)
236 #endif
237 {
238         if (mCollections.size() != other.mCollections.size()) {
239                 wxLogError(wxT("[ShapesDocument] Shapes files must contain the same number of collections to generate a patch"));
240                 return stream;
241         }
242
243         // 8-bit versions
244         for (unsigned int i = 0; i < mCollections.size(); ++i) {
245                 mCollections[i]->SavePatch(stream, *other.mCollections[i], i, 0);
246         }
247
248         for (unsigned int i = 0; i < mCollections.size(); ++i) {
249                 mCollections[i]->SavePatch(stream, *other.mCollections[i], i, 1);
250         }
251
252         return stream;
253 }
254
255 #if wxUSE_STD_IOSTREAM
256 wxSTD istream& ShapesDocument::LoadObject(wxSTD istream& stream)
257 #else
258 wxInputStream& ShapesDocument::LoadObject(wxInputStream& stream)
259 #endif
260 {
261         mGoodData = false;
262         
263         // first check file size to immediately rule out invalid stuff
264 #if wxUSE_STD_IOSTREAM
265         stream.seekg(0, std::ios::end);
266         wxInt32 filesize = stream.tellg();
267         stream.seekg(0, std::ios::beg);
268 #else
269         wxInt32 filesize = stream.GetSize();
270 #endif
271         if (filesize < COLLECTIONS_PER_FILE * SIZEOF_collection_header) {
272                 wxLogError(wxT("[ShapesDocument] File too small to be a Marathon shapes file"));
273                 return stream;
274         }
275
276         // find how many collections are stored and load them
277         unsigned int    i = 0;
278
279         while (true) {
280                 ShapesCollection        *c = new ShapesCollection(IsVerbose());
281
282                 if (IsVerbose())
283                         wxLogDebug(wxT("[ShapesDocument] Trying to load collection %d"), i);
284
285 #if wxUSE_STD_IOSTREAM
286                 stream.seekg(i * SIZEOF_collection_header, std::ios::beg);
287 #else
288                 stream.SeekI(i * SIZEOF_collection_header);
289 #endif
290                 c->LoadObject(stream);
291
292                 if (c->IsGood()) {
293                         mCollections.push_back(c);
294                         i++;
295                 } else {
296                         break;
297                 }
298         }
299         if (i >= COLLECTIONS_PER_FILE)
300                 mGoodData = true;
301         else
302                 wxLogError(wxT("[ShapesDocument] Could not find enough collections. This may not be a Marathon Shapes file."));
303
304         return stream;
305 }
306
307 #if wxUSE_STD_IOSTREAM
308 bool ShapesDocument::LoadPatch(wxSTD istream& stream)
309 #else
310 bool ShapesDocument::LoadPatch(wxInputStream& stream)
311 #endif
312 {
313 #if wxUSE_STD_IOSTREAM
314         stream.seekg(0, std::ios::end);
315         wxInt32 filesize = stream.tellg();
316         stream.seekg(0, std::ios::beg);
317 #else
318         wxInt32 filesize = stream.GetSize();
319 #endif
320
321         // memory is cheap, read the whole thing in
322         BigEndianBuffer buffer(filesize);
323         
324 #if wxUSE_STD_IOSTREAM
325         stream.read((char *) buffer.Data(), buffer.Size());
326 #else
327         stream.Read((char *) buffer.Data(), buffer.Size());
328 #endif
329
330         while (buffer.Position() < buffer.Size()) {
331                 long collection = buffer.ReadLong();
332                 if (collection < mCollections.size()) {
333                         mCollections[collection]->LoadPatch(buffer);
334                         if (!mCollections[collection]->IsGood()) {
335                                 return false;
336                         }
337                 } else {
338                         wxLogError(wxT("Shapes patches cannot add entire collections"));
339                         return false;
340                 }
341         }
342
343         return true;
344 }