Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 2002-10-29 |
2 | // Created by: Michael SAZONOV | |
973c2be1 | 3 | // Copyright (c) 2002-2014 OPEN CASCADE SAS |
b311480e | 4 | // |
973c2be1 | 5 | // This file is part of Open CASCADE Technology software library. |
b311480e | 6 | // |
d5f74e42 | 7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published | |
973c2be1 | 9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT | |
11 | // distribution for complete text of the license and disclaimer of any warranty. | |
b311480e | 12 | // |
973c2be1 | 13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. | |
7fd59977 | 15 | |
42cf5bc1 | 16 | |
7fd59977 | 17 | #include <BinLDrivers.hxx> |
42cf5bc1 | 18 | #include <BinLDrivers_DocumentSection.hxx> |
19 | #include <BinLDrivers_DocumentStorageDriver.hxx> | |
7fd59977 | 20 | #include <BinLDrivers_Marker.hxx> |
21 | #include <BinMDF_ADriver.hxx> | |
42cf5bc1 | 22 | #include <BinMDF_ADriverTable.hxx> |
7fd59977 | 23 | #include <BinObjMgt_Persistent.hxx> |
24 | #include <CDM_Application.hxx> | |
42cf5bc1 | 25 | #include <CDM_Document.hxx> |
26 | #include <CDM_MessageDriver.hxx> | |
7fd59977 | 27 | #include <FSD_BinaryFile.hxx> |
28 | #include <FSD_FileHeader.hxx> | |
4ff92abe | 29 | #include <OSD_OpenFile.hxx> |
7fd59977 | 30 | #include <PCDM_ReadWriter.hxx> |
31 | #include <Standard_ErrorHandler.hxx> | |
42cf5bc1 | 32 | #include <Standard_Type.hxx> |
7fd59977 | 33 | #include <Storage_Schema.hxx> |
42cf5bc1 | 34 | #include <TCollection_AsciiString.hxx> |
35 | #include <TCollection_ExtendedString.hxx> | |
7fd59977 | 36 | #include <TColStd_Array1OfInteger.hxx> |
37 | #include <TColStd_ListIteratorOfListOfInteger.hxx> | |
38 | #include <TColStd_ListOfInteger.hxx> | |
7fd59977 | 39 | #include <TDF_AttributeIterator.hxx> |
40 | #include <TDF_ChildIterator.hxx> | |
41 | #include <TDF_Data.hxx> | |
42cf5bc1 | 42 | #include <TDF_Label.hxx> |
7fd59977 | 43 | #include <TDF_Tool.hxx> |
44 | #include <TDocStd_Document.hxx> | |
45 | ||
92efcf78 | 46 | IMPLEMENT_STANDARD_RTTIEXT(BinLDrivers_DocumentStorageDriver,PCDM_StorageDriver) |
47 | ||
7fd59977 | 48 | #define SHAPESECTION_POS (Standard_CString)"SHAPE_SECTION_POS:" |
49 | ||
50 | //======================================================================= | |
51 | //function : BinLDrivers_DocumentStorageDriver | |
52 | //purpose : Constructor | |
53 | //======================================================================= | |
54 | ||
55 | BinLDrivers_DocumentStorageDriver::BinLDrivers_DocumentStorageDriver () | |
56 | { | |
57 | } | |
58 | ||
7fd59977 | 59 | //======================================================================= |
60 | //function : Write | |
61 | //purpose : | |
62 | //======================================================================= | |
63 | ||
64 | void BinLDrivers_DocumentStorageDriver::Write | |
65 | (const Handle(CDM_Document)& theDocument, | |
66 | const TCollection_ExtendedString& theFileName) | |
67 | { | |
15e8b082 M |
68 | SetIsError(Standard_False); |
69 | SetStoreStatus(PCDM_SS_OK); | |
70 | ||
4ff92abe | 71 | myFileName = theFileName; |
72 | ||
73 | std::ofstream aFileStream; | |
74 | OSD_OpenStream (aFileStream, theFileName, std::ios::out | std::ios::binary); | |
75 | ||
76 | if (aFileStream.is_open() && aFileStream.good()) | |
77 | { | |
78 | Write (theDocument, aFileStream); | |
79 | } | |
80 | else | |
81 | { | |
82 | SetIsError (Standard_True); | |
83 | SetStoreStatus(PCDM_SS_WriteFailure); | |
84 | } | |
85 | } | |
86 | ||
87 | //======================================================================= | |
88 | //function : Write | |
89 | //purpose : | |
90 | //======================================================================= | |
91 | ||
92 | void BinLDrivers_DocumentStorageDriver::Write (const Handle(CDM_Document)& theDoc, Standard_OStream& theOStream) | |
93 | { | |
94 | myMsgDriver = theDoc->Application()->MessageDriver(); | |
7fd59977 | 95 | myMapUnsupported.Clear(); |
96 | ||
7fd59977 | 97 | Handle(TDocStd_Document) aDoc = |
4ff92abe | 98 | Handle(TDocStd_Document)::DownCast(theDoc); |
7fd59977 | 99 | if (aDoc.IsNull()) { |
15e8b082 M |
100 | SetIsError(Standard_True); |
101 | SetStoreStatus(PCDM_SS_Doc_IsNull); | |
7fd59977 | 102 | } |
103 | else { | |
7fd59977 | 104 | // First pass: collect empty labels, assign IDs to the types |
105 | if (myDrivers.IsNull()) | |
106 | myDrivers = AttributeDrivers (myMsgDriver); | |
107 | Handle(TDF_Data) aData = aDoc->GetData(); | |
108 | FirstPass (aData->Root()); | |
109 | ||
110 | // 1. Write info section (including types table) | |
4ff92abe | 111 | WriteInfoSection (aDoc, theOStream); |
112 | ||
7fd59977 | 113 | myTypesMap.Clear(); |
15e8b082 M |
114 | if (IsError()) |
115 | { | |
116 | SetStoreStatus(PCDM_SS_Info_Section_Error); | |
117 | return; | |
118 | } | |
7fd59977 | 119 | |
7fd59977 | 120 | |
7fd59977 | 121 | |
122 | // 2. Write the Table of Contents of Sections | |
4ff92abe | 123 | BinLDrivers_VectorOfDocumentSection::Iterator anIterS (mySections); |
124 | for (; anIterS.More(); anIterS.Next()) | |
125 | anIterS.ChangeValue().WriteTOC (theOStream); | |
7fd59977 | 126 | |
4ff92abe | 127 | // Shapes Section is the last one, it indicates the end of the table. |
128 | BinLDrivers_DocumentSection aShapesSection (SHAPESECTION_POS, | |
129 | Standard_False); | |
130 | aShapesSection.WriteTOC (theOStream); | |
7fd59977 | 131 | |
132 | // 3. Write document contents | |
4ff92abe | 133 | // (Storage data to the stream) |
134 | myRelocTable.Clear(); | |
135 | myPAtt.Init(); | |
7fd59977 | 136 | |
4ff92abe | 137 | // Write Doc structure |
138 | WriteSubTree (aData->Root(), theOStream); // Doc is written | |
7fd59977 | 139 | |
140 | // 4. Write Shapes section | |
4ff92abe | 141 | WriteShapeSection (aShapesSection, theOStream); |
142 | ||
143 | // Write application-defined sections | |
144 | for (anIterS.Init (mySections); anIterS.More(); anIterS.Next()) { | |
145 | BinLDrivers_DocumentSection& aSection = anIterS.ChangeValue(); | |
146 | const Standard_Size aSectionOffset = (Standard_Size) theOStream.tellp(); | |
147 | WriteSection (aSection.Name(), aDoc, theOStream); | |
148 | aSection.Write (theOStream, aSectionOffset); | |
149 | } | |
150 | ||
151 | // End of processing: close structures and check the status | |
152 | myPAtt.Destroy(); // free buffer | |
153 | myEmptyLabels.Clear(); | |
154 | myMapUnsupported.Clear(); | |
155 | ||
156 | if (!myRelocTable.Extent()) { | |
157 | // No objects written | |
0797d9d3 | 158 | #ifdef OCCT_DEBUG |
4ff92abe | 159 | WriteMessage ("BinLDrivers_DocumentStorageDriver, no objects written"); |
7fd59977 | 160 | #endif |
4ff92abe | 161 | SetIsError(Standard_True); |
162 | SetStoreStatus(PCDM_SS_No_Obj); | |
7fd59977 | 163 | } |
4ff92abe | 164 | myRelocTable.Clear(); |
7fd59977 | 165 | |
4ff92abe | 166 | if (!theOStream) { |
7fd59977 | 167 | // A problem with the stream |
0797d9d3 | 168 | #ifdef OCCT_DEBUG |
169 | TCollection_ExtendedString anErrorStr ("Error: "); | |
170 | WriteMessage (anErrorStr + "BinLDrivers_DocumentStorageDriver, Problem with the file stream, rdstate=" | |
4ff92abe | 171 | + (Standard_Integer )theOStream.rdstate()); |
7fd59977 | 172 | #endif |
15e8b082 | 173 | SetIsError(Standard_True); |
566f8441 | 174 | SetStoreStatus(PCDM_SS_WriteFailure); |
7fd59977 | 175 | } |
176 | ||
177 | } | |
178 | } | |
179 | ||
180 | //======================================================================= | |
181 | //function : UnsupportedAttrMsg | |
9293178b | 182 | //purpose : |
7fd59977 | 183 | //======================================================================= |
184 | ||
185 | void BinLDrivers_DocumentStorageDriver::UnsupportedAttrMsg | |
186 | (const Handle(Standard_Type)& theType) | |
187 | { | |
0797d9d3 | 188 | #ifdef OCCT_DEBUG |
7fd59977 | 189 | static TCollection_ExtendedString aMsg |
190 | ("BinDrivers_DocumentStorageDriver: warning: attribute driver for type "); | |
191 | #endif | |
192 | if (!myMapUnsupported.Contains(theType)) { | |
193 | myMapUnsupported.Add(theType); | |
0797d9d3 | 194 | #ifdef OCCT_DEBUG |
7fd59977 | 195 | WriteMessage (aMsg + theType->Name() + " not found"); |
196 | #endif | |
197 | } | |
198 | } | |
199 | ||
200 | //======================================================================= | |
201 | //function : WriteSubTree | |
202 | //purpose : | |
203 | //======================================================================= | |
204 | ||
205 | void BinLDrivers_DocumentStorageDriver::WriteSubTree | |
206 | (const TDF_Label& theLabel, | |
207 | Standard_OStream& theOS) | |
208 | { | |
209 | // Skip empty labels | |
210 | if (!myEmptyLabels.IsEmpty() && myEmptyLabels.First() == theLabel) { | |
211 | myEmptyLabels.RemoveFirst(); | |
212 | return; | |
213 | } | |
214 | ||
215 | // Write label header: tag | |
216 | Standard_Integer aTag = theLabel.Tag(); | |
217 | #if DO_INVERSE | |
218 | aTag = InverseInt (aTag); | |
219 | #endif | |
220 | theOS.write ((char*)&aTag, sizeof(Standard_Integer)); | |
221 | ||
222 | // Write attributes | |
223 | TDF_AttributeIterator itAtt (theLabel); | |
224 | for ( ; itAtt.More() && theOS; itAtt.Next()) { | |
225 | const Handle(TDF_Attribute)& tAtt = itAtt.Value(); | |
226 | const Handle(Standard_Type)& aType = tAtt->DynamicType(); | |
227 | // Get type ID and driver | |
228 | Handle(BinMDF_ADriver) aDriver; | |
229 | const Standard_Integer aTypeId = myDrivers->GetDriver (aType,aDriver); | |
230 | if (aTypeId > 0) { | |
231 | // Add source to relocation table | |
232 | const Standard_Integer anId = myRelocTable.Add (tAtt); | |
233 | ||
234 | // Create and fill data item | |
235 | myPAtt.SetTypeId (aTypeId); | |
236 | myPAtt.SetId (anId); | |
237 | aDriver->Paste (tAtt, myPAtt, myRelocTable); | |
238 | ||
239 | // Write data to the stream -->!!! | |
240 | theOS << myPAtt; | |
241 | } | |
0797d9d3 | 242 | #ifdef OCCT_DEBUG |
7fd59977 | 243 | else |
244 | UnsupportedAttrMsg (aType); | |
245 | #endif | |
246 | } | |
247 | if (!theOS) { | |
248 | // Problem with the stream | |
249 | return; | |
250 | } | |
251 | ||
252 | // Write the end attributes list marker | |
253 | BinLDrivers_Marker anEndAttr = BinLDrivers_ENDATTRLIST; | |
254 | #if DO_INVERSE | |
255 | anEndAttr = (BinLDrivers_Marker) InverseInt (anEndAttr); | |
256 | #endif | |
257 | theOS.write ((char*)&anEndAttr, sizeof(anEndAttr)); | |
258 | ||
259 | // Process sub-labels | |
260 | TDF_ChildIterator itChld (theLabel); | |
261 | for ( ; itChld.More(); itChld.Next()) | |
262 | { | |
263 | const TDF_Label& aChildLab = itChld.Value(); | |
264 | WriteSubTree (aChildLab, theOS); | |
265 | } | |
266 | ||
267 | // Write the end label marker | |
268 | BinLDrivers_Marker anEndLabel = BinLDrivers_ENDLABEL; | |
269 | #if DO_INVERSE | |
270 | anEndLabel = (BinLDrivers_Marker) InverseInt (anEndLabel); | |
271 | #endif | |
272 | theOS.write ((char*)&anEndLabel, sizeof(anEndLabel)); | |
273 | ||
274 | } | |
275 | ||
7fd59977 | 276 | //======================================================================= |
277 | //function : AttributeDrivers | |
278 | //purpose : | |
279 | //======================================================================= | |
280 | ||
281 | Handle(BinMDF_ADriverTable) BinLDrivers_DocumentStorageDriver::AttributeDrivers | |
282 | (const Handle(CDM_MessageDriver)& theMessageDriver) | |
283 | { | |
284 | return BinLDrivers::AttributeDrivers (theMessageDriver); | |
285 | } | |
286 | ||
287 | //======================================================================= | |
288 | //function : FirstPassSubTree | |
289 | //purpose : | |
290 | //======================================================================= | |
291 | ||
292 | Standard_Boolean BinLDrivers_DocumentStorageDriver::FirstPassSubTree | |
293 | (const TDF_Label& L, | |
294 | TDF_LabelList& ListOfEmptyL) | |
295 | { | |
296 | // are there writable attributes on L ? | |
297 | Standard_Boolean hasAttr = Standard_False; | |
298 | TDF_AttributeIterator itAtt (L); | |
299 | for ( ; itAtt.More(); itAtt.Next()) { | |
300 | const Handle(Standard_Type)& aType = itAtt.Value()->DynamicType(); | |
301 | Handle(BinMDF_ADriver) aDriver; | |
302 | // do not rely on a value returned by GetDriver here, because | |
303 | // the IDs have not yet been assigned to the types | |
304 | myDrivers->GetDriver (aType, aDriver); | |
305 | if (!aDriver.IsNull()) { | |
306 | hasAttr = Standard_True; | |
307 | myTypesMap.Add (aType); | |
308 | } | |
0797d9d3 | 309 | #ifdef OCCT_DEBUG |
7fd59977 | 310 | else |
311 | UnsupportedAttrMsg (aType); | |
312 | #endif | |
313 | } | |
314 | ||
315 | // are there writable attributes on sub-labels ? | |
316 | Standard_Boolean hasChildAttr = Standard_False; | |
317 | TDF_LabelList emptyChildrenList; | |
318 | TDF_ChildIterator itChld (L); | |
319 | for ( ; itChld.More(); itChld.Next()) | |
320 | { | |
321 | if (FirstPassSubTree (itChld.Value(), emptyChildrenList)) | |
322 | emptyChildrenList.Append( itChld.Value() ); | |
323 | else | |
324 | hasChildAttr = Standard_True; | |
325 | } | |
326 | ||
327 | Standard_Boolean isEmpty = !(hasAttr || hasChildAttr); | |
328 | ||
329 | if (!isEmpty) | |
330 | ListOfEmptyL.Append( emptyChildrenList ); | |
331 | ||
332 | return isEmpty; | |
333 | } | |
334 | ||
335 | //======================================================================= | |
336 | //function : FirstPass | |
337 | //purpose : | |
338 | //======================================================================= | |
339 | ||
340 | void BinLDrivers_DocumentStorageDriver::FirstPass | |
341 | (const TDF_Label& theRoot) | |
342 | { | |
343 | myTypesMap.Clear(); | |
344 | myEmptyLabels.Clear(); | |
345 | ||
346 | if (FirstPassSubTree( theRoot, myEmptyLabels)) | |
347 | myEmptyLabels.Append( theRoot ); | |
348 | ||
349 | myDrivers->AssignIds (myTypesMap); | |
350 | } | |
351 | ||
352 | //======================================================================= | |
353 | //function : WriteInfoSection | |
354 | //purpose : Write info secton using FSD_BinaryFile driver | |
355 | //======================================================================= | |
356 | ||
357 | #define START_TYPES "START_TYPES" | |
358 | #define END_TYPES "END_TYPES" | |
359 | ||
4ff92abe | 360 | void BinLDrivers_DocumentStorageDriver::WriteInfoSection |
361 | (const Handle(CDM_Document)& theDoc, | |
362 | Standard_OStream& theOStream) | |
7fd59977 | 363 | { |
4ff92abe | 364 | // Magic number |
365 | theOStream.write (FSD_BinaryFile::MagicNumber(), strlen(FSD_BinaryFile::MagicNumber())); | |
366 | ||
367 | FSD_FileHeader aHeader; | |
368 | ||
369 | { | |
370 | aHeader.testindian = -1; | |
371 | aHeader.binfo = -1; | |
372 | aHeader.einfo = -1; | |
373 | aHeader.bcomment = -1; | |
374 | aHeader.ecomment = -1; | |
375 | aHeader.btype = -1; | |
376 | aHeader.etype = -1; | |
377 | aHeader.broot = -1; | |
378 | aHeader.eroot = -1; | |
379 | aHeader.bref = -1; | |
380 | aHeader.eref = -1; | |
381 | aHeader.bdata = -1; | |
382 | aHeader.edata = -1; | |
383 | } | |
384 | ||
385 | // aHeader.testindian | |
386 | { | |
387 | union { | |
388 | char ti2[4]; | |
389 | Standard_Integer aResult; | |
390 | } aWrapUnion; | |
391 | ||
392 | aWrapUnion.ti2[0] = 1; | |
393 | aWrapUnion.ti2[1] = 2; | |
394 | aWrapUnion.ti2[2] = 3; | |
395 | aWrapUnion.ti2[3] = 4; | |
396 | ||
397 | aHeader.testindian = aWrapUnion.aResult; | |
7fd59977 | 398 | } |
399 | ||
4ff92abe | 400 | // info section |
401 | aHeader.binfo = (Standard_Integer)theOStream.tellp(); | |
402 | ||
403 | // header section | |
404 | aHeader.einfo = aHeader.binfo + FSD_BinaryFile::WriteHeader (theOStream, aHeader, Standard_True); | |
405 | ||
406 | // add format | |
407 | Handle(Storage_Data) theData = new Storage_Data; | |
408 | PCDM_ReadWriter::WriteFileFormat (theData, theDoc); | |
409 | PCDM_ReadWriter::Writer()->WriteReferenceCounter (theData, theDoc); | |
410 | PCDM_ReadWriter::Writer()->WriteReferences (theData, theDoc, myFileName); | |
411 | PCDM_ReadWriter::Writer()->WriteExtensions (theData, theDoc); | |
412 | PCDM_ReadWriter::Writer()->WriteVersion (theData, theDoc); | |
413 | ||
414 | // add the types table | |
415 | theData->AddToUserInfo(START_TYPES); | |
416 | for (Standard_Integer i = 1; i <= myTypesMap.Extent(); i++) | |
7fd59977 | 417 | { |
4ff92abe | 418 | Handle(BinMDF_ADriver) aDriver = myDrivers->GetDriver(i); |
419 | if (!aDriver.IsNull()) | |
420 | { | |
421 | const TCollection_AsciiString& aTypeName = aDriver->TypeName(); | |
422 | theData->AddToUserInfo (aTypeName); | |
7fd59977 | 423 | } |
7fd59977 | 424 | } |
4ff92abe | 425 | theData->AddToUserInfo(END_TYPES); |
426 | ||
427 | Standard_Integer aObjNb = 1; | |
428 | Standard_Integer aShemaVer = 1; | |
429 | ||
430 | aHeader.einfo += FSD_BinaryFile::WriteInfo (theOStream, | |
431 | aObjNb, | |
432 | BinLDrivers::StorageVersion(), | |
433 | Storage_Schema::ICreationDate(), | |
6fe96f84 | 434 | "", // schema name |
4ff92abe | 435 | aShemaVer, |
436 | theData->ApplicationName(), | |
437 | theData->ApplicationVersion(), | |
438 | theData->DataType(), | |
439 | theData->UserInfo(), | |
440 | Standard_True); // only count the size of the section | |
441 | ||
442 | // calculate comment section | |
443 | TColStd_SequenceOfExtendedString aComments; | |
444 | theDoc->Comments(aComments); | |
445 | for (Standard_Integer i = 1; i <= aComments.Length(); i++) | |
446 | { | |
447 | theData->AddToComments (aComments(i)); | |
7fd59977 | 448 | } |
4ff92abe | 449 | |
450 | aHeader.bcomment = aHeader.einfo; | |
451 | aHeader.ecomment = aHeader.bcomment + FSD_BinaryFile::WriteComment(theOStream, theData->Comments(), Standard_True); | |
452 | ||
453 | aHeader.edata = aHeader.ecomment; | |
454 | ||
455 | // write header information | |
456 | FSD_BinaryFile::WriteHeader (theOStream, aHeader); | |
457 | ||
458 | // write info section | |
459 | FSD_BinaryFile::WriteInfo (theOStream, | |
460 | aObjNb, | |
461 | BinLDrivers::StorageVersion(), | |
462 | Storage_Schema::ICreationDate(), | |
6fe96f84 | 463 | "", // schema name |
4ff92abe | 464 | aShemaVer, |
465 | theData->ApplicationName(), | |
466 | theData->ApplicationVersion(), | |
467 | theData->DataType(), | |
468 | theData->UserInfo()); | |
469 | ||
470 | // write the comments | |
471 | FSD_BinaryFile::WriteComment(theOStream, theData->Comments()); | |
472 | ||
7fd59977 | 473 | } |
474 | ||
475 | //======================================================================= | |
476 | //function : WriteMessage | |
477 | //purpose : write theMessage to the MessageDriver of the | |
478 | // Application | |
479 | //======================================================================= | |
480 | ||
481 | void BinLDrivers_DocumentStorageDriver::WriteMessage | |
482 | (const TCollection_ExtendedString& theMsg) | |
483 | { | |
484 | if (!myMsgDriver.IsNull()) | |
485 | myMsgDriver->Write (theMsg.ToExtString()); | |
486 | } | |
487 | ||
488 | //======================================================================= | |
489 | //function : AddSection | |
9293178b | 490 | //purpose : |
7fd59977 | 491 | //======================================================================= |
492 | ||
493 | void BinLDrivers_DocumentStorageDriver::AddSection | |
494 | (const TCollection_AsciiString& theName, | |
495 | const Standard_Boolean isPostRead) | |
496 | { | |
497 | mySections.Append (BinLDrivers_DocumentSection (theName, isPostRead)); | |
498 | } | |
499 | ||
500 | //======================================================================= | |
501 | //function : WriteSection | |
9293178b | 502 | //purpose : |
7fd59977 | 503 | //======================================================================= |
504 | ||
505 | void BinLDrivers_DocumentStorageDriver::WriteSection | |
506 | (const TCollection_AsciiString& /*theName*/, | |
857ffd5e | 507 | const Handle(CDM_Document)& /*theDocument*/, |
7fd59977 | 508 | Standard_OStream& /*theOS*/) |
509 | { | |
510 | // empty; should be redefined in subclasses | |
511 | } | |
512 | ||
513 | //======================================================================= | |
514 | //function : WriteShapeSection | |
515 | //purpose : defines WriteShapeSection | |
516 | //======================================================================= | |
517 | void BinLDrivers_DocumentStorageDriver::WriteShapeSection | |
518 | (BinLDrivers_DocumentSection& theSection, | |
519 | Standard_OStream& theOS) | |
520 | { | |
521 | const Standard_Size aShapesSectionOffset = (Standard_Size) theOS.tellp(); | |
522 | theSection.Write (theOS, aShapesSectionOffset); | |
523 | } |