1 // Created on: 1993-08-13
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
19 #include <Draw_Appli.hxx>
20 #include <Draw_Drawable3D.hxx>
21 #include <Draw_Failure.hxx>
22 #include <Draw_Interpretor.hxx>
23 #include <Draw_ProgressIndicator.hxx>
24 #include <Draw_Window.hxx>
25 #include <gp_Pnt2d.hxx>
26 #include <Message.hxx>
27 #include <Message_Messenger.hxx>
28 #include <Message_PrinterOStream.hxx>
30 #include <OSD_Environment.hxx>
31 #include <OSD_File.hxx>
32 #include <OSD_Process.hxx>
33 #include <OSD_SharedLibrary.hxx>
34 #include <OSD_Timer.hxx>
35 #include <Plugin_MapOfFunctions.hxx>
36 #include <Resource_Manager.hxx>
37 #include <Standard_ErrorHandler.hxx>
38 #include <Standard_Stream.hxx>
39 #include <Standard_Version.hxx>
40 #include <TCollection_AsciiString.hxx>
44 #include <Standard_WarningDisableFunctionCast.hxx>
46 // on MSVC, use #pragma to define name of the Tcl library to link with,
47 // depending on Tcl version number
49 // two helper macros are needed to convert version number macro to string literal
50 #define STRINGIZE1(a) #a
51 #define STRINGIZE2(a) STRINGIZE1(a)
52 #pragma comment (lib, "tcl" STRINGIZE2(TCL_MAJOR_VERSION) STRINGIZE2(TCL_MINOR_VERSION) ".lib")
53 #pragma comment (lib, "tk" STRINGIZE2(TCL_MAJOR_VERSION) STRINGIZE2(TCL_MINOR_VERSION) ".lib")
58 extern Standard_Boolean Draw_ParseFailed;
60 Standard_EXPORT Draw_Viewer dout;
61 Standard_EXPORT Draw_Interpretor theCommands;
62 Standard_EXPORT Standard_Boolean Draw_Batch = Standard_False;
63 Standard_EXPORT Standard_Boolean Draw_Spying = Standard_False;
64 Standard_EXPORT Standard_Boolean Draw_Chrono = Standard_False;
65 Standard_EXPORT Standard_Boolean Draw_VirtualWindows = Standard_False;
66 Standard_EXPORT Standard_Boolean ErrorMessages = Standard_True;
68 static const char* ColorNames[MAXCOLOR] = {
69 "White","Red","Green","Blue","Cyan","Gold","Magenta",
70 "Maroon","Orange","Pink","Salmon","Violet","Yellow","Khaki","Coral"
73 std::filebuf Draw_Spyfile;
75 static std::ostream spystream(&Draw_Spyfile);
77 static Handle(Draw_ProgressIndicator) global_Progress = NULL;
79 Standard_EXPORT Standard_Boolean Draw_Interprete(const char* command);
80 // true if complete command
82 // *******************************************************************
84 // *******************************************************************
86 static void interpreteTclCommand (const TCollection_AsciiString& theCmd)
93 while (console_semaphore == HAS_CONSOLE_COMMAND)
98 TCollection_ExtendedString aCmdWide (theCmd);
99 wcscpy_s (console_command, aCmdWide.ToWideString());
101 console_semaphore = HAS_CONSOLE_COMMAND;
102 while (console_semaphore == HAS_CONSOLE_COMMAND)
109 std::cout << "Error while reading a script file.\n";
116 Draw_Interprete (theCmd.ToCString());
120 static void ReadInitFile (const TCollection_AsciiString& theFileName)
122 TCollection_AsciiString aCmd = theFileName;
124 aCmd.ChangeAll ('\\', '/');
126 aCmd = TCollection_AsciiString ("source -encoding utf-8 \"") + aCmd + "\"";
127 interpreteTclCommand (aCmd);
130 //! Define environment variable available from Tcl and OCCT.
131 static void setOcctTclEnv (const TCollection_AsciiString& theName,
132 TCollection_AsciiString& thePath)
134 if (thePath.IsEmpty())
139 thePath.ChangeAll ('\\', '/');
140 OSD_Environment aRedPathEnv (theName);
141 aRedPathEnv.SetValue (thePath);
144 const TCollection_AsciiString aPutEnv = theName + "=" + thePath;
145 Tcl_PutEnv (aPutEnv.ToCString());
148 //! Look for resource within standard installation layouts relative to executable location.
150 //! Bin (INSTALL_DIR_BIN):
151 //! - Windows: <prefix>/win64/vc10/bin(d)
152 //! - Unix: <prefix>/bin
153 //! Resources (INSTALL_DIR_RESOURCE):
154 //! - Windows: <prefix>/src
155 //! - Unix: <prefix>/share/opencascade-7.0.0/resources
156 //! Samples (INSTALL_DIR_SAMPLES):
157 //! - Windows: <prefix>/samples
158 //! - Unix: <prefix>/share/opencascade-7.0.0/samples
159 //! Tests (INSTALL_DIR_TESTS):
160 //! - Windows: <prefix>/tests
161 //! - Unix: <prefix>/share/opencascade-7.0.0/tests
163 //! @param theCasRoot [out] found CASROOT location (e.g. installation folder)
164 //! @param theResRoot [out] found resources root location
165 //! @param theResName [in] resource to find ("resources", "samples", etc.)
166 //! @param theProbeFile [in] file to probe within resources location (e.g. "DrawResources/DrawDefault" within "resources")
167 static bool searchResources (TCollection_AsciiString& theCasRoot,
168 TCollection_AsciiString& theResRoot,
169 const TCollection_AsciiString& theResName,
170 const TCollection_AsciiString& theProbeFile)
172 const TCollection_AsciiString aResLayouts[] =
174 TCollection_AsciiString("/share/opencascade-" OCC_VERSION_STRING_EXT "/") + theResName,
175 TCollection_AsciiString("/share/opencascade-" OCC_VERSION_COMPLETE "/") + theResName,
176 TCollection_AsciiString("/share/opencascade-" OCC_VERSION_STRING "/") + theResName,
177 TCollection_AsciiString("/share/opencascade/") + theResName,
178 TCollection_AsciiString("/share/occt-" OCC_VERSION_STRING_EXT "/") + theResName,
179 TCollection_AsciiString("/share/occt-" OCC_VERSION_COMPLETE "/") + theResName,
180 TCollection_AsciiString("/share/occt-" OCC_VERSION_STRING "/") + theResName,
181 TCollection_AsciiString("/share/occt/") + theResName,
182 TCollection_AsciiString("/") + theResName,
183 TCollection_AsciiString("/share/opencascade"),
184 TCollection_AsciiString("/share/occt"),
185 TCollection_AsciiString("/share"),
186 TCollection_AsciiString("/src"),
187 TCollection_AsciiString("")
190 const TCollection_AsciiString anExeDir (OSD_Process::ExecutableFolder());
191 for (Standard_Integer aLayIter = 0;; ++aLayIter)
193 const TCollection_AsciiString& aResLayout = aResLayouts[aLayIter];
194 const TCollection_AsciiString aProbeFile = aResLayout + "/" + theProbeFile;
195 if (OSD_File (anExeDir + aProbeFile).Exists())
197 theCasRoot = anExeDir;
198 theResRoot = theCasRoot + aResLayout;
202 else if (OSD_File (anExeDir + "../" + aProbeFile).Exists())
204 theCasRoot = anExeDir + "..";
205 theResRoot = theCasRoot + aResLayout;
208 // <prefix>/gcc/bin(d)
209 else if (OSD_File (anExeDir + "../../" + aProbeFile).Exists())
211 theCasRoot = anExeDir + "../..";
212 theResRoot = theCasRoot + aResLayout;
215 // <prefix>/win64/vc10/bin(d)
216 else if (OSD_File (anExeDir + "../../../" + aProbeFile).Exists())
218 theCasRoot = anExeDir + "../../..";
219 theResRoot = theCasRoot + aResLayout;
223 if (aResLayout.IsEmpty())
230 //=======================================================================
231 //function : GetInterpretor
233 //=======================================================================
234 Draw_Interpretor& Draw::GetInterpretor()
239 //=======================================================================
241 //purpose : Set/Get Progress Indicator
242 //=======================================================================
243 void Draw::SetProgressBar(const Handle(Draw_ProgressIndicator)& theProgress)
245 global_Progress = theProgress;
248 Handle(Draw_ProgressIndicator) Draw::GetProgressBar()
250 return global_Progress;
254 /*--------------------------------------------------------*\
255 | exitProc: finalization handler for Tcl/Tk thread. Forces parent process to die
256 \*--------------------------------------------------------*/
257 void exitProc(ClientData /*dc*/)
260 for (Standard_Integer id = 0; id < MAXVIEW; id++)
266 // *******************************************************************
268 // *******************************************************************
270 Standard_EXPORT void Draw_Appli(HINSTANCE hInst, HINSTANCE hPrevInst, int nShow, int argc, wchar_t** argv, const FDraw_InitAppli Draw_InitAppli)
272 void Draw_Appli(int argc, char** argv, const FDraw_InitAppli Draw_InitAppli)
276 // prepend extra DLL search path to override system libraries like opengl32.dll
278 OSD_Environment aUserDllEnv ("CSF_UserDllPath");
279 const TCollection_ExtendedString aUserDllPath (aUserDllEnv.Value());
280 if (!aUserDllPath.IsEmpty())
282 // This function available since Win XP SP1 #if (_WIN32_WINNT >= 0x0502).
283 // We retrieve dynamically here (kernel32 should be always preloaded).
284 typedef BOOL (WINAPI *SetDllDirectoryW_t)(const wchar_t* thePathName);
285 HMODULE aKern32Module = GetModuleHandleW (L"kernel32");
286 SetDllDirectoryW_t aFunc = (aKern32Module != NULL)
287 ? (SetDllDirectoryW_t )GetProcAddress (aKern32Module, "SetDllDirectoryW") : NULL;
290 aFunc (aUserDllPath.ToWideString());
294 //std::cerr << "SetDllDirectoryW() is not available on this system!\n";
296 if (aKern32Module != NULL)
298 FreeLibrary (aKern32Module);
303 // *****************************************************************
305 // *****************************************************************
306 Draw_Batch = Standard_False;
307 TCollection_AsciiString aRunFile, aCommand;
308 Standard_Boolean isInteractiveForced = Standard_False;
310 // parse command line
311 for (int anArgIter = 1; anArgIter < argc; ++anArgIter)
313 TCollection_AsciiString anArg (argv[anArgIter]);
316 || anArg == "--help")
318 std::cout << "Open CASCADE " << OCC_VERSION_STRING_EXT << " DRAW Test Harness\n\n";
319 std::cout << "Options:\n";
320 std::cout << " -b: batch mode (no GUI, no viewers)\n";
321 std::cout << " -v: no GUI, use virtual (off-screen) windows for viewers\n";
322 std::cout << " -i: interactive mode\n";
323 std::cout << " -f file: execute script from file\n";
324 std::cout << " -c command args...: execute command (with optional arguments)\n\n";
325 std::cout << "Options -b, -v, and -i are mutually exclusive.\n";
326 std::cout << "If -c or -f are given, -v is default; otherwise default is -i.\n";
327 std::cout << "Options -c and -f are alternatives and should be at the end \n";
328 std::cout << "of the command line.\n";
329 std::cout << "Option -c can accept set of commands separated by ';'.\n";
332 else if (anArg == "-b")
334 Draw_Batch = Standard_True;
336 else if (anArg == "-v")
338 // force virtual windows
339 Draw_VirtualWindows = Standard_True;
341 else if (anArg == "-i")
344 Draw_VirtualWindows = Standard_False;
345 isInteractiveForced = Standard_True;
347 else if (anArg == "-f") // -f option should be LAST!
349 Draw_VirtualWindows = !isInteractiveForced;
350 if (++anArgIter < argc)
352 aRunFile = TCollection_AsciiString (argv[anArgIter]);
356 else if (anArg == "-c") // -c option should be LAST!
358 Draw_VirtualWindows = !isInteractiveForced;
359 if (++anArgIter < argc)
361 aCommand = TCollection_AsciiString (argv[anArgIter]);
363 while (++anArgIter < argc)
365 aCommand.AssignCat (" ");
366 aCommand.AssignCat (argv[anArgIter]);
372 std::cout << "Error: unsupported option " << TCollection_AsciiString (argv[anArgIter]) << "\n";
376 // *****************************************************************
378 // *****************************************************************
379 OSD::SetSignal(Standard_False);
380 //OSD::SetSignalStackTraceLength (10);
383 // in interactive mode, force Windows to report dll loading problems interactively
384 if ( ! Draw_VirtualWindows && ! Draw_Batch )
388 // *****************************************************************
389 // init X window and create display
390 // *****************************************************************
397 Draw_Batch=!Init_Appli(hInst, hPrevInst, nShow, hWnd);
399 Draw_Batch=!Init_Appli();
403 std::cout << "DRAW is running in batch mode" << std::endl;
405 Tcl_Init(theCommands.Interp());
411 for (int i = 0; i < MAXCOLOR; ++i)
413 if (!dout.DefineColor (i, ColorNames[i]))
415 std::cout <<"Could not allocate default color " << ColorNames[i] << std::endl;
420 // *****************************************************************
421 // set maximum precision for cout
422 // *****************************************************************
423 std::cout.precision(15);
425 // *****************************************************************
427 // *****************************************************************
428 Draw::BasicCommands(theCommands);
429 Draw::MessageCommands(theCommands);
430 Draw::VariableCommands(theCommands);
431 Draw::UnitCommands(theCommands);
432 if (!Draw_Batch) Draw::GraphicCommands(theCommands);
434 // *****************************************************************
436 // *****************************************************************
437 Draw_InitAppli(theCommands);
440 Tcl_CreateExitHandler(exitProc, 0);
443 // *****************************************************************
445 // *****************************************************************
447 const TCollection_AsciiString aDrawDef (OSD_Environment ("DRAWDEFAULT").Value());
448 if (!aDrawDef.IsEmpty())
450 ReadInitFile (aDrawDef);
454 TCollection_AsciiString aDrawHome;
455 TCollection_AsciiString aCasRoot (OSD_Environment ("CASROOT").Value());
456 if (!aCasRoot.IsEmpty())
458 aDrawHome = aCasRoot + "/src/DrawResources";
462 // search for relative locations within standard development environment
463 TCollection_AsciiString aResPath;
464 if (searchResources (aCasRoot, aResPath, "resources", "DrawResources/DrawDefault"))
466 aDrawHome = aResPath + "/DrawResources";
467 setOcctTclEnv ("CASROOT", aCasRoot);
468 setOcctTclEnv ("DRAWHOME", aDrawHome);
469 setOcctTclEnv ("CSF_OCCTResourcePath", aResPath);
472 TCollection_AsciiString aSamplesPath;
473 if (OSD_Environment ("CSF_OCCTSamplesPath").Value().IsEmpty()
474 && searchResources (aCasRoot, aSamplesPath, "samples", "tcl/Readme.txt"))
476 setOcctTclEnv ("CSF_OCCTSamplesPath", aSamplesPath);
479 TCollection_AsciiString aTestsPath;
480 if (OSD_Environment ("CSF_TestScriptsPath").Value().IsEmpty()
481 && searchResources (aCasRoot, aTestsPath, "tests", "parse.rules"))
483 setOcctTclEnv ("CSF_TestScriptsPath", aTestsPath);
487 if (!aDrawHome.IsEmpty())
489 const TCollection_AsciiString aDefStr = aDrawHome + "/DrawDefault";
490 ReadInitFile (aDefStr);
495 ReadInitFile ("ddefault");
497 std::cout << " the CASROOT variable is mandatory to Run OpenCascade "<< std::endl;
498 std::cout << "No default file" << std::endl;
503 // read commands from file
504 if (!aRunFile.IsEmpty())
506 if (!isInteractiveForced)
508 // disable console messages colorization to avoid spoiling log with color codes
509 theCommands.SetToColorize (Standard_False);
511 ReadInitFile (aRunFile);
512 // provide a clean exit, this is useful for some analysis tools
513 if ( ! isInteractiveForced )
521 // execute command from command line
522 if (!aCommand.IsEmpty())
527 // on Windows except batch mode, commands are executed in separate thread
528 while (console_semaphore == HAS_CONSOLE_COMMAND) Sleep(10);
529 TCollection_ExtendedString aCmdWide(aCommand);
530 wcscpy_s(console_command, aCmdWide.ToWideString());
531 console_semaphore = HAS_CONSOLE_COMMAND;
532 while (console_semaphore == HAS_CONSOLE_COMMAND) Sleep(10);
536 Draw_Interprete (aCommand.ToCString()); // Linux and Windows batch mode
537 // provide a clean exit, this is useful for some analysis tools
538 if ( ! isInteractiveForced )
546 // *****************************************************************
548 // *****************************************************************
553 Run_Appli(Draw_Interprete);
558 const int MAXCMD = 2048;
560 for (int ncmd = 1;; ++ncmd)
562 std::cout << "Draw[" << ncmd << "]> ";
563 if (std::cin.getline (cmd, MAXCMD).fail())
567 Draw_Interprete(cmd);
571 // Destruction de l'application
572 Destroy_Appli(hInst);
577 // User functions called before and after each command
578 void (*Draw_BeforeCommand)() = NULL;
579 void (*Draw_AfterCommand)(Standard_Integer) = NULL;
581 Standard_Boolean Draw_Interprete(const char* com)
584 static Standard_Boolean first = Standard_True;
585 static Tcl_DString command;
588 first = Standard_False;
589 Tcl_DStringInit(&command);
593 // string is already converted into UTF-8
594 Tcl_DStringAppend(&command, com, -1);
595 #elif ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 1)))
596 // OCC63: Since Tcl 8.1 it uses UTF-8 encoding for internal representation of strings
597 Tcl_ExternalToUtfDString ( NULL, com, -1, &command );
599 Tcl_DStringAppend(&command,com,-1);
602 if (!theCommands.Complete(Tcl_DStringValue(&command)))
603 return Standard_False;
605 // *******************************************************************
606 // Command interpreter
607 // *******************************************************************
609 // Standard_Integer i = 0;
610 // Standard_Integer j = 0;
612 Standard_Boolean wasspying = Draw_Spying;
615 Standard_Boolean hadchrono = Draw_Chrono;
616 if (hadchrono) tictac.Start();
618 if (Draw_BeforeCommand) (*Draw_BeforeCommand) ();
622 c = theCommands.RecordAndEval(Tcl_DStringValue(&command));
624 if (Draw_AfterCommand) (*Draw_AfterCommand)(c);
626 if (wasspying && Draw_Spying) {
627 if (c > 0) spystream << "# ";
628 spystream << Tcl_DStringValue(&command) << "\n";
633 if (*theCommands.Result())
635 if (c > 0 && theCommands.ToColorize())
637 Message_PrinterOStream::SetConsoleTextColor (&std::cout, Message_ConsoleColor_Red, true);
639 std::cout << theCommands.Result() << std::endl;
640 if (c > 0 && theCommands.ToColorize())
642 Message_PrinterOStream::SetConsoleTextColor (&std::cout, Message_ConsoleColor_Default, false);
646 if (Draw_Chrono && hadchrono) {
651 Tcl_DStringFree(&command);
653 return Standard_True;
660 Standard_Integer Tcl_AppInit (Tcl_Interp *)
671 Standard_Integer Draw_Call (char *c)
673 Standard_Integer r = theCommands.Eval(c);
674 std::cout << theCommands.Result() << std::endl;
678 //=================================================================================
680 //=================================================================================
681 void Draw::Load (Draw_Interpretor& theDI,
682 const TCollection_AsciiString& theKey,
683 const TCollection_AsciiString& theResourceFileName,
684 const TCollection_AsciiString& theDefaultsDirectory,
685 const TCollection_AsciiString& theUserDefaultsDirectory,
686 const Standard_Boolean theIsVerbose)
688 static Plugin_MapOfFunctions theMapOfFunctions;
689 OSD_Function aFunc = NULL;
690 if (!theMapOfFunctions.Find (theKey, aFunc))
692 TCollection_AsciiString aPluginLibrary;
693 Handle(Resource_Manager) aPluginResource = new Resource_Manager (theResourceFileName, theDefaultsDirectory, theUserDefaultsDirectory, theIsVerbose);
694 if (!aPluginResource->Find (theKey, aPluginLibrary))
696 Message::SendFail() << "could not find the resource:" << theKey;
697 Standard_SStream aMsg; aMsg << "Could not find the resource:" << theKey << std::endl;
698 throw Draw_Failure (aMsg.str().c_str());
701 #if !defined(_WIN32) || defined(__MINGW32__)
702 aPluginLibrary = TCollection_AsciiString ("lib") + aPluginLibrary;
705 aPluginLibrary += ".dll";
707 aPluginLibrary += ".dylib";
708 #elif defined (HPUX) || defined(_hpux)
709 aPluginLibrary += ".sl";
711 aPluginLibrary += ".so";
713 OSD_SharedLibrary aSharedLibrary (aPluginLibrary.ToCString());
714 if (!aSharedLibrary.DlOpen (OSD_RTLD_LAZY))
716 const TCollection_AsciiString anError (aSharedLibrary.DlError());
717 Standard_SStream aMsg;
718 aMsg << "Could not open: " << aPluginLibrary << "; reason: " << anError;
720 std::cout << "could not open: " << aPluginLibrary << " ; reason: "<< anError << std::endl;
722 throw Draw_Failure(aMsg.str().c_str());
725 aFunc = aSharedLibrary.DlSymb ("PLUGINFACTORY");
728 const TCollection_AsciiString anError (aSharedLibrary.DlError());
729 Standard_SStream aMsg;
730 aMsg << "Could not find the factory in: " << aPluginLibrary << anError;
731 throw Draw_Failure(aMsg.str().c_str());
733 theMapOfFunctions.Bind (theKey, aFunc);
736 void (*fp) (Draw_Interpretor&) = NULL;
737 fp = (void (*)(Draw_Interpretor&) )aFunc;
743 const Standard_Integer THE_MAX_INTEGER_COLOR_COMPONENT = 255;
744 const Standard_ShortReal THE_MAX_REAL_COLOR_COMPONENT = 1.0f;
746 //! Parses string and get an integer color component (only values within range 0 .. 255 are allowed)
747 //! @param theColorComponentString the string representing the color component
748 //! @param theIntegerColorComponent an integer color component that is a result of parsing
749 //! @return true if parsing was successful, or false otherwise
750 static bool parseNumericalColorComponent (const Standard_CString theColorComponentString,
751 Standard_Integer& theIntegerColorComponent)
753 Standard_Integer anIntegerColorComponent;
754 if (!Draw::ParseInteger (theColorComponentString, anIntegerColorComponent))
758 if ((anIntegerColorComponent < 0) || (anIntegerColorComponent > THE_MAX_INTEGER_COLOR_COMPONENT))
762 theIntegerColorComponent = anIntegerColorComponent;
766 //! Parses the string and gets a real color component from it (only values within range 0.0 .. 1.0 are allowed)
767 //! @param theColorComponentString the string representing the color component
768 //! @param theRealColorComponent a real color component that is a result of parsing
769 //! @return true if parsing was successful, or false otherwise
770 static bool parseNumericalColorComponent (const Standard_CString theColorComponentString,
771 Standard_ShortReal& theRealColorComponent)
773 Standard_Real aRealColorComponent;
774 if (!Draw::ParseReal (theColorComponentString, aRealColorComponent))
778 const Standard_ShortReal aShortRealColorComponent = static_cast<Standard_ShortReal> (aRealColorComponent);
779 if ((aShortRealColorComponent < 0.0f) || (aShortRealColorComponent > THE_MAX_REAL_COLOR_COMPONENT))
783 theRealColorComponent = aShortRealColorComponent;
787 //! Parses the string and gets a real color component from it (integer values 2 .. 255 are scaled to the 0.0 .. 1.0
788 //! range, values 0 and 1 are leaved as they are)
789 //! @param theColorComponentString the string representing the color component
790 //! @param theColorComponent a color component that is a result of parsing
791 //! @return true if parsing was successful, or false otherwise
792 static bool parseColorComponent (const Standard_CString theColorComponentString,
793 Standard_ShortReal& theColorComponent)
795 Standard_Integer anIntegerColorComponent;
796 if (parseNumericalColorComponent (theColorComponentString, anIntegerColorComponent))
798 if (anIntegerColorComponent == 1)
800 theColorComponent = THE_MAX_REAL_COLOR_COMPONENT;
804 theColorComponent = anIntegerColorComponent * 1.0f / THE_MAX_INTEGER_COLOR_COMPONENT;
808 return parseNumericalColorComponent (theColorComponentString, theColorComponent);
811 //! Parses the array of strings and gets an integer color (only values within range 0 .. 255 are allowed and at least
812 //! one of components must be greater than 1)
813 //! @tparam TheNumber the type of resulting color vector elements
814 //! @param theNumberOfColorComponents the number of color components
815 //! @param theColorComponentStrings the array of strings representing color components
816 //! @param theNumericalColor a 4-component vector that is a result of parsing
817 //! @return true if parsing was successful, or false otherwise
818 template <typename TheNumber>
819 static bool parseNumericalColor (Standard_Integer& theNumberOfColorComponents,
820 const char* const* const theColorComponentStrings,
821 NCollection_Vec4<TheNumber>& theNumericalColor)
823 for (Standard_Integer aColorComponentIndex = 0; aColorComponentIndex < theNumberOfColorComponents;
824 ++aColorComponentIndex)
826 const char* const aColorComponentString = theColorComponentStrings[aColorComponentIndex];
827 TheNumber aNumericalColorComponent;
828 if (parseNumericalColorComponent (aColorComponentString, aNumericalColorComponent))
830 theNumericalColor[aColorComponentIndex] = aNumericalColorComponent;
834 if (aColorComponentIndex == 3)
836 theNumberOfColorComponents = 3;
847 //! Parses an array of strings and get an integer color (only values within range 0 .. 255 are allowed and at least
848 //! one of components must be greater than 1)
849 //! @param theNumberOfColorComponents the number of color components
850 //! @param theColorComponentStrings the array of strings representing color components
851 //! @param theColor a color that is a result of parsing
852 //! @return true if parsing was successful, or false otherwise
853 static bool parseIntegerColor (Standard_Integer& theNumberOfColorComponents,
854 const char* const* const theColorComponentStrings,
855 Quantity_ColorRGBA& theColor)
857 const Standard_Integer THE_COLOR_COMPONENT_NOT_PARSED = -1;
858 NCollection_Vec4<int> anIntegerColor (THE_COLOR_COMPONENT_NOT_PARSED);
859 if (!parseNumericalColor (theNumberOfColorComponents, theColorComponentStrings, anIntegerColor)
860 || anIntegerColor.maxComp() <= 1)
864 if (anIntegerColor.a() == THE_COLOR_COMPONENT_NOT_PARSED)
866 anIntegerColor.a() = THE_MAX_INTEGER_COLOR_COMPONENT;
869 const NCollection_Vec4<float> aRealColor = NCollection_Vec4<float> (anIntegerColor) / static_cast<float> (THE_MAX_INTEGER_COLOR_COMPONENT);
870 theColor = Quantity_ColorRGBA (Quantity_ColorRGBA::Convert_sRGB_To_LinearRGB (aRealColor));
874 //! Parses an array of strings and get a real color (only values within range 0.0 .. 1.0 are allowed)
875 //! @param theNumberOfColorComponents the number of color components
876 //! @param theColorComponentStrings the array of strings representing color components
877 //! @param theColor a color that is a result of parsing
878 //! @return true if parsing was successful, or false otherwise
879 static bool parseRealColor (Standard_Integer& theNumberOfColorComponents,
880 const char* const* const theColorComponentStrings,
881 Quantity_ColorRGBA& theColor)
883 NCollection_Vec4<float> aRealColor (THE_MAX_REAL_COLOR_COMPONENT);
884 if (!parseNumericalColor (theNumberOfColorComponents, theColorComponentStrings, aRealColor))
888 theColor = Quantity_ColorRGBA (aRealColor);
893 //=======================================================================
894 // function : parseColor
896 //=======================================================================
897 Standard_Integer Draw::parseColor (const Standard_Integer theArgNb,
898 const char* const* const theArgVec,
899 Quantity_ColorRGBA& theColor,
900 const bool theToParseAlpha)
902 if ((theArgNb >= 1) && Quantity_ColorRGBA::ColorFromHex (theArgVec[0], theColor, !theToParseAlpha))
906 if (theArgNb >= 1 && Quantity_ColorRGBA::ColorFromName (theArgVec[0], theColor))
908 if (theArgNb >= 2 && theToParseAlpha)
910 const Standard_CString anAlphaStr = theArgVec[1];
911 Standard_ShortReal anAlphaComponent;
912 if (parseColorComponent (anAlphaStr, anAlphaComponent))
914 theColor.SetAlpha (anAlphaComponent);
922 const Standard_Integer aNumberOfColorComponentsToParse = Min (theArgNb, theToParseAlpha ? 4 : 3);
923 Standard_Integer aNumberOfColorComponentsParsed = aNumberOfColorComponentsToParse;
924 if (parseIntegerColor (aNumberOfColorComponentsParsed, theArgVec, theColor))
926 return aNumberOfColorComponentsParsed;
928 aNumberOfColorComponentsParsed = aNumberOfColorComponentsToParse;
929 if (parseRealColor (aNumberOfColorComponentsParsed, theArgVec, theColor))
931 return aNumberOfColorComponentsParsed;
938 //=======================================================================
939 //function : ParseOnOff
941 //=======================================================================
942 Standard_Boolean Draw::ParseOnOff (Standard_CString theArg,
943 Standard_Boolean& theIsOn)
945 TCollection_AsciiString aFlag(theArg);
950 theIsOn = Standard_True;
951 return Standard_True;
953 else if (aFlag == "off"
956 theIsOn = Standard_False;
957 return Standard_True;
959 return Standard_False;
962 //=======================================================================
963 //function : ParseOnOffIterator
965 //=======================================================================
966 Standard_Boolean Draw::ParseOnOffIterator (Standard_Integer theArgsNb,
967 const char** theArgVec,
968 Standard_Integer& theArgIter)
970 Standard_Boolean isOn = Standard_True;
971 if (theArgIter + 1 < theArgsNb
972 && Draw::ParseOnOff (theArgVec[theArgIter + 1], isOn))
979 //=======================================================================
980 //function : ParseOnOffNoIterator
982 //=======================================================================
983 Standard_Boolean Draw::ParseOnOffNoIterator (Standard_Integer theArgsNb,
984 const char** theArgVec,
985 Standard_Integer& theArgIter)
987 Standard_Boolean toReverse = strncasecmp (theArgVec[theArgIter], "no", 2) == 0
988 || strncasecmp (theArgVec[theArgIter], "-no", 3) == 0;
989 Standard_Boolean isOn = Draw::ParseOnOffIterator (theArgsNb, theArgVec, theArgIter);
990 return toReverse ? !isOn : isOn;