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