Integration of OCCT 6.5.0 from SVN
[occt.git] / src / CGM / CGM_Driver.cxx
1 // File:        CGM_Driver.cxx
2 // Created:     Fri Sep 13 12:04:31 1996
3 // Author:      DCB
4 // Copyright:   MatraDatavision 1998
5
6 #define xBUG    //  GG 140699
7 //              Ascendante compatibillity using OLD driver constructor
8 //              must generates directly a file.
9
10 #define IMP020701       //GG
11 //              Don't creates an external reference named error please ...
12 //              Thanks to SAMTECH
13
14 #include <CGM_Driver.ixx>
15 #include <MFT_FontManager.hxx>
16 #include <PlotMgt_TextManager.hxx>
17 #include <PlotMgt_HListOfMFTFonts.hxx>
18 #include <TShort_HArray1OfShortReal.hxx>
19 #include <Aspect_Units.hxx>
20 #include <Aspect_ColorMapEntry.hxx>
21 #include <Aspect_TypeMapEntry.hxx>
22 #include <Aspect_WidthMapEntry.hxx>
23 #include <Aspect_GenericColorMap.hxx>
24 #include <Aspect_RGBPixel.hxx>
25 #include <Aspect_DriverError.hxx>
26 #include <TColStd_DataMapOfIntegerInteger.hxx>
27 #include <OSD_Environment.hxx>
28 #include <cgmlib.hxx>
29
30 #include <AlienImage.hxx>
31 #include <Image_Image.hxx>
32 static Handle(Image_Image) myImage;
33
34 /////////////////////////////////////////////////////////////////////////*/
35 #define TRACE 0
36 #define PPI (float)(72.F/(0.0254005F METER))
37 #define MAXPARAM 1024
38 #define TRANSFORMCOLOR(c) \
39   { if (TypeOfCgm == CgmCharEncoding) c = (((c+1) << 2) - 1); }
40
41 #define DRAD       (PI/180.)
42 #define DEFPLOTTER "DIRECT_CGM"
43
44 //-----------------------------------------------------------------
45 // Standard CGM settings.
46 //-----------------------------------------------------------------
47 #define CGMVER             1
48 #define INTBITS           32
49 #define MAXREAL   32767.0000F // Clear text
50 #define MINREAL  -32768.0000F
51 #define REALBITS          15 // Character encoding
52 #define REALPLACES        -5
53 #define REALDEFEXP         0
54 #define REALEXP            0
55 #define REALFORM           0 // Binary encoding
56 #define REALWHOLE         15
57 #define REALFRACTION      20
58
59 #define INDEXBITS          8
60 #define CLRBITS           16
61 #define CLRINDBITS         8
62 #define SCALEMOD    ABSTRACT
63 #define SCALFACT           1
64 #define IMCOLRPREC     65536
65 #define BACKRED          255
66 #define BACKGREEN        255
67 #define BACKBLUE         255
68
69 //-----------------------------------------------------------------
70 // CGM states.
71 //-----------------------------------------------------------------
72 typedef enum {
73   CgmBinary,
74   CgmCharEncoding,
75   CgmClearText
76 } CgmType;
77
78 typedef enum {
79   mfDesc,
80   picDesc,
81   picBody,
82   imgDraw
83 } CGMstate;
84 static CGMstate myState;
85
86 static TColStd_DataMapOfIntegerInteger aTypeIndex;
87 static CgmType                         TypeOfCgm;
88
89 //Definition of the C handle who handles the CGM metafile
90 FILE* cgmo;
91
92 //Those C arrays are the parameters used by the CGM library.
93 long  ptablong[MAXPARAM];
94 float ptabreal[MAXPARAM];
95 char  ptabchar[MAXPARAM];
96
97 //Declare the array in wich WIDTHS will be put (an internal widthmap).
98 float* WIDTHMAP = NULL;
99
100 // Error string
101 #ifndef IMP020701       
102 char error[1024];
103 #endif
104
105 //=============================================================
106 CGM_Driver::CGM_Driver (const Handle(PlotMgt_Plotter)& aPlotter,
107                         const Standard_CString aName,
108                         const Quantity_Length aDX,
109                         const Quantity_Length aDY,
110                         const Aspect_TypeOfColorSpace aTypeOfColorSpace)
111                       : PlotMgt_PlotterDriver (aPlotter, aName)
112 {
113   BeginFile (aPlotter, aDX, aDY, aTypeOfColorSpace);
114 }
115
116 //=============================================================
117 CGM_Driver::CGM_Driver (const Standard_CString aName,
118                         const Quantity_Length aDX,
119                         const Quantity_Length aDY,
120                         const Aspect_TypeOfColorSpace aTypeOfColorSpace)
121                       : PlotMgt_PlotterDriver (aName)
122 {
123   Handle(PlotMgt_Plotter) thePlotter =
124 #ifdef BUG
125     new PlotMgt_Plotter(TCollection_AsciiString(DEFPLOTTER));
126 #else
127     new PlotMgt_Plotter(TCollection_AsciiString(DEFPLOTTER),Standard_True);
128 #endif
129   BeginFile (thePlotter, aDX, aDY, aTypeOfColorSpace);
130 }
131
132 //=============================================================
133 void CGM_Driver::BeginFile (const Handle(PlotMgt_Plotter)& aPlotter,
134                             const Quantity_Length aDX,
135                             const Quantity_Length aDY,
136                             const Aspect_TypeOfColorSpace aTypeOfColorSpace)
137 {
138   SetPlotter (aPlotter);
139   // Initialization of buffers
140   memset (ptablong, 0, sizeof(ptablong));
141   memset (ptabreal, 0, sizeof(ptabreal));
142   memset (ptabchar, 0, sizeof(ptabchar));
143
144   myWidth            = Standard_ShortReal(aDX - 2*myPaperMargin);
145   myHeight           = Standard_ShortReal(aDY - 2*myPaperMargin);
146   myTypeOfColorSpace = aTypeOfColorSpace;
147
148   // Set the type of CGM file by reading the environment variable "CSF_CGM_Type".
149   OSD_Environment cgmType = OSD_Environment ( "CSF_CGM_Type" );
150   if (cgmType.Value().IsEmpty()) TypeOfCgm = CgmClearText;
151   else {
152     if (cgmType.Value().IsEqual("BIN")) {
153       TypeOfCgm = CgmBinary;
154     } else if (cgmType.Value().IsEqual("CAR")) {
155       TypeOfCgm = CgmCharEncoding;
156     } else if (cgmType.Value().IsEqual("TEX")) {
157       TypeOfCgm = CgmClearText;
158     } else TypeOfCgm = CgmClearText;
159   }
160
161   // Open the CGM metafile
162   cgmo = OPEN_FILE ((Standard_PCharacter)myFileName.ToCString(), TypeOfCgm + 1);
163   if (!cgmo) {
164 #ifdef IMP020701
165     char error[1024];
166 #endif
167     sprintf (error, "****** CGM_Driver ERROR, unable to open file '%s'\n",
168              myFileName.ToCString());
169     Aspect_DriverError::Raise(error);
170   }
171   // Write the metafile descriptor    
172   myFileIsOpened = Standard_True;
173   myState = mfDesc;
174   InitializeDriver (myFileName.ToCString());
175 }
176
177 //=============================================================
178 void CGM_Driver::Close()
179 {
180   if (myFileIsOpened) {
181     // Declare the end of the CGM metafile
182     WriteData (ENDMF, ptablong, ptabreal, ptabchar);
183     // Free memory allocated for WIDTHS
184     if (WIDTHMAP)
185       delete[] WIDTHMAP;
186     // Close the CGM metafile
187     CLOSE_FILE ();
188     myFileIsOpened = Standard_False;
189   }
190   aTypeIndex.Clear ();
191 }
192
193 //=============================================================
194 void CGM_Driver::BeginDraw ()
195 {
196   // Create TextManager
197   myTextManager = new PlotMgt_TextManager(this);
198   //============================================
199   if (myCurrentPage <= 0) myCurrentPage = 1;
200   else                    myCurrentPage++;
201   // Write the picture descriptor in the CGM metafile
202   myState = picDesc;
203   // Declare the new image
204   ptablong[0] = myCurrentPage;
205   WriteData (BEGPIC, ptablong, ptabreal, ptabchar);
206   // Set the color selection mode (always index)
207   old.color_mode = DIRECT;
208   cur.color_mode = INDEXED;
209   WriteData (COLRMODE, ptablong, ptabreal, ptabchar);
210   // Set the scale mode
211   cur.scale_mode = SCALEMOD;
212   cur.scale_factor = (float)SCALFACT;
213   WriteData (SCALEMODE, ptablong, ptabreal, ptabchar);
214   // Set the method to compute line width
215   old.linewidth_mode = SCALED;
216   cur.linewidth_mode = ABS;
217   WriteData (LINEWIDTHMODE, ptablong, ptabreal, ptabchar);
218   //Set the method to compute edge width
219   old.edgewidth_mode = SCALED;
220   cur.edgewidth_mode = ABS;
221   WriteData (EDGEWIDTHMODE, ptablong, ptabreal, ptabchar);
222   // Declare the window in which the picture will be drawn
223   cur.vdc_extent.a.x.real = (float)0;
224   cur.vdc_extent.a.y.real = (float)0;
225   cur.vdc_extent.b.x.real = myWidth;
226   cur.vdc_extent.b.y.real = myHeight;
227   WriteData (VDCEXT, ptablong, ptabreal, ptabchar);
228   // set the background color
229   cur.back.red   = BACKRED;    TRANSFORMCOLOR (cur.back.red);
230   cur.back.green = BACKGREEN;  TRANSFORMCOLOR (cur.back.green);
231   cur.back.blue  = BACKBLUE;   TRANSFORMCOLOR (cur.back.blue);
232   WriteData (BACKCOLR, ptablong, ptabreal, ptabchar);
233   // Declare the body of the picture
234   WriteData (BEGPICBODY, ptablong, ptabreal, ptabchar);
235   myState = picBody;
236   // Write color map in the picture body
237   InitializeColorMap(ColorMap ());
238   // Set clipping rectangle
239   cur.clip_rect.a.x.real = (float)0;
240   cur.clip_rect.a.y.real = (float)0;
241   cur.clip_rect.b.x.real = myWidth;
242   cur.clip_rect.b.y.real = myHeight;
243   WriteData (CLIPRECT, ptablong, ptabreal, ptabchar);
244   // Set clip indicator to ON
245   cur.clip_ind = ON;
246   WriteData (CLIP, ptablong, ptabreal, ptabchar);
247   // Reset default values for line & fill color and type of line
248   oldatt.line.index  = -1;
249   oldatt.fill.index  = -1;
250   oldatt.edge.index  = -1;
251   oldatt.line_type   = -1;
252   oldatt.edge_type   = -1;
253 }
254
255 //=============================================================
256 void CGM_Driver::EndDraw (const Standard_Boolean )//dontFlush)
257 {
258   // Close the current picture
259   WriteData (ENDPIC, ptablong, ptabreal, ptabchar);
260   myImage.Nullify ();
261 }
262
263 //=============================================================
264 void CGM_Driver::InitializeColorMap (const Handle(Aspect_ColorMap)& aColorMap) 
265
266   // CGM version 1 allows the COLOR MAP setting only in the body of a picture.
267   if (myState == picBody || myState == imgDraw) {
268     Standard_Real r,g,b;
269     Standard_Integer index,cpt,tab=2,Size = aColorMap->Size();
270     Aspect_ColorMapEntry entry;
271     Quantity_Color color;
272     ptablong[0] = Size;
273     ptablong[1] = cpt = aColorMap->Entry(1).Index();
274     for (Standard_Integer i=1; i<= Size; i++) {
275       entry = aColorMap->Entry(i);
276       index = entry.Index();
277       color = entry.Color();
278       color.Values(r, g, b, Quantity_TOC_RGB);
279       if (myTypeOfColorSpace != Aspect_TOCS_BlackAndWhite) {
280         ptablong[tab  ] = Standard_Integer(255*r); TRANSFORMCOLOR(ptablong[tab  ]);
281         ptablong[tab+1] = Standard_Integer(255*g); TRANSFORMCOLOR(ptablong[tab+1]);
282         ptablong[tab+2] = Standard_Integer(255*b); TRANSFORMCOLOR(ptablong[tab+2]);
283       } else {
284         ptablong[tab  ] = 0; TRANSFORMCOLOR(ptablong[tab  ]);
285         ptablong[tab+1] = 0; TRANSFORMCOLOR(ptablong[tab+1]);
286         ptablong[tab+2] = 0; TRANSFORMCOLOR(ptablong[tab+2]);
287       }
288       tab += 3;
289       if (cpt != index)
290         break;
291       cpt++;
292     }
293     // Put backgrount color at the end of ColorMap
294     ptablong[0]++;
295     ptablong[tab  ] = BACKRED;   TRANSFORMCOLOR(ptablong[tab  ]);
296     ptablong[tab+1] = BACKGREEN; TRANSFORMCOLOR(ptablong[tab+1]);
297     ptablong[tab+2] = BACKBLUE;  TRANSFORMCOLOR(ptablong[tab+2]);
298     myBKIndex = cpt;
299     // Write ColorMap to the CGM file
300     WriteData (COLRTABLE, ptablong, ptabreal, ptabchar);
301     if (myTypeOfColorSpace == Aspect_TOCS_BlackAndWhite)
302       myTypeOfColorSpace = Aspect_TOCS_RGB;
303   }
304 }
305
306 //=============================================================
307 void CGM_Driver::InitializeTypeMap (const Handle(Aspect_TypeMap)& aTypeMap) 
308
309 /*
310 In CGM File:
311    LINEEDGETYPEDEF  - code
312    LONG [0]         - linetype (negative)
313    LING [1]         - repeat length
314    for (i=0; i < LONG[1]; i++)
315      REAL [i]       - line description element
316      it's necessary to put all line description elements as integers
317 */
318 /*
319   if (CGMstates == picdes) {
320     Standard_Integer Size = aTypeMap->Size();
321     switch (TypeOfCgm) {
322       case (CgmBinary):
323         Aspect_DriverError::Raise("CGM BINARY ENCODING not implemented yet");
324         break;
325       case (CgmCharEncoding):
326         Aspect_DriverError::Raise("CGM CHARACTER ENCODING not implemented yet");
327         break;
328       case (CgmClearText):
329         for (Standard_Integer i=1; i<= Size; i++) {
330           fprintf(cgmo, "LINEEDGETYPEDEF"); 
331           const TColQuantity_Array1OfLength& asr = aTypeMap->Entry(i).Type().Values();
332           fprintf (cgmo," (%ld), ", -aTypeMap->Entry(i).Index());
333           fprintf (cgmo,"%ld", asr.Upper()-asr.Lower()+1);
334           if ( (asr.Upper()-asr.Lower()+1) > 1 ) {
335             fprintf(cgmo,",");
336           }
337           for (Standard_Integer j = asr.Lower(); j < asr.Upper(); j += 2) {
338             fprintf(cgmo, "%.*f, %.*f", 5, asr(j+1), 5, asr(j));
339             if (j+2 < asr.Upper()) {
340               fprintf(cgmo,",");
341             }
342           }
343           fprintf(cgmo,";\n");
344         }
345         break;
346     }
347   } else {
348     CGMTypeMap = aTypeMap;
349   }
350 */
351   Standard_Integer Size = aTypeMap->Size(), i;
352   aTypeIndex.Clear();
353   for (i = 1; i <= Size; i++) {
354     Standard_Integer index = aTypeMap->Entry(i).Index();
355     if (aTypeMap->Entry(i).Type().Style() == Aspect_TOL_USERDEFINED)
356       aTypeIndex.Bind (index, 1);
357     else
358       aTypeIndex.Bind (index, aTypeMap->Entry(i).Type().Style()+1);
359   }
360 }
361
362 //=============================================================
363 void CGM_Driver::InitializeWidthMap (const Handle(Aspect_WidthMap)& aWidthMap) 
364 {
365   Standard_Integer Size = aWidthMap->Size();
366   if (WIDTHMAP)
367     delete[] WIDTHMAP;
368   WIDTHMAP = new float[Size];
369   memset (WIDTHMAP, 0, sizeof(WIDTHMAP));
370   for (Standard_Integer i=1; i<= Size; i++) {
371     Standard_Real w = aWidthMap->Entry(i).Width();
372     WIDTHMAP[aWidthMap->Entry(i).Index()] = (float)w;
373   }
374 }
375
376 //=================================================================================
377 Standard_Boolean CGM_Driver::SizeOfImageFile (const Standard_CString anImageFile,
378                                               Standard_Integer& aWidth,
379                                               Standard_Integer& aHeight) const
380 {
381   return AlienImage::LoadImageFile (anImageFile, myImage, aWidth, aHeight);
382 }
383
384 //=============================================================
385 // Category: Methods to write attributes
386 //=============================================================
387 void CGM_Driver::PlotLineAttrib (const Standard_Integer ColorIndex,
388                                  const Standard_Integer TypeIndex,
389                                  const Standard_Integer WidthIndex)
390 {
391   // Set color of the line
392   if (myColorIndex != ColorIndex) {
393     curatt.line.index = myColorIndex = ColorIndex;
394     WriteData (LINECOLR, ptablong, ptabreal, ptabchar);
395   }
396   // Set type of the line
397   if (myTypeIndex != TypeIndex) {
398     curatt.line_type = myTypeIndex = TypeIndex;
399     WriteData (LINETYPE, ptablong, ptabreal, ptabchar);
400   }
401   // Set width of the line
402   if (myWidthIndex != WidthIndex) {
403     curatt.line_width.real = WIDTHMAP[(myWidthIndex = WidthIndex)];
404     WriteData (LINEWIDTH, ptablong, ptabreal, ptabchar);
405   }
406   // Set the color of the edge of polygon
407   if (myEdgeColor != ColorIndex) {
408     curatt.edge.index = myEdgeColor = ColorIndex;
409     WriteData (EDGECOLR, ptablong, ptabreal, ptabchar);
410   }
411   // Set the type of the edge of polygon
412   if (myEdgeType != TypeIndex) {
413     curatt.edge_type = myEdgeType = TypeIndex;
414     WriteData (EDGETYPE, ptablong, ptabreal, ptabchar);
415   }
416   // Set the width of the edge of polygon
417   if (myEdgeWidth != WidthIndex) {
418     curatt.edge_width.real = WIDTHMAP[(myEdgeWidth = WidthIndex)];
419     WriteData (EDGEWIDTH, ptablong, ptabreal, ptabchar);
420   }
421 }
422
423 //===============================================================================
424 void CGM_Driver::PlotPolyAttrib (const Standard_Integer ColorIndex,
425                                  const Standard_Integer TileIndex,
426                                  const Standard_Boolean DrawEdge)
427 {
428   // Set the edge visibility to the corresponding value
429   if (myEdgeVisibility != (DrawEdge ? ON : OFF)) {
430     curatt.edge_vis = myEdgeVisibility = (DrawEdge ? ON : OFF);
431     WriteData (EDGEVIS, ptablong, ptabreal, ptabchar);
432   }
433   // Set the interior style to fill by solid
434   if (myInteriorStyle != (TileIndex < 0 ? EMPTY : SOLID)) {
435     curatt.int_style = myInteriorStyle = (TileIndex < 0 ? EMPTY : SOLID);
436     WriteData (INTSTYLE, ptablong, ptabreal, ptabchar);
437   }
438   // Set the fill color for drawing
439   if (myFillIndex != ColorIndex) {
440     if (ColorIndex > 0) curatt.fill.index = myFillIndex = ColorIndex;
441     else                curatt.fill.index = myFillIndex = myBKIndex;
442     WriteData (FILLCOLR, ptablong, ptabreal, ptabchar);
443   }
444 }
445
446 //=============================================================
447 // Category: Methods to draw primitives
448 //=============================================================
449
450 //=============================================================
451 Standard_Boolean CGM_Driver::PlotPoint (const Standard_ShortReal X,
452                                         const Standard_ShortReal Y)
453 {
454   ptablong[0] = 2;
455   ptabreal[0] = X;        ptabreal[1] = Y;
456   ptabreal[2] = X + 0.1F; ptabreal[3] = Y + 0.1F;
457   WriteData (LINE, ptablong, ptabreal, ptabchar);
458   return Standard_True;
459 }
460
461 //=============================================================
462 Standard_Boolean CGM_Driver::PlotSegment (const Standard_ShortReal X1,
463                                           const Standard_ShortReal Y1,
464                                           const Standard_ShortReal X2,
465                                           const Standard_ShortReal Y2)
466 {
467   ptablong[0] = 2;
468   ptabreal[0] = X1; ptabreal[1] = Y1;
469   ptabreal[2] = X2; ptabreal[3] = Y2;
470   WriteData (LINE, ptablong, ptabreal, ptabchar);
471   return Standard_True;
472 }
473
474 //=============================================================
475 #define _XP(idx) ((float*)xArray)[(idx)]
476 #define _YP(idx) ((float*)yArray)[(idx)]
477 //=============================================================
478 Standard_Boolean CGM_Driver::PlotPolyline (const Standard_Address xArray,
479                                            const Standard_Address yArray,
480                                            const Standard_Address nPts,
481                                            const Standard_Integer nParts)
482 {
483   // Multipart drawing can only be used for text drawing
484   // (called from PlotMgt_TextManager::EndChar()
485   int Tab, N = 0;
486   for (int i = 0; i < nParts; i++) {
487     Tab = 0;
488     ptablong[0] = ((int*)nPts)[i];
489     for (int j = N; j < N + ptablong[0]; j++) {
490       ptabreal[Tab++] = _XP(j); ptabreal[Tab++] = _YP(j);
491     }
492     WriteData (LINE, ptablong, ptabreal, ptabchar);
493     N += ptablong[0];
494   }
495   return Standard_True;
496 }
497
498 //=============================================================
499 Standard_Boolean CGM_Driver::PlotPolygon (const Standard_Address xArray,
500                                           const Standard_Address yArray,
501                                           const Standard_Address nPts,
502                                           const Standard_Integer nParts)
503 {
504   if (nParts == 1) {
505     int Tab = 0;
506     ptablong[0] = ((int*)nPts)[0];
507     for (int i=0; i < ptablong[0]; i++) {
508       ptabreal[Tab++] = _XP(i); ptabreal[Tab++] = _YP(i);
509     }
510     WriteData (POLYGON, ptablong, ptabreal, ptabchar);
511   } else {
512     // This can only be used for text drawing
513     // (called from PlotMgt_TextManager::EndChar()
514     int Tab = 0, Vis = 1, N = 0, cpN;
515     ptablong[0] = 0;
516     for (int i = 0; i < nParts; i++) {
517       cpN = ((int*)nPts)[i];
518       for (int j = N; j < N + cpN - 1; j++) {
519         ptabreal[Tab++] = _XP(j); ptabreal[Tab++] = _YP(j);
520         ptablong[Vis++] = VIS; ptablong[0]++;
521       }
522       N += cpN;
523       ptabreal[Tab++] = _XP(N-1); ptabreal[Tab++] = _YP(N-1);
524       ptablong[Vis++] = CLOSEVIS; ptablong[0]++;
525     }
526     WriteData (POLYGONSET, ptablong, ptabreal, ptabchar);
527   }
528   return Standard_True;
529 }
530 //=============================================================
531 #undef _XP
532 #undef _YP
533
534 //=============================================================
535 Standard_Boolean CGM_Driver::PlotArc (const Standard_ShortReal Xpos,
536                                       const Standard_ShortReal Ypos,
537                                       const Standard_ShortReal aXradius,
538                                       const Standard_ShortReal aYradius,
539                                       const Standard_ShortReal sAngle,
540                                       const Standard_ShortReal oAngle)
541 {
542   Standard_ShortReal san = sAngle;
543   Standard_ShortReal fan = sAngle + oAngle;
544   if (oAngle >= 2*PI) {
545     PlotPolyAttrib (myLineColorIndex, -1, Standard_True);
546     if (aXradius == aYradius) {
547       ptabreal[0] = (float)Xpos; ptabreal[1] = (float)Ypos;
548       ptabreal[2] = (float)aXradius;
549       WriteData (CIRCLE, ptablong, ptabreal, ptabchar);
550     } else {
551       ptabreal[0] = (float)Xpos;              ptabreal[1] = (float)Ypos;
552       ptabreal[2] = (float)(Xpos + aXradius); ptabreal[3] = (float)Ypos;
553       ptabreal[4] = (float)Xpos;              ptabreal[5] = (float)(Ypos + aYradius);
554       WriteData (ELLIPSE, ptablong, ptabreal, ptabchar);
555     }
556   } else {
557     if (aXradius == aYradius) {
558       ptabreal[0] = (float)Xpos;     ptabreal[1] = (float)Ypos;
559       ptabreal[2] = (float)cos(san); ptabreal[3] = (float)sin(san);
560       ptabreal[4] = (float)cos(fan); ptabreal[5] = (float)sin(fan);
561       ptabreal[6] = (float)aXradius;
562       WriteData (ARCCTR, ptablong, ptabreal, ptabchar);
563     } else {
564       ptabreal[0] = (float)Xpos;              ptabreal[1] = (float)Ypos;
565       ptabreal[2] = (float)(Xpos + aXradius); ptabreal[3] = (float)Ypos;
566       ptabreal[4] = (float)Xpos;              ptabreal[5] = (float)(Ypos + aYradius);
567       ptabreal[6] = (float)cos(san);          ptabreal[7] = (float)sin(san);
568       ptabreal[8] = (float)cos(fan);          ptabreal[9] = (float)sin(fan);
569       WriteData (ELLIPARC, ptablong,  ptabreal, ptabchar);
570     }
571   }
572   return Standard_True;
573 }
574
575 //=============================================================
576 Standard_Boolean CGM_Driver::PlotPolyArc (const Standard_ShortReal Xpos,
577                                           const Standard_ShortReal Ypos,
578                                           const Standard_ShortReal aXradius,
579                                           const Standard_ShortReal aYradius,
580                                           const Standard_ShortReal sAngle,
581                                           const Standard_ShortReal oAngle)
582 {
583   Standard_ShortReal san = sAngle;
584   Standard_ShortReal fan = sAngle + oAngle;
585   if (oAngle >= 2.*PI) {
586     if (aXradius == aYradius) {
587       ptabreal[0] = (float)Xpos; ptabreal[1] = (float)Ypos;
588       ptabreal[2] = (float)aXradius;
589       WriteData (CIRCLE, ptablong, ptabreal, ptabchar);
590     } else {
591       ptabreal[0] = (float)Xpos;              ptabreal[1] = (float)Ypos;
592       ptabreal[2] = (float)(Xpos + aXradius); ptabreal[3] = (float)aYradius;
593       ptabreal[4] = (float)Xpos;              ptabreal[5] = (float)(Ypos + aYradius);
594       WriteData (ELLIPSE, ptablong, ptabreal, ptabchar);
595     }
596   } else {
597     if (aXradius == aYradius) {
598       ptabreal[0] = (float)Xpos;     ptabreal[1] = (float)Ypos;
599       ptabreal[2] = (float)cos(san); ptabreal[3] = (float)sin(san);
600       ptabreal[4] = (float)cos(fan); ptabreal[5] = (float)sin(fan);
601       ptabreal[6] = (float)aXradius;       ptablong[8] = 0;
602       WriteData (ARCCTRCLOSE, ptablong, ptabreal, ptabchar);
603     } else {
604       ptabreal[0] = (float)Xpos;                ptabreal[1] = (float)Ypos;
605       ptabreal[2] = (float)(Xpos + aXradius);   ptabreal[3] = (float)Ypos;
606       ptabreal[4] = (float)Xpos;                ptabreal[5] = (float)(Ypos + aYradius);
607       ptabreal[6] = (float)cos(san);            ptabreal[7] = (float)sin(san);
608       ptabreal[8] = (float)(aXradius*cos(fan)); ptabreal[9] = (float)(aYradius*sin(fan));
609       ptablong[11] = 0;
610       WriteData (ELLIPARCCLOSE, ptablong, ptabreal, ptabchar);
611     }
612   }
613   return Standard_True;
614 }
615
616 //=============================================================
617 // Private methods
618 //=============================================================
619 void CGM_Driver::InitializeDriver (const Standard_CString aName)
620 {
621   //declare the Metafile
622   strcpy(ptabchar,aName);
623   WriteData (BEGMF, ptablong, ptabreal, ptabchar);
624   //Set the CGM's version
625   ptablong[0] = CGMVER;
626   WriteData (MFVERSION, ptablong, ptabreal, ptabchar);
627   //Put in the metafile a string whose content is free
628   strcpy(ptabchar,"Generated with CGM_Driver from MATRA-DATAVISION");
629   WriteData (MFDESC, ptablong, ptabreal, ptabchar);
630   //Set the element list (always 'DRAWINGPLUS')
631   ptablong[1]=1;
632   WriteData (MFELEMLIST, ptablong, ptabreal, ptabchar);
633   //Set the type of value (integer or real)
634   cur.vdc_type = REAL;
635   WriteData (VDCTYPE, ptablong, ptabreal, ptabchar);
636   //Set the integer precision 
637   cur.int_bits = INTBITS;
638   WriteData (INTEGERPREC, ptablong, ptabreal, ptabchar);
639   //Set the real precision
640   cur.max_real = MAXREAL;     // Clear text
641   cur.min_real = MINREAL;
642   cur.real_bits = REALBITS;   // Character encoding
643   cur.real_places = REALPLACES;
644   cur.real_defexp = REALDEFEXP;
645   cur.real_expald = REALEXP;
646   curbin.real_type = REALFORM;    // Binary encoding
647   curbin.real_whole = REALWHOLE;
648   curbin.real_fraction = REALFRACTION;
649   WriteData (REALPREC, ptablong, ptabreal, ptabchar);
650   //Set the index precision
651   cur.index_bits = INDEXBITS;
652   WriteData (INDEXPREC, ptablong, ptabreal, ptabchar);
653   //Set the color precision
654   cur.col_bits = CLRBITS;
655   WriteData (COLRPREC, ptablong, ptabreal, ptabchar);
656   //Set the Color Index precision
657   cur.colind_bits = CLRINDBITS;
658   WriteData (COLRINDEXPREC, ptablong, ptabreal, ptabchar);
659   //set the max color index
660   cur.max_colind = 255;
661   WriteData (MAXCOLRINDEX, ptablong, ptabreal, ptabchar);
662   //Set the minimum color and the maximum color
663   cur.min_rgb.red = cur.min_rgb.green = cur.min_rgb.blue = 0;
664   cur.max_rgb.red = cur.max_rgb.green = cur.max_rgb.blue = 255;
665   TRANSFORMCOLOR(cur.max_rgb.red);
666   TRANSFORMCOLOR(cur.max_rgb.green);
667   TRANSFORMCOLOR(cur.max_rgb.blue);
668   WriteData (COLRVALUEEXT, ptablong, ptabreal,  ptabchar);
669   //Set the internal variables
670   myBKIndex           = 0;
671   myCurrentPage       = 0;
672   myFillIndex         = -9;
673   myEdgeColor         = -9;
674   myEdgeType          = -9;
675   myEdgeWidth         = -9;
676   myInteriorStyle     = -9;
677   myEdgeVisibility    = -9;
678   myImage.Nullify ();
679 }
680
681 //=============================================================
682 void CGM_Driver::WriteData (const Standard_Integer aCode,
683                             const Standard_Address pLongData,
684                             const Standard_Address pFloatData,
685                             const Standard_Address pCharData)
686 {
687   short  code   = (short) aCode;
688   long*  aLong  = (long*) pLongData;
689   float* aFloat = (float*)pFloatData;
690   char*  aChar  = (char*) pCharData;
691   if (code == LINETYPE) {
692     curatt.line_type = aTypeIndex.Find(curatt.line_type);
693   } else if (code == EDGETYPE) {
694     curatt.edge_type = aTypeIndex.Find(curatt.edge_type);
695   }
696   switch (TypeOfCgm) {
697     case (CgmBinary):
698       CGMObin  (cgmo, code, aLong, aFloat, aChar);
699       break;
700     case (CgmCharEncoding):
701       CGMOchar (cgmo, code, aLong, aFloat, aChar);
702       break;
703     case (CgmClearText):
704       CGMOtext (cgmo, code, aLong, aFloat, aChar);
705       break;
706   }
707 }
708
709 //=============================================================
710 Standard_Boolean CGM_Driver::PlotImage (const Standard_ShortReal aX,
711                                         const Standard_ShortReal aY,
712                                         const Standard_ShortReal aWidth,
713                                         const Standard_ShortReal aHeight,
714                                         const Standard_ShortReal aScale,
715                                         const Standard_CString anImageFile,
716                                         const Standard_Address anArrayOfPixels,
717                                         const Standard_Integer aLineIndex)
718 {
719   Aspect_ColorMapEntry anEntry;
720   Handle(Aspect_GenericColorMap) aColorMap = new Aspect_GenericColorMap;
721   // We'll create new colormap here and will set it
722   Standard_Boolean status;
723   Standard_Integer idx = 0, found = 0, fidx = 0, LowX = 0, LowY = 0;
724   Standard_Integer width  = Standard_Integer(aWidth),
725                    height = Standard_Integer(aHeight);
726   Standard_Integer x, y;
727   Standard_Real    r, g, b;
728   Aspect_RGBPixel* g2dp = (Aspect_RGBPixel*) anArrayOfPixels;
729   Quantity_Color   color;
730   // Load image if necessary
731   if (anImageFile) {
732     status = SizeOfImageFile (anImageFile, width, height);
733     if (status) {
734       LowX = myImage -> LowerX ();
735       LowY = myImage -> LowerY ();
736     }
737   } else {
738     status = Standard_True;
739   }
740
741   // Put image colormap and pixels to the file
742   if (status) {
743     Standard_ShortReal wscale, hscale;
744     wscale = hscale = (float)(aScale * myPixelSize * PPI / 2.F);
745     // Put image in the file
746     float a2X = (float)(aX - wscale * width/2.F);
747     float a2Y = (float)(aY + hscale * (height/2.F - (aLineIndex == -1 ? 0:aLineIndex)));
748     if (aLineIndex != -1) height = 1;
749     int cellsSize = sizeof(long)*(width*height + 10);
750
751     Aspect_RGBPixel* pixels =
752       (Aspect_RGBPixel*) malloc (IMCOLRPREC*sizeof(Aspect_RGBPixel));
753     if (pixels == NULL)  return Standard_False;
754     long* cells = (long*) malloc (cellsSize);
755     if (cells == NULL) {  free (pixels); return Standard_False;  }
756
757     //Initialize the array
758     memset (pixels, 0, IMCOLRPREC*sizeof(Aspect_RGBPixel));
759     int pixidx = 10; // Pixel description begins with index 10
760     // Put cellarray entry data
761     ptabreal[0] = a2X;                ptabreal[1] = a2Y; // P
762     ptabreal[2] = a2X+(width*wscale); ptabreal[3] = a2Y-(height*hscale); // Q
763     ptabreal[4] = a2X+(width*wscale); ptabreal[5] = a2Y; // R
764     cells[0]    = width*height;       cells[7] = width;
765     cells[8]    = height;
766     // For all pixels of an Image
767     for (y=0; y < height; y++) {
768       for (x=0; x < width; x++) {
769         // Get pixel of image at (x,y) position
770         if (anImageFile) {
771           color = myImage -> PixelColor (x + LowX, y + LowY);
772           color.Values (r, g, b, Quantity_TOC_RGB);
773         } else {
774           r = g2dp -> red;
775           g = g2dp -> green;
776           b = g2dp -> blue;
777           g2dp++;
778         }
779         // Try to find the pixel
780         for (int c = 0; c < idx; c++) {
781           if (pixels[c].red   == r && pixels[c].green == g && pixels[c].blue  == b) {
782             found = 1;
783             fidx  = c;
784           }
785           if (found) break;
786         }
787         if (!found) {
788           // It's necessary to add new color to colormap
789           pixels[idx].red   = (float)r;
790           pixels[idx].green = (float)g;
791           pixels[idx].blue  = (float)b;
792           color.SetValues (r, g, b, Quantity_TOC_RGB);
793           anEntry = Aspect_ColorMapEntry (idx, color);
794           anEntry.SetIndex (idx);
795           aColorMap->AddEntry (anEntry);
796           cells[pixidx++] = idx;
797           idx++;
798         } else {
799           cells[pixidx++] = fidx;
800         }
801         if (idx > IMCOLRPREC) {
802           free (pixels);
803           free (cells);
804           return Standard_False;
805         }
806         found = 0;
807       } // for (x=0; x < width; x++)
808     } // for (y=0; y < height; y++)
809     free (pixels);
810     // Calculate image color precision
811     int imcolprec = 0, tmp = 1L;
812     while (tmp < aColorMap->Size()) { tmp <<= 1L; imcolprec++; }
813     cells[9] = imcolprec;
814     // Write image data to file (colormap and image data).
815     myState = imgDraw;
816     InitializeColorMap (aColorMap);
817     WriteData          (CELLARRAY, cells, ptabreal, ptabchar);
818     // Restore old colormap
819     myState = picBody;
820     InitializeColorMap (ColorMap ());
821     free (cells);
822     return Standard_True;
823   } // IF STATUS
824   return Standard_False;
825 }