0022337: V3d_View::Print crashes in OCCT 6.5.0
authorAPL <>
Wed, 7 Sep 2011 07:16:18 +0000 (07:16 +0000)
committerbugmaster <bugmaster@opencascade.com>
Mon, 5 Mar 2012 15:30:00 +0000 (19:30 +0400)
18 files changed:
src/Aspect/Aspect.cdl
src/Graphic3d/Graphic3d_GraphicDriver.cdl
src/Graphic3d/Graphic3d_GraphicDriver_Print.cxx
src/OpenGl/FILES
src/OpenGl/OpenGl_GraphicDriver.cdl
src/OpenGl/OpenGl_GraphicDriver_print.cxx
src/OpenGl/OpenGl_PrinterContext.cxx [new file with mode: 0644]
src/OpenGl/OpenGl_PrinterContext.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_TextRender.cxx
src/OpenGl/OpenGl_tgl_funcs.hxx
src/OpenGl/OpenGl_togl_begin_layer_mode.cxx
src/OpenGl/OpenGl_togl_print.cxx
src/OpenGl/OpenGl_view.cxx
src/V3d/V3d_View.cdl
src/V3d/V3d_View_Print.cxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
src/Visual3d/Visual3d_View.cdl
src/Visual3d/Visual3d_View_Print.cxx

index 10a489f..3b5bc46 100755 (executable)
@@ -844,6 +844,29 @@ is
         end TypeOfColorScaleOrientation;
         ---Purpose: Defines the type of color scale orientation
 
+        enumeration PrintAlgo is
+          PA_STRETCH,
+          PA_TILE
+        end PrintAlgo;
+        ---Purpose: Defines print algorithm
+        --          Aspect_PrintAlgo:
+        --          1) PA_STRETCH - Stretch offscreen printing frame
+        --                          if its dimensions are smaller than
+        --                          the printer's printing area dimensions;
+        --                          This algorithm is more reliable as it
+        --                          works on any hardware and is recommended
+        --                          to be used with average printing resolutions,
+        --                          as it more RAM memory dependent than PA_TILE;
+        --                          Stretching is performend using bicubic interpolation
+        --                          algorithm from FreeImage library if OCCT is built
+        --                          with FreeImage support, otherwise Windows API 
+        --                          StretchBlt() function in STRETCH_HALFTONE mode
+        --                          is used;
+        --          2) PA_TILE    - If the offscreen printing frame dimensions
+        --                          are smaller than the printer's printing
+        --                          area dimensions - use multiple printing
+        --                          frames to cover the whole printing area
+
         ---------------------------------
         -- Category: Instantiated classes
         ---------------------------------
index 3f6c369..6bc9d05 100755 (executable)
@@ -66,6 +66,7 @@ uses
     TypeOfTriedronPosition  from Aspect,
     Handle              from Aspect,
     Display             from Aspect,
+    PrintAlgo           from Aspect,
 
     AspectLine3d        from Graphic3d,
     AspectMarker3d      from Graphic3d,
@@ -1300,8 +1301,10 @@ is
            ACOverLayer     : CLayer2d from Aspect;
            hPrnDC          : Handle from Aspect;
            showBackground  : Boolean;
-           filename        : CString)
-        is deferred;
+           filename        : CString;
+           printAlgorithm  : PrintAlgo from Aspect = Aspect_PA_STRETCH;
+           theScaleFactor  : Real from Standard = 1.0 )
+        returns Boolean from Standard is deferred;
       ---Level: Internal
       ---Purpose: print the contents of all layers of the view to the printer.
     -- <hPrnDC> : Pass the PrinterDeviceContext (HDC),
@@ -1309,6 +1312,13 @@ is
     -- (background is white)
       -- else set to TRUE for printing with current background color.
     -- <filename>: If != NULL, then the view will be printed to a file.
+    -- <printAlgorithm>: Select print algorithm: stretch, tile.   
+    -- <theScaleFactor>: Scaling coefficient, used internally to scale the
+    -- printings accordingly to the scale factor selected in the printer 
+    -- properties dialog.
+    -- Returns Standard_True if the data is passed to the printer, otherwise
+    -- Standard_False if the print operation failed due to the printer errors, 
+    -- or insufficient system memory available.
     ---Warning: Works only under Windows.
 
 
index 0ee4d5d..ddc2075 100755 (executable)
 /* Print Methods                                                        */
 /************************************************************************/
 
-void Graphic3d_GraphicDriver::Print (const Graphic3d_CView& , 
-                                     const Aspect_CLayer2d& , 
-                                     const Aspect_CLayer2d& , 
-                                     const Aspect_Handle ,
-                                     const Standard_Boolean ,
-                                     const Standard_CString ) const {
-                                     }
+Standard_Boolean Graphic3d_GraphicDriver::Print (const Graphic3d_CView& , 
+                                                 const Aspect_CLayer2d& , 
+                                                 const Aspect_CLayer2d& , 
+                                                 const Aspect_Handle ,
+                                                 const Standard_Boolean ,
+                                                 const Standard_CString ,
+                                                 const Aspect_PrintAlgo ,
+                                                const Standard_Real ) const
+{
+  return Standard_False;
+}
index 8dcd730..fbbb96b 100755 (executable)
@@ -247,3 +247,5 @@ OpenGl_ResourceVBO.cxx
 OpenGl_ResourceVBO.hxx
 OpenGl_ResourceTexture.cxx
 OpenGl_ResourceTexture.hxx
+OpenGl_PrinterContext.cxx
+OpenGl_PrinterContext.hxx
index 19af1a5..9f59be9 100755 (executable)
@@ -49,6 +49,7 @@ uses
     TypeOfTriedronPosition  from Aspect,
     Handle              from Aspect,
     Display             from Aspect,
+    PrintAlgo           from Aspect,
 
     AspectLine3d        from Graphic3d,
     AspectMarker3d      from Graphic3d,
@@ -1208,8 +1209,10 @@ is
              ACOverLayer     : CLayer2d from Aspect;
              hPrnDC          : Handle from Aspect;
              showBackground  : Boolean;
-             filename        : CString)
-        is redefined static;
+             filename        : CString;
+             printAlgorithm  : PrintAlgo from Aspect = Aspect_PA_STRETCH;
+             theScaleFactor  : Real from Standard = 1.0 ) 
+        returns Boolean from Standard is redefined static;
       ---Level: Internal
       ---Purpose: print the contents of all layers of the view to the printer.
     -- <hPrnDC> : Pass the PrinterDeviceContext (HDC),
@@ -1217,6 +1220,17 @@ is
     -- (background is white)
       -- else set to TRUE for printing with current background color.
     -- <filename>: If != NULL, then the view will be printed to a file.
+    -- <printAlgorithm>: Select print algorithm: stretch, tile.
+    -- <theScaleFactor>: Scaling coefficient, used internally to scale the
+    -- printings accordingly to the scale factor selected in the printer 
+    -- properties dialog.
+    -- Returns Standard_True if the data is passed to the printer, otherwise
+    -- Standard_False if the print operation failed due to the printer errors, 
+    -- or lack of system memory. This might be related to insufficient memory
+    -- or some internal errors. All this errors are indicated by the message 
+    -- boxes (on level of OpenGl_GraphicDriver).
+    -- Warning: This function can reuse FBO assigned to the view
+    -- Please take it into account if you use it for your purposes;
     ---Warning: Works only under Windows.
 
 
index 05d1cda..ef1646a 100755 (executable)
 /* Print Methods                                                        */
 /************************************************************************/
 
-void OpenGl_GraphicDriver::Print (const Graphic3d_CView& ACView, 
-                                  const Aspect_CLayer2d& ACUnderLayer, 
-                                  const Aspect_CLayer2d& ACOverLayer,
-                                  const Aspect_Handle    hPrintDC,
-                                  const Standard_Boolean showBackground,
-                                  const Standard_CString filename ) const
+Standard_Boolean OpenGl_GraphicDriver::Print
+  (const Graphic3d_CView& ACView, 
+   const Aspect_CLayer2d& ACUnderLayer, 
+   const Aspect_CLayer2d& ACOverLayer,
+   const Aspect_Handle    hPrintDC,
+   const Standard_Boolean showBackground,
+   const Standard_CString filename,
+   const Aspect_PrintAlgo printAlgorithm,
+   const Standard_Real theScaleFactor) const
 {
 
 #ifdef WNT
@@ -35,11 +38,12 @@ void OpenGl_GraphicDriver::Print (const Graphic3d_CView& ACView,
     PrintFunction ("call_togl_print");
     PrintCView (MyCView, 1);
   }
-  call_togl_print (&MyCView, &MyCUnderLayer, &MyCOverLayer,
-    hPrintDC, (int)showBackground, filename);
+  return call_togl_print (&MyCView, &MyCUnderLayer, &MyCOverLayer,
+                          hPrintDC, (int)showBackground, filename,
+                          (int)printAlgorithm, (float)theScaleFactor);
 #else
   Standard_NotImplemented::Raise ("OpenGl_GraphicDriver::Print is implemented "
     "only on Windows");
-
+  return Standard_False;
 #endif
 }
diff --git a/src/OpenGl/OpenGl_PrinterContext.cxx b/src/OpenGl/OpenGl_PrinterContext.cxx
new file mode 100644 (file)
index 0000000..4e3d4b2
--- /dev/null
@@ -0,0 +1,110 @@
+// File:      OpenGl_PrinterContext.cxx
+// Created:   20.05.11 10:00:00
+// Author:    Anton POLETAEV
+
+#include <OpenGl_PrinterContext.hxx>
+
+OpenGl_PrinterContext* OpenGl_PrinterContext::g_PrinterContext = NULL;
+GLCONTEXT              OpenGl_PrinterContext::g_ContextId      = NULL;
+
+//=======================================================================
+//function : OpenGl_PrinterContext
+//purpose  : Constructor
+//=======================================================================
+
+OpenGl_PrinterContext::OpenGl_PrinterContext (GLCONTEXT theCtx) :
+  myCtx (theCtx), myProjTransform (0, 3, 0, 3), myLayerViewportX (0),
+  myLayerViewportY (0), myScaleX (1.0f), myScaleY (1.0f)
+{
+  // assign global instance to the current object
+  if (myCtx != NULL)
+  {
+    g_PrinterContext = this;
+    g_ContextId      = myCtx;
+  }
+
+  // init projection matrix
+  Standard_Real anInitValue = 0.0;
+  myProjTransform.Init (anInitValue);
+  myProjTransform (0,0)  = 1.0f;
+  myProjTransform (1,1)  = 1.0f;
+  myProjTransform (2,2)  = 1.0f;
+  myProjTransform (3,3)  = 1.0f;
+}
+
+//=======================================================================
+//function : ~OpenGl_PrinterContext
+//purpose  : Destructor
+//=======================================================================
+
+OpenGl_PrinterContext::~OpenGl_PrinterContext () 
+{
+  // unassign global instance
+  if (g_PrinterContext == this)
+  {
+    g_ContextId      = NULL;
+    g_PrinterContext = NULL;
+  }
+}
+
+//=======================================================================
+//function : GetProjTransformation
+//purpose  : Get view projection transformation matrix.
+//=======================================================================
+
+void OpenGl_PrinterContext::GetProjTransformation (GLfloat theMatrix[16])
+{
+  for (int i = 0, k = 0; i < 4; i++)
+    for (int j = 0; j < 4; j++, k++)
+      theMatrix[k] = (GLfloat)myProjTransform (i,j);
+}
+
+//=======================================================================
+//function : SetProjTransformation
+//purpose  : Set view projection transformation matrix for printing purposes.
+//           theProjTransform parameter should be an 4x4 array.
+//=======================================================================
+
+bool OpenGl_PrinterContext::SetProjTransformation (TColStd_Array2OfReal& thePrj)
+{
+  if (thePrj.RowLength () != 4 || thePrj.ColLength () != 4)
+    return false;
+
+  myProjTransform = thePrj;
+
+  return true;
+}
+
+//=======================================================================
+//function : Deactivate
+//purpose  : Deactivate PrinterContext object.
+//           Useful when you need to redraw in usual mode the same
+//           OpenGl context that you used for printing right after printing,
+//           before the OpenGl_PrinterContext instance destroyed
+//=======================================================================
+
+void OpenGl_PrinterContext::Deactivate ()
+{
+  // unassign global instance
+  if (g_PrinterContext == this)
+  {
+    g_ContextId      = NULL;
+    g_PrinterContext = NULL;
+  }
+}
+
+
+//=======================================================================
+//function : GetInstance
+//purpose  : Get the PrinterContext instance assigned for OpenGl context.
+//           Return NULL, if there is no current printing operation and
+//           there is no assigned instance for "theCtx" OpenGl context.
+//=======================================================================
+
+OpenGl_PrinterContext* OpenGl_PrinterContext::GetPrinterContext (GLCONTEXT theCtx)
+{
+  if (g_ContextId == theCtx)
+    return g_PrinterContext;
+  else
+    return NULL;
+}
diff --git a/src/OpenGl/OpenGl_PrinterContext.hxx b/src/OpenGl/OpenGl_PrinterContext.hxx
new file mode 100644 (file)
index 0000000..2f117fd
--- /dev/null
@@ -0,0 +1,116 @@
+// File:      OpenGl_PrinterContext.hxx
+// Created:   20.05.11 10:00:00
+// Author:    Anton POLETAEV
+
+#ifndef _OPENGL_PRINTERCONTEXT_H
+#define _OPENGL_PRINTERCONTEXT_H
+
+#include <MMgt_TShared.hxx>
+#include <Standard.hxx>
+#include <Standard_DefineHandle.hxx>
+#include <Handle_MMgt_TShared.hxx>
+#include <OpenGl_tgl_all.hxx>
+#include <NCollection_DataMap.hxx>
+#include <InterfaceGraphic_Graphic3d.hxx>
+#include <InterfaceGraphic_Visual3d.hxx>
+#include <TColStd_Array2OfReal.hxx>
+
+class Standard_Transient;
+class Handle(Standard_Type);
+class Handle(MMgt_TShared);
+class OpenGl_PrinterContext;
+
+DEFINE_STANDARD_HANDLE(OpenGl_PrinterContext,MMgt_TShared)
+
+//! Class provides specific information for redrawing view to offscreen buffer
+//! on printing. The information is: projection matrixes for tiling,
+//! scaling factors for text/markers and layer viewport dimensions.
+//! The OpenGl_PrinterContext class allows to have only one global instance
+//! that can be accessed by GetPrinterContext() during printing operation. 
+//! The class instance can be created only by call_togl_print().
+class OpenGl_PrinterContext : public MMgt_TShared
+{
+
+public:
+
+  //! Get the PrinterContext instance assigned for OpenGl context.
+  //! Return NULL, if there is no current printing operation and
+  //! there is no assigned instance for "theCtx" OpenGl context.
+  static OpenGl_PrinterContext* GetPrinterContext(GLCONTEXT theCtx);
+
+  //! Get view projection transformation matrix.
+  const TColStd_Array2OfReal& GetProjTransformation () 
+  {
+    return myProjTransform; 
+  }
+
+  //! Get view projection transformation matrix.
+  void GetProjTransformation (GLfloat theMatrix[16]); 
+
+  //! Get text/markers scale factor
+  void GetScale (GLfloat& theScaleX, GLfloat& theScaleY)
+  {
+    theScaleX = myScaleX;
+    theScaleY = myScaleY;
+  }
+
+  //! Get layer viewport dimensions
+  void GetLayerViewport (GLsizei& theViewportX,
+                         GLsizei& theViewportY)
+  {
+    theViewportX = myLayerViewportX;
+    theViewportY = myLayerViewportY;
+  }
+
+private:
+
+  //! Constructor
+  OpenGl_PrinterContext (GLCONTEXT theCtx);
+
+  //! Destructor
+  virtual ~OpenGl_PrinterContext ();
+
+  //! Deactivate current printing context.
+  //! Useful when you need to redraw in usual mode the same OpenGl context
+  //! that you used for printing right after printing, before the 
+  //! OpenGl_PrinterContext instance destroyed.
+  void Deactivate ();
+
+  //! Set view projection transformation matrix for printing/tiling purposes
+  //! theProjTransform parameter should be an 4x4 array.
+  bool SetProjTransformation (TColStd_Array2OfReal& theProjTransform);
+
+  //! Set text scale factor
+  void SetScale (GLfloat theScaleX, GLfloat theScaleY)
+  {
+    myScaleX = theScaleX;
+    myScaleY = theScaleY;
+  }
+
+  //! Set layer viewport dimensions
+  void SetLayerViewport (GLsizei theViewportX,
+                         GLsizei theViewportY) 
+  {
+    myLayerViewportX = theViewportX; 
+    myLayerViewportY = theViewportY;
+  }
+
+private:
+
+  static OpenGl_PrinterContext* g_PrinterContext;
+  static GLCONTEXT g_ContextId;
+  TColStd_Array2OfReal myProjTransform;
+  GLfloat              myScaleX;
+  GLfloat              myScaleY;
+  GLsizei              myLayerViewportX;
+  GLsizei              myLayerViewportY;
+  GLCONTEXT            myCtx;
+
+  // the printer context could be created only in method call_togl_print
+  friend Standard_Boolean call_togl_print (CALL_DEF_VIEW *, CALL_DEF_LAYER *,
+                                           CALL_DEF_LAYER *, 
+                                           const Aspect_Drawable, const int,
+                                           const char*, const int, const float);
+};
+
+#endif
index e0d9a93..147ae52 100755 (executable)
@@ -4,16 +4,16 @@
 #include <stdio.h>
 #include <string.h>
 
-#include <TCollection_AsciiString.hxx>
-#include <TCollection_HAsciiString.hxx>
-
-#include <Standard_Stream.hxx>
-
+#include <OpenGl_tgl_all.hxx>
 #include <OpenGl_FontMgr.hxx>   
 #include <OpenGl_tgl_funcs.hxx>
 #include <OpenGl_TextRender.hxx>
 #include <OpenGl_telem_attri.hxx>
 #include <OpenGl_cmn_varargs.hxx>
+#include <OpenGl_PrinterContext.hxx>
+#include <Standard_Stream.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <TCollection_HAsciiString.hxx>
 
 #include <OSD_Environment.hxx>
 #include <Quantity_NameOfColor.hxx>
@@ -384,6 +384,22 @@ void OpenGl_TextRender::RenderText ( const wchar_t* str, GLuint base, int is2d,
 
     if( ! zoom )
     {
+#ifdef WNT
+      // if the context has assigned printer context, use it's parameters
+      OpenGl_PrinterContext* aPrinterContext = 
+        OpenGl_PrinterContext::GetPrinterContext( GET_GL_CONTEXT() );
+      if( aPrinterContext )
+      {
+        // get printing scaling in x and y dimensions
+        GLfloat aTextScalex = 1, aTextScaley = 1;
+        aPrinterContext->GetScale( aTextScalex, aTextScaley );
+        
+        // text should be scaled in all directions with same
+        // factor to save its proportions, so use height (y) scaling
+        // as it is better for keeping text/3d graphics proportions
+        glScalef( aTextScaley, aTextScaley, aTextScaley );
+      }
+#endif
       glScaled( h, h, h );
     }
     else
index a4d3e6d..5b4fad7 100755 (executable)
@@ -1334,16 +1334,18 @@ void EXPORT call_togl_userdraw (
                                 );
 
 /* ------------------------- */
-void EXPORT call_togl_print (
-
-                             CALL_DEF_VIEW *aview,
-                             CALL_DEF_LAYER *anunderlayer,
-                             CALL_DEF_LAYER *anoverlayer,
-                             const Aspect_Drawable hPrintDC,
-                             const int background,
-                             const char* filename
-
-                             );
+Standard_Boolean EXPORT call_togl_print (
+
+                                         CALL_DEF_VIEW *aview,
+                                         CALL_DEF_LAYER *anunderlayer,
+                                         CALL_DEF_LAYER *anoverlayer,
+                                         const Aspect_Drawable hPrintDC,
+                                         const int background,
+                                         const char* filename,
+                                         const int printalgo = 0,
+                                         const float theScaleFactor = 1.0
+
+                                         );
 
 
 #ifdef BUC61044
index 7213a57..5729b1e 100755 (executable)
@@ -57,6 +57,7 @@ HISTORIQUE DES MODIFICATIONS   :
 #include <Visual3d_Layer.hxx>
 
 #include <OpenGl_Extension.hxx>
+#include <OpenGl_PrinterContext.hxx>
 
 /*----------------------------------------------------------------------*/
 /*
@@ -297,6 +298,35 @@ call_togl_redraw_layer2d (
   printf ("\tratio %f new ortho %f %f %f %f\n",
     ratio, left, right, bottom, top);
 #endif
+
+#ifdef WNT
+  // Check printer context that exists only for print operation
+  OpenGl_PrinterContext* aPrinterContext = 
+    OpenGl_PrinterContext::GetPrinterContext (GET_GL_CONTEXT());
+
+  if (aPrinterContext)
+  {
+    // additional transformation matrix could be applied to
+    // render only those parts of viewport that will be
+    // passed to a printer as a current "frame" to provide
+    // tiling; scaling of graphics by matrix helps render a
+    // part of a view (frame) in same viewport, but with higher
+    // resolution
+    GLfloat aProjMatrix[16];
+    aPrinterContext->GetProjTransformation (aProjMatrix);
+    glLoadMatrixf ((GLfloat*) aProjMatrix);
+
+    // printing operation also assumes other viewport dimension
+    // to comply with transformation matrix or graphics scaling
+    // factors for tiling for layer redraw
+    GLsizei anViewportX = 0;
+    GLsizei anViewportY = 0;
+    aPrinterContext->GetLayerViewport (anViewportX, anViewportY);
+    if (anViewportX != 0 && anViewportY != 0)
+      glViewport (0, 0, anViewportX, anViewportY);
+  }
+#endif 
+
   glOrtho (left, right, bottom, top, -1.0, 1.0);
 
 #ifdef TRACE_MAT
index ed55b8f..d5b580b 100755 (executable)
@@ -17,85 +17,315 @@ e-mail t-hartl@muenchen.matra-dtv.fr  */
 #include <OpenGl_tgl_funcs.hxx>
 #include <OpenGl_tgl_subrvis.hxx>
 #include <OpenGl_animation.hxx>
-
+#include <OpenGl_FrameBuffer.hxx>
+#include <OpenGl_PrinterContext.hxx>
+#include <Visual3d_Layer.hxx>
+#include <TColStd_Array2OfReal.hxx>
 #include <string.h>
 
-/* SAV - begin */
-/* MSDN says: point is 1/72 inch. But in our case text height in the 3D view
-differs from printed one. An experiment showed that delimeter equal to 2*72 gives
-practically equal text heights. */
-int defaultDelimeter = 72;
-int delimeter = 144;
-int defaultPntSize = 12;
+#ifdef HAVE_FREEIMAGE
+  #include <NCollection_Handle.hxx>
+  #include <FreeImagePlus.h>
+  #ifdef _MSC_VER
+  #pragma comment( lib, "FreeImage.lib" )
+  #pragma comment( lib, "FreeImagePlus.lib" )
+  #endif
+  typedef NCollection_Handle<fipImage> FipHandle;
+#endif
 
-GLuint printerFontBase = 0;
+// ---------------------------------------------------------------
+// Function: getNearestPowOfTwo
+// Purpose:  get the nearest power of two for theNumber
+// ---------------------------------------------------------------
+static GLsizei getNearestPowOfTwo (const GLsizei theNumber)
+{
+  GLsizei aLast = 1;
+  for (GLsizei p2 = 1; p2 <= theNumber; aLast = p2, p2 <<= 1);
+  return aLast;
+}
 
-/* printer DC needed to avoid passing OS specific type as a procedure parameter */
-#ifdef WNT
-HDC     printer;
-HGDIOBJ oldObj;
-#endif
+// ---------------------------------------------------------------
+// Function: getMaxFrameSize
+// Purpose:  get the maximum possible frame size
+// ---------------------------------------------------------------
+static void getMaxFrameSize(Standard_Integer& theWidth,
+                            Standard_Integer& theHeight)
+{
+  GLsizei aMaxX, aMaxY;
+  GLint aVpDim[2];
+  GLint aTexDim = 2048;
+  glGetIntegerv (GL_MAX_VIEWPORT_DIMS, (GLint*) &aVpDim);
+  glGetIntegerv (GL_MAX_TEXTURE_SIZE, &aTexDim);
+  (aVpDim[0] >= aTexDim) ? aMaxX = (GLsizei) aTexDim : 
+                           aMaxX = getNearestPowOfTwo((GLsizei)aVpDim[0]);
+  (aVpDim[1] >= aTexDim) ? aMaxY = (GLsizei) aTexDim :
+                           aMaxY = getNearestPowOfTwo((GLsizei)aVpDim[1]);
+
+  theWidth  = (Standard_Integer)aMaxX;
+  theHeight = (Standard_Integer)aMaxY;
+}
 
-GLuint createFont( char* typeFace, int height, int weight, int italic )
+// ---------------------------------------------------------------
+// Function: fitDimensionsRatio
+// Purpose:  calculate correct width/height ratio for theWidth and
+//           theHeight parameters
+// ---------------------------------------------------------------
+static void fitDimensionsRatio (Standard_Integer& theWidth,
+                                Standard_Integer& theHeight,
+                                const Standard_Real theViewRatio)
 {
-#ifdef WNT
-  /* no unicode support yet*/
-  HFONT  font;
-  GLuint base;
-  DWORD  charSet = ANSI_CHARSET;
-
-  if ( ( base = glGenLists( 96 ) ) == 0 )
-    return 0;
-
-  if ( _stricmp( typeFace, "symbol" ) == 0 )
-    charSet = SYMBOL_CHARSET;
-
-  font = CreateFont( height, 0, 0, 0, weight, italic, FALSE, FALSE,
-    charSet, OUT_TT_PRECIS,
-    CLIP_DEFAULT_PRECIS, DRAFT_QUALITY,
-    DEFAULT_PITCH, typeFace );
-  oldObj = SelectObject( printer, font );
-  wglUseFontBitmaps( printer, 32, 96, base );
-  return base;
-#endif
-  return 0;
+  // set dimensions in accordance with the viewratio
+  if (theHeight <  theWidth/theViewRatio)
+      theWidth  = (Standard_Integer)(theHeight*theViewRatio);
+
+  if (theWidth  <  theHeight*theViewRatio)
+      theHeight = (Standard_Integer)(theWidth/theViewRatio);
 }
 
-void deleteFont( GLuint base )
+// ---------------------------------------------------------------
+// Function: getDimensionsTiling
+// Purpose:  calculate maximum possible dimensions for framebuffer 
+//           in tiling mode according to the view size
+// ---------------------------------------------------------------
+static void getDimensionsTiling (Standard_Integer& theFrameWidth,
+                                 Standard_Integer& theFrameHeight,
+                                 const int theViewWidth,
+                                 const int theViewHeight)
 {
-#ifdef WNT
-  HFONT currentFont;
-
-  if ( base == 0 )
-    /* no font created */
-    return;
-  /* deleting font list id */
-  glDeleteLists( base, 96 );
-  currentFont = (HFONT)SelectObject( printer, oldObj );
-  /* deleting current font structure */
-  DeleteObject( currentFont );
-#endif
+  // fit the maximum dimensions into the printing area
+  if (theFrameWidth > theViewWidth)
+      theFrameWidth = theViewWidth;
+
+  if (theFrameHeight > theViewHeight)
+      theFrameHeight = theViewHeight;
+}
+
+// ---------------------------------------------------------------
+// Function: initBufferStretch
+// Purpose:  calculate initialization sizes for frame buffer
+//           when the stretch algorithm is selected
+// ---------------------------------------------------------------
+static void initBufferStretch (Standard_Integer& theFrameWidth,
+                               Standard_Integer& theFrameHeight,
+                               const int theViewWidth,
+                               const int theViewHeight)
+{
+
+  // Calculate correct width/height for framebuffer
+  Standard_Real aViewRatio = (Standard_Real)theViewWidth/theViewHeight;
+  fitDimensionsRatio (theFrameWidth, theFrameHeight, aViewRatio);
+
+  // downscale the framebuffer if it is too large
+  Standard_Real aWidthRate  = (Standard_Real)theFrameWidth /theViewWidth;
+  Standard_Real aHeightRate = (Standard_Real)theFrameHeight/theViewHeight;
+
+  if ((aWidthRate > 1 && aHeightRate > 1 && aWidthRate >= aHeightRate) || 
+      (aWidthRate > 1 && aHeightRate <= 1))
+  {
+    theFrameWidth  = (Standard_Integer)(theFrameWidth /aWidthRate);
+    theFrameHeight = (Standard_Integer)(theFrameHeight/aWidthRate);
+  }
+  else if ((aWidthRate  > 1 && aHeightRate > 1 && aWidthRate < aHeightRate) ||
+           (aWidthRate <= 1 && aHeightRate > 1))
+  {
+    theFrameWidth  = (Standard_Integer)(theFrameWidth /aHeightRate);
+    theFrameHeight = (Standard_Integer)(theFrameHeight/aHeightRate);
+  }
+
+}
+
+// ---------------------------------------------------------------
+// Function: initBufferTiling
+// Purpose:  calculate initialization sizes for frame buffer
+//           when the tile algorithm is selected
+// ---------------------------------------------------------------
+static void initBufferTiling (Standard_Integer& theFrameWidth,
+                              Standard_Integer &theFrameHeight,
+                              const int theViewWidth,
+                              const int theViewHeight)
+{
+  // fit framebuffer into the printing area
+  if (theFrameWidth > theViewWidth)
+      theFrameWidth = theViewWidth;
+
+  if (theFrameHeight > theViewHeight)
+      theFrameHeight = theViewHeight;
 }
 
-void updatePrinterFont( char* type, int height )
+// ---------------------------------------------------------------
+// Function: redrawView
+// Purpose:  redraw view in printing mode
+// ---------------------------------------------------------------
+static void redrawView (CALL_DEF_VIEW *aview, 
+                        CALL_DEF_LAYER *anunderlayer, 
+                        CALL_DEF_LAYER *anoverlayer,
+                        const int isBackground)
 {
+  // prepare for redraw
+  call_func_redraw_all_structs_begin (aview->WsId);
+  call_togl_setplane (aview);
+
+  // clear background
+  if (isBackground == 0)
+  {
+    glClearColor (1.0, 1.0, 1.0, 1.0);
+    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  }
+
+  // draw underlayer
+  if (anunderlayer->ptrLayer)
+  {
+    call_togl_redraw_layer2d (aview, anunderlayer);
+  }
+
+  // redraw main plane
+  call_func_redraw_all_structs_proc (aview->WsId);
+  call_subr_displayCB (aview,OCC_REDRAW_BITMAP | OCC_PRE_OVERLAY);
+  // draw overlayer
+  if (anoverlayer->ptrLayer)
+  {
+    call_togl_redraw_layer2d (aview, anoverlayer);
+  }
+  call_subr_displayCB (aview,OCC_REDRAW_BITMAP);
+
+
+  // tell to end redrawing
+  call_func_redraw_all_structs_end (aview->WsId, 0);
+  call_togl_redraw_immediat_mode (aview);
+}
+
+// ---------------------------------------------------------------
+// Function: initBitmapBuffer
+// Purpose:  init device independent bitmap to hold printing data
+// ---------------------------------------------------------------
 #ifdef WNT
-  int delim = delimeter;
-  if ( height <= 0 ) {
-    height = defaultPntSize;
-    delim = defaultDelimeter;
+#ifndef HAVE_FREEIMAGE
+static void initBitmapBuffer (const HDC theMemoryDC,
+                              HBITMAP &theMemoryBmp,
+                              const   Standard_Integer theBmpWidth,
+                              const   Standard_Integer theBmpHeight,
+                              VOID*   &theBufferPtr)
+{
+  // define compatible bitmap
+  BITMAPINFO aBitmapData;
+  memset (&aBitmapData, 0, sizeof (BITMAPINFOHEADER));
+  aBitmapData.bmiHeader.biSize          = sizeof (BITMAPINFOHEADER);
+  aBitmapData.bmiHeader.biWidth         = theBmpWidth;
+  aBitmapData.bmiHeader.biHeight        = theBmpHeight;
+  aBitmapData.bmiHeader.biPlanes        = 1;
+  aBitmapData.bmiHeader.biBitCount      = 24;
+  aBitmapData.bmiHeader.biXPelsPerMeter = 0;
+  aBitmapData.bmiHeader.biYPelsPerMeter = 0;
+  aBitmapData.bmiHeader.biClrUsed       = 0;
+  aBitmapData.bmiHeader.biClrImportant  = 0;
+  aBitmapData.bmiHeader.biCompression   = BI_RGB;
+  aBitmapData.bmiHeader.biSizeImage     = 0;
+
+  // Create Device Independent Bitmap
+  theMemoryBmp = CreateDIBSection (theMemoryDC, &aBitmapData, DIB_RGB_COLORS,
+                                   &theBufferPtr, NULL, 0);
+}
+#else
+// ---------------------------------------------------------------
+// Function: imagePasteDC
+// Purpose:  copy the data from image buffer to the device context
+// ---------------------------------------------------------------
+static bool imagePasteDC(HDC theDstDC,    FipHandle theImage, int theOffsetX,
+                         int theOffsetY,  int theWidth, int theHeight, 
+                         int theLeft = 0, int theTop = 0)
+{
+  // get image parameters
+  BITMAPINFO* aBitmapData = theImage->getInfo ();
+  SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
+  // organize blocks data passing if memory isn't enough to pass all the data
+  // at once
+  int aLinesComplete = 0, aMaxBlockWidth = theHeight, aBlockWidth = 0,
+      aPassed        = 0, aInverseLine   = 0, aScan = 0;
+  BYTE *aDataPtr = 0;
+  while (aMaxBlockWidth >= 1 && aLinesComplete < theHeight)
+  {
+    // how much lines still to pass
+    aBlockWidth = theHeight - aLinesComplete;
+
+    // normalize count of lines to pass to maximum lines count at one pass.
+    if (aBlockWidth > aMaxBlockWidth)
+      aBlockWidth = aMaxBlockWidth;
+
+    // access image data at the start scan line, we need to calculate scan from
+    // the bottom of image (image is bottom-left, the src coord is top-left)
+    aInverseLine = theTop + aBlockWidth + aLinesComplete;
+    aScan = theImage->getHeight() - aInverseLine;
+    aDataPtr = theImage->getScanLine (aScan);
+    if (!aDataPtr)
+      return false;
+
+    // try to pass block to the device
+    if (aBlockWidth > 0)
+    {
+      // instead of banded output we provide blocked as it isn't always passed
+      // to printer as it is expected
+      aPassed = SetDIBitsToDevice (theDstDC, theOffsetX,
+                                   theOffsetY + aLinesComplete,
+                                   theWidth, aBlockWidth, theLeft, 0,
+                                   0, aBlockWidth,
+                                   aDataPtr, aBitmapData, DIB_RGB_COLORS);
+
+      // if result is bad, try to decrease band width
+      if (aPassed != aBlockWidth)
+      {
+        aMaxBlockWidth = aMaxBlockWidth >> 1;
+        aLinesComplete = 0;
+      }
+      else
+        aLinesComplete += aBlockWidth;
+    }
   }
-  /* deleting old font */
-  deleteFont( printerFontBase );
-  /* creating new one */
-  printerFontBase = createFont( type, -MulDiv( height, GetDeviceCaps( printer, LOGPIXELSY ), delim ),
-    (int)FW_NORMAL, 0 );
-#endif
+
+  // check for total failure
+  if (aMaxBlockWidth < 1)
+    return false;
+
+  return true;
 }
-/* SAV - end */
 
+// ---------------------------------------------------------------
+// Function: imageStretchDC
+// Purpose:  copy pixels from image to dc by stretching them
+// ---------------------------------------------------------------
+static bool imageStretchDC(HDC theDstDC,   FipHandle theImage, int theOffsetX,
+                           int theOffsetY, int theWidth, int theHeight)
+{
+  // access to raw image data
+  BYTE *aDataPtr = theImage->accessPixels ();
+  if (!aDataPtr)
+    return false;
+
+  // get image parameters
+  unsigned int widthPx    = theImage->getWidth ();
+  unsigned int heightPx   = theImage->getHeight ();
+  BITMAPINFO* aBitmapData = theImage->getInfo ();
+  SetStretchBltMode (theDstDC, STRETCH_HALFTONE);
+  
+  // pass lines and check if operation is succesfull
+  int aPassed = 0;
+  aPassed = StretchDIBits (theDstDC, theOffsetX, theOffsetY, theWidth,
+                           theHeight, 0, 0, widthPx, heightPx, aDataPtr,
+                           aBitmapData, DIB_RGB_COLORS, SRCCOPY);
+
+  if (aPassed != heightPx)
+    return false;
+  return true;
+}
+#endif
+#endif
 
-void EXPORT
+// ---------------------------------------------------------------
+// Function: call_togl_print
+// Purpose:
+// ---------------------------------------------------------------
+Standard_Boolean EXPORT
 call_togl_print
 (
  CALL_DEF_VIEW *aview,
@@ -103,295 +333,470 @@ call_togl_print
  CALL_DEF_LAYER *anoverlayer,
  const Aspect_Drawable hPrintDC,
  const int background,
- const char* filename
+ const char* filename,
+ const int   printalgo,
+ const float theScaleFactor
  )
 {
 
 #ifdef WNT
 
-  CMN_KEY_DATA data;
-  Tint swap = 1; /* swap buffers ? yes */
+  CMN_KEY_DATA data; 
+  DOCINFO di;
+  bool IsTiling = (printalgo == 1);
+  HDC  hPrnDC   = (HDC) hPrintDC;
+
+  TsmGetWSAttri (aview->WsId, WSWindow, &data);
+  if (TxglWinset (call_thedisplay, (WINDOW) data.ldata) != TSuccess)
+  {
+    MessageBox (NULL, "Print failed: can't setup the view for printing.",
+                "The operation couldn't be completed.", MB_OK);
+    return Standard_False;
+  }
 
+  // printer page dimensions
+  int devWidth  = GetDeviceCaps (hPrnDC, HORZRES);
+  int devHeight = GetDeviceCaps (hPrnDC, VERTRES);
 
-  BOOL bRet = FALSE;
-  HDC hPrnDC;
-  DOCINFO   di;
+  // if context is actually a memory dc, try to retrieve bitmap dimensions
+  // (memory dc could be used for testing purposes)
+  if (GetObjectType (hPrnDC) == OBJ_MEMDC)
+  {
+    // memory dc dimensions
+    BITMAP aBitmapInfo;
+    HBITMAP aMemoryBitmap = (HBITMAP) GetCurrentObject (hPrnDC, OBJ_BITMAP);
+    if (aMemoryBitmap)
+      if (GetObject (aMemoryBitmap, sizeof (BITMAP), &aBitmapInfo))
+      {
+        devWidth  = aBitmapInfo.bmWidth;
+        devHeight = aBitmapInfo.bmHeight;
+      }
+  }
 
-  hPrnDC = (HDC) hPrintDC;
-  printer = hPrnDC;
+  Standard_Integer tempWidth  = (Standard_Integer) devWidth;
+  Standard_Integer tempHeight = (Standard_Integer) devHeight;
 
-  /* Begin main routine **************************************************************/
-  TsmGetWSAttri (aview->WsId, WSWindow, &data);
-  if (TxglWinset (call_thedisplay, (WINDOW) data.ldata) == TSuccess) 
+  // view dimensions
+  RECT rect;
+  GetClientRect((WINDOW) data.ldata, &rect);
+  int viewWidth  = rect.right-rect.left;
+  int viewHeight = rect.bottom-rect.top;
+  if (viewWidth == 0 || viewHeight == 0)
   {
-    static PIXELFORMATDESCRIPTOR pfd = {
-      sizeof(PIXELFORMATDESCRIPTOR),  // size of this pfd
-        1,        // version number
-        PFD_SUPPORT_OPENGL|
-        PFD_DRAW_TO_BITMAP,
-        PFD_TYPE_RGBA,
-        0, 0, 0, 0, 0, 0,   // color bits ignored
-        0,        // no alpha buffer
-        0,        // shift bit ignored
-        0,        // no accumulation buffer
-        0, 0, 0, 0,       // accum bits ignored
-        32,       // 32-bit z-buffer  
-        0,        // no stencil buffer
-        0,        // no auxiliary buffer
-        PFD_MAIN_PLANE,     // main layer
-        0,        // reserved
-        0, 0, 0       // layer masks ignored
-    };
-    HWND w;
-    HDC hDC;    
-    HDC hMemDC;
-    HGLRC hGLRC;
-    RECT rect;
-
-    BITMAPINFO* pBMI;
-    BITMAPINFOHEADER* bmHeader;
-
-    BYTE  biInfo[sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD)];
-    HGDIOBJ hBmOld;
-    HBITMAP hBm;
-    VOID* base;
-
-    int nIndex;
-    int bmiSize;
-
-    float viewRatio;
-    int devWidth;
-    int devHeight;
-    int viewWidth;
-    int viewHeight;
-    int width;
-    int height;
-    float tempWidth;
-    float tempHeight;
-    int offsetx = 0;
-    int offsety = 0;
-
-#ifdef mydebug
-    devWidth = 640;
-    tempWidth = (float) devWidth;
-    devHeight = 480;
-    tempHeight = (float) devHeight;
+    MessageBox (NULL, "Print failed: can't setup the view for printing.",
+                "The operation couldn't be completed.", MB_OK);
+    return Standard_False;
+  }
+
+  // calculate correct width/height ratio
+  Standard_Real viewRatio = (Standard_Real)viewWidth/viewHeight;
+  fitDimensionsRatio(tempWidth, tempHeight, viewRatio);
+
+  // width and height for printing area
+  int width  = (int) (tempWidth  * theScaleFactor);
+  int height = (int) (tempHeight * theScaleFactor);
+
+  // device independent bitmap for the whole view
+#ifdef HAVE_FREEIMAGE
+  FipHandle  aViewImage  = NULL;
+  BYTE*      aViewBuffer = NULL;
 #else
-    devWidth = GetDeviceCaps(hPrnDC, HORZRES);
-    tempWidth = (float) devWidth;
-    devHeight = GetDeviceCaps(hPrnDC, VERTRES);
-    tempHeight = (float) devHeight;
-#endif
-    GetClientRect((WINDOW) data.ldata, &rect);
-    viewWidth = rect.right-rect.left;
-    viewHeight = rect.bottom-rect.top;
-
-    viewRatio = (float) viewWidth/(float) viewHeight;
-
-    // Calculate correct width/height ratio
-    if (tempHeight < tempWidth/viewRatio)
-      tempWidth = tempHeight*viewRatio;
-    if (tempWidth < tempHeight*viewRatio)
-      tempHeight = tempWidth/viewRatio;
-
-    width = (int) tempWidth;
-    height = (int) tempHeight;
-
-    // Create virtual window    
-    w = CreateWindow(
-      "Button",              
-      "",      
-      WS_OVERLAPPEDWINDOW |   
-      WS_CLIPCHILDREN |
-      WS_CLIPSIBLINGS,
-      0, 0,             
-      width, height,   
-      NULL,                
-      NULL,         
-      NULL,        
-      NULL);  
-#ifdef mydebug
-    ShowWindow(w, SW_SHOW);
+  HDC     hMemDC          = CreateCompatibleDC (hPrnDC);
+  HBITMAP hViewBitmap     = NULL;
+  HGDIOBJ hViewBitmapOld  = NULL;
+  VOID*   aViewBuffer    = NULL;
 #endif
 
-    hDC = GetDC(w);
-    if (!hDC)
-    {
-      MessageBox(0,"hDC == NULL", "Fehler", MB_OK);
-      return;
-    }
+  // Frame buffer initialization
+  OpenGl_FrameBuffer* aFrameBuffer = NULL;
+  OpenGl_FrameBuffer* aPrevBuffer = (OpenGl_FrameBuffer*) aview->ptrFBO;
+  Standard_Integer aFrameWidth (0),  aFrameHeight (0),
+                   aPrevBufferX (0), aPrevBufferY (0);
 
-    // Initialize Bitmap Information
-
-    pBMI = (BITMAPINFO *) biInfo;
-    ZeroMemory(pBMI, sizeof(*pBMI));
-    bmiSize = sizeof(*pBMI);
-
-    pBMI = (BITMAPINFO *) calloc(1, bmiSize);
-    bmHeader = &pBMI->bmiHeader;
-
-    bmHeader->biSize = sizeof(*bmHeader);
-    bmHeader->biWidth = width;
-    bmHeader->biHeight = height;
-    bmHeader->biPlanes = 1;                     /* must be 1 */
-    bmHeader->biBitCount = 24;
-    bmHeader->biXPelsPerMeter = 0;
-    bmHeader->biYPelsPerMeter = 0;
-    bmHeader->biClrUsed = 0;                    /* all are used */
-    bmHeader->biClrImportant = 0;               /* all are important */
-    bmHeader->biCompression = BI_RGB;
-    bmHeader->biSizeImage = 0;
-
-    // Create Device Independent Bitmap 
-    hMemDC = CreateCompatibleDC(hPrnDC);
-    hBm = CreateDIBSection(hMemDC, pBMI, DIB_RGB_COLORS, &base, NULL, 0); 
-    hBmOld = SelectObject(hMemDC, hBm);
-
-    // Release Memory   
-    free(pBMI);
-    //    free(bmHeader);
-
-    // further initialization
-#ifdef mydebug
-    pfd.cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
-    nIndex = ChoosePixelFormat(hDC, &pfd);
-    if (nIndex == 0)
+  // try to use existing frame buffer
+  if (aPrevBuffer)
+  {
+    GLsizei aPrevWidth  = aPrevBuffer->GetSizeX();
+    GLsizei aPrevHeight = aPrevBuffer->GetSizeY();
+    bool isUsable = false;
+
+    // check if its possible to use previous frame buffer
+    if (!IsTiling && aPrevWidth >= width && aPrevHeight >= height)
     {
-      MessageBox(0,"ChoosePixelFormat failed", "Error", MB_OK | MB_ICONSTOP);
-      goto Error;
+      aFrameWidth  = (Standard_Integer) width;
+      aFrameHeight = (Standard_Integer) height;
+      isUsable = true;
     }
-
-
-    if (!SetPixelFormat(hDC, nIndex, &pfd))
+    else if (IsTiling)
     {
-      MessageBox(0,"SetPixelFormat failed", "Error", MB_OK | MB_ICONSTOP);
-      goto Error;
+      getDimensionsTiling (aFrameWidth, aFrameHeight, width, height);
+      if (aPrevWidth >= aFrameWidth && aPrevHeight >= aFrameHeight)
+        isUsable = true;
     }
 
-    // Create Rendering Context
-    hGLRC = wglCreateContext(hDC);
-
-    if (hGLRC == NULL) 
+    // if it is enough memory for image paste dc operation
+    if (isUsable)
     {
-      MessageBox(0,"No Rendering Context", "Error", MB_OK | MB_ICONSTOP);
-      goto Error;
-    }
-    wglMakeCurrent(hDC,hGLRC);
+#ifdef HAVE_FREEIMAGE
+      // try to allocate fipImage and necessary resources
+      fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
+                                           aFrameHeight, 24);
+
+      // if allocated succesfully
+      if (anImagePtr->isValid())
+      {
+        aViewImage  = anImagePtr;
+        aViewBuffer = aViewImage->accessPixels ();
+      }
+      else
+        delete anImagePtr;
+
+      if (!aViewBuffer)
+      {
+        isUsable = false;
+        aViewBuffer = NULL;
+        aViewImage  = NULL;
+      }
 #else
-    pfd.cColorBits = GetDeviceCaps(hMemDC, BITSPIXEL);
-    nIndex = ChoosePixelFormat(hMemDC, &pfd);
-    if (nIndex == 0)
-    {
-      MessageBox(0,"ChoosePixelFormat failed", "Error", MB_OK | MB_ICONSTOP);
-      goto Error;
+      // try to allocate compatible bitmap and necessary resources
+      initBitmapBuffer (hMemDC, hViewBitmap, 
+                        aFrameWidth, aFrameHeight, aViewBuffer);
+      if (!aViewBuffer)
+      {
+        isUsable = false;
+        if (hViewBitmap)
+          DeleteObject (hViewBitmap);
+        hViewBitmap = NULL;
+      }
+      else
+        hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
+#endif
     }
 
-
-    if (!SetPixelFormat(hMemDC, nIndex, &pfd))
+    // use previous frame buffer
+    if (isUsable)
     {
-      MessageBox(0,"SetPixelFormat failed", "Error", MB_OK | MB_ICONSTOP);
-      goto Error;
+      aPrevBufferX = aPrevWidth;
+      aPrevBufferY = aPrevHeight;
+      aFrameBuffer = aPrevBuffer;
+      aFrameBuffer->ChangeViewport (aFrameWidth, aFrameHeight);
     }
+  }
 
-    // Create Rendering Context
-    hGLRC = wglCreateContext(hMemDC);
+  // if previous buffer cannot be used, try to init a new one
+  if (!aFrameBuffer)
+  {
+    aFrameBuffer = new OpenGl_FrameBuffer();
 
-    if (hGLRC == NULL) 
+    // try to create the framebuffer with the best possible size
+    Standard_Integer aMaxWidth(0), aMaxHeight(0);
+    getMaxFrameSize (aMaxWidth, aMaxHeight);
+    while (aMaxWidth > 1 && aMaxHeight > 1)
     {
-      MessageBox(0,"No Rendering Context", "Error", MB_OK | MB_ICONSTOP);
-      goto Error;
-    }
-    wglMakeCurrent(hMemDC,hGLRC);
+      aFrameWidth  = aMaxWidth;
+      aFrameHeight = aMaxHeight;
+
+      // calculate dimensions for different printing algorithms
+      if (!IsTiling)
+        initBufferStretch (aFrameWidth, aFrameHeight, width, height);
+      else
+        initBufferTiling (aFrameWidth, aFrameHeight, width, height);
+
+      // try to initialize framebuffer
+      if (aFrameBuffer->Init (aFrameWidth, aFrameHeight))
+      {
+#ifdef HAVE_FREEIMAGE
+        // try to allocate fipImage and necessary resources
+        fipImage* anImagePtr = new fipImage (FIT_BITMAP, aFrameWidth,
+                                            aFrameHeight, 24);
+
+        // if allocated succesfully
+        if (anImagePtr->isValid())
+        {
+          aViewImage  = anImagePtr;
+          aViewBuffer = aViewImage->accessPixels ();
+        }
+        else
+          delete anImagePtr;
+
+        if (!aViewBuffer)
+        {
+          aFrameBuffer->Release ();
+          aViewBuffer = NULL;
+          aViewImage  = NULL;
+        }
+        else
+          break;
+#else
+        // try to allocate compatible bitmap and necessary resources
+        initBitmapBuffer (hMemDC, hViewBitmap, 
+                          aFrameWidth, aFrameHeight, aViewBuffer);
+        if (!aViewBuffer)
+        {
+          if (hViewBitmap)
+            DeleteObject (hViewBitmap);
+          aFrameBuffer->Release ();
+          hViewBitmap = NULL;
+        }
+        else
+        {
+          hViewBitmapOld = SelectObject (hMemDC, hViewBitmap);
+          break;
+        }
 #endif
+      }
 
-    /* creating default font */
-    printerFontBase = 
-      createFont( "", -MulDiv( defaultPntSize, GetDeviceCaps( hPrnDC, LOGPIXELSY ), defaultDelimeter ),
-      (int)FW_NORMAL, 0 );
-
-    // redraw to new Rendering Context
-    call_func_redraw_all_structs_begin (aview->WsId);
-
-    call_togl_setplane( aview ); /* update clipping planes */
-
-    if (background == 0)
-    {
-      glClearColor(1.0, 1.0, 1.0, 1.0);
-      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+      // not initialized, decrease dimensions
+      aMaxWidth  = aMaxWidth  >> 1;
+      aMaxHeight = aMaxHeight >> 1;
     }
 
-    if (anunderlayer->ptrLayer)
-      call_togl_redraw_layer2d (aview, anunderlayer);
-    call_func_redraw_all_structs_proc (aview->WsId);
-
-    if (anoverlayer->ptrLayer)
-      call_togl_redraw_layer2d (aview, anoverlayer);
-#ifdef RIC120302
-    call_subr_displayCB(aview,OCC_REDRAW_BITMAP);
+    // check if there are proper dimensions 
+    if (aMaxWidth <= 1 || aMaxHeight <= 1)
+    {
+      MessageBox (NULL, "Print failed: can't allocate buffer for printing.",
+                  "The operation couldn't be completed.", MB_OK);
+
+      if (aFrameBuffer)
+        delete aFrameBuffer;
+#ifndef HAVE_FREEIMAGE
+      if (hMemDC)
+        DeleteDC (hMemDC);
 #endif
 
-    call_func_redraw_all_structs_end (aview->WsId, swap);
+      return Standard_False;
+    }
+  }
 
-    call_togl_redraw_immediat_mode (aview);
-#ifndef mydebug
-    /* Start printing of DIB ********************************************************/
+  // setup printing context and viewport
+  GLint aViewPortBack[4]; 
+  GLint aReadBufferPrev = GL_BACK;
+  GLint anAlignBack     = 1;
+  OpenGl_PrinterContext aPrinterContext (GET_GL_CONTEXT());
+  aPrinterContext.SetLayerViewport ((GLsizei)aFrameWidth,
+                                    (GLsizei)aFrameHeight);
+  glGetIntegerv (GL_VIEWPORT, aViewPortBack);
+  glGetIntegerv (GL_PACK_ALIGNMENT, &anAlignBack);
+  glPixelStorei (GL_PACK_ALIGNMENT, 4);
+
+  // start document if the printer context is not actually a memory dc
+  // (memory dc could be used for testing purposes)
+  if (GetObjectType (hPrnDC) == OBJ_DC)
+  {
+    // Initalize printing procedure
     di.cbSize = sizeof(DOCINFO);
-    di.lpszDocName = "Text";
+    di.lpszDocName = "Open Cascade Document - print v3d view";
     di.lpszOutput = filename;
 
-    if (StartDoc(hPrnDC, &di) == SP_ERROR) goto Error;
-    if (StartPage(hPrnDC) <= 0) goto Error;
+    // if can't print the document
+    if (StartDoc (hPrnDC, &di) <= 0 || StartPage (hPrnDC) <= 0)
+    {
+      MessageBox (NULL, "Print failed: printer can't start operation.",
+                  "The operation couldn't be completed.", MB_OK);
+#ifndef HAVE_FREEIMAGE
+      if (hViewBitmap)
+      {
+        SelectObject (hMemDC, hViewBitmapOld);
+        DeleteObject (hViewBitmap);
+      }
+      DeleteDC (hMemDC);
+#endif
 
-    // calculate offset for centered printing
-    if (width < devWidth)
-      offsetx = (devWidth - width)/2;
-    if (height < devHeight)
-      offsety = (devHeight - height)/2;
+      return Standard_False;
+    }
+  }
 
-    BitBlt(hPrnDC, offsetx, offsety, width, height, hMemDC, 0, 0, SRCCOPY);
+  // activate the offscreen buffer
+  aFrameBuffer->BindBuffer ();
 
-    EndPage(hPrnDC);
-    EndDoc(hPrnDC);
-    /* releasing created font */
-    deleteFont( printerFontBase );
-    printerFontBase = 0;
+  // calculate offset for centered printing
+  int aDevOffx = (int)(devWidth  - width) /2;
+  int aDevOffy = (int)(devHeight - height)/2;
 
-    /* End of printing section ******************************************************/
+  // operation complete flag
+  bool isDone = true;
+  
+  if (!IsTiling)
+  {
+    aPrinterContext.SetScale ((GLfloat)aFrameWidth /viewWidth,
+                              (GLfloat)aFrameHeight/viewHeight);
+    aFrameBuffer->SetupViewport ();
+    redrawView (aview, anunderlayer, anoverlayer, background);
+    glReadPixels (0, 0, aFrameWidth, aFrameHeight,
+                  GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
+
+    // copy result to the printer device and check for errors
+#ifdef HAVE_FREEIMAGE
+    if (!aViewImage->rescale(width, height, FILTER_BICUBIC) ||
+        !imagePasteDC (hPrnDC, aViewImage, aDevOffx, aDevOffy, width, height))
+      isDone = imageStretchDC (hPrnDC, aViewImage, aDevOffx, aDevOffy,
+                               width, height);
 #else
-    Sleep(5000);
-#endif
-
-Error:
-    /* Clean memory *****************************************************************/
-    if(hBm != NULL)
+    if (width > aFrameWidth && height > aFrameHeight)
     {
-      SelectObject(hMemDC, hBmOld);
-      DeleteObject(hBm);
-      DeleteObject(hBmOld);
+      SetStretchBltMode (hPrnDC, STRETCH_HALFTONE);
+      isDone = StretchBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
+                           hMemDC, 0, 0, aFrameWidth, aFrameHeight, SRCCOPY);
     }
-    wglMakeCurrent(NULL, NULL);
-    if (hGLRC != NULL)
+    else
     {
-      wglDeleteContext(hGLRC);
+      isDone = BitBlt (hPrnDC, aDevOffx, aDevOffy, width, height,
+                       hMemDC, 0, 0, SRCCOPY);
     }
-    if (hMemDC != NULL)
+#endif
+  }
+  else
+  {
+    // calculate total count of frames and cropping size
+    Standard_Integer aPxCropx = 0;
+    Standard_Integer aPxCropy = 0;
+    Standard_Integer aTotalx = 
+                     (Standard_Integer)floor ((float)width /aFrameWidth);
+    Standard_Integer aTotaly = 
+                     (Standard_Integer)floor ((float)height/aFrameHeight);
+    if (width %aFrameWidth != 0)
     {
-      DeleteDC(hMemDC);
+      aPxCropx = (aFrameWidth - width%aFrameWidth)/2;
+      aTotalx++;
     }
-
-    if (hDC != NULL)
+    if (height%aFrameHeight != 0)
     {
-      ReleaseDC(w, hDC);
+      aPxCropy = (aFrameHeight - height%aFrameHeight)/2;
+      aTotaly++;
     }
-    if (w != NULL)
+
+    int anOddPixelx = (width %aFrameWidth) %2;
+    int anOddPixely = (height%aFrameHeight)%2;
+
+    // calculate scale factor for full frames
+    Standard_Real aScalex = (Standard_Real)width /aFrameWidth;
+    Standard_Real aScaley = (Standard_Real)height/aFrameHeight;
+
+    // calculate and set the text scaling factor for printing context
+    GLfloat aScaleRatex = (GLfloat)aFrameWidth /viewWidth;
+    GLfloat aScaleRatey = (GLfloat)aFrameHeight/viewHeight;
+    aPrinterContext.SetScale (aScaleRatex*(GLfloat)aScalex,
+                              aScaleRatey*(GLfloat)aScaley);
+
+    // initialize projection matrix for printer context
+    TColStd_Array2OfReal aProj (0, 3, 0, 3);
+    Standard_Real aDef = 0;
+    aProj.Init (aDef);
+    aProj(2,2) = 1.0;
+    aProj(3,3) = 1.0;
+
+    // projection matrix offsets for printer context
+    // offsets are even numbers
+    Standard_Real aOffsetx(0), aOffsety(0);
+    aOffsetx = -(aTotalx-1);
+    aOffsety = -(aTotaly-1);
+
+    // rect of frame image that will be copied
+    // and coordinates in view image where to put it
+    Standard_Integer aLeft = 0, aRight = 0, aBottom = 0, aTop = 0;
+    Standard_Integer aSubLeft = (Standard_Integer)aDevOffx;
+    Standard_Integer aSubTop  = (Standard_Integer)aDevOffy;
+
+    // draw sequence of full frames
+    for (int i = 0; i < aTotalx; i++)
     {
-      DestroyWindow(w);
+      // offsets are even numbers
+      aOffsety = -(aTotaly-1);
+      aSubTop  =  (Standard_Integer)aDevOffy;
+
+      // calculate cropped frame rect
+      aLeft  = (i == 0) ? aPxCropx : 0;
+      aRight = (i == aTotalx-1) ? aFrameWidth-(aPxCropx+anOddPixelx) :
+                                  aFrameWidth;
+
+      for (int j = 0; j < aTotaly; j++)
+      {
+        // no offset for single frames
+        aProj(3,0) = (aTotalx == 1) ? 0 : -aOffsetx;
+        aProj(3,1) = (aTotaly == 1) ? 0 :  aOffsety;
+
+        // set projection matrix
+        aProj(0,0) = aScalex;
+        aProj(1,1) = aScaley;
+        aPrinterContext.SetProjTransformation (aProj);
+
+        // calculate cropped frame rect
+        aTop    = (j == 0)         ? aPxCropy : 0;
+        aBottom = (j == aTotaly-1) ? aFrameHeight-(aPxCropy+anOddPixely) :
+                                     aFrameHeight;
+
+        // draw to the offscreen buffer and capture the result
+        aFrameBuffer->SetupViewport ();
+        redrawView (aview, anunderlayer, anoverlayer, background);
+        glReadPixels (0, 0, aFrameWidth, aFrameHeight,
+                      GL_BGR_EXT, GL_UNSIGNED_BYTE, (GLvoid* )aViewBuffer);
+#ifdef HAVE_FREEIMAGE
+        // cut out pixels that are out of printing area
+        isDone = imagePasteDC (hPrnDC, aViewImage, aSubLeft, aSubTop,
+                               aRight-aLeft, aBottom-aTop, aLeft, aTop);
+#else
+        isDone = BitBlt (hPrnDC, aSubLeft, aSubTop, aRight-aLeft, aBottom-aTop,
+                         hMemDC, aLeft, aTop, SRCCOPY);
+#endif
+
+        // stop operation if errors
+        if (!isDone)
+          break;
+
+        // calculate new view offset for y-coordinate
+        aOffsety += 2.0;
+        aSubTop  += aBottom-aTop;
+      }
+
+      // stop operation if errors
+      if (!isDone)
+        break;
+      // calculate new view offset for x-coordinate
+      aOffsetx += 2.0;
+      aSubLeft += aRight-aLeft;
     }
+  }
 
-    /* End of clean memory *****************************************************************/
+  // complete printing or indicate an error
+  if (GetObjectType (hPrnDC) == OBJ_DC && isDone == true)
+  {
+    EndPage (hPrnDC);
+    EndDoc (hPrnDC);
   }
+  else if (isDone == false)
+  {
+    MessageBox (NULL, "Print failed: insufficient memory or spool error.\nPlease use smaller printer resolution.",
+                "The opeartion couldn't be completed.", MB_OK);
+    if (GetObjectType (hPrnDC) == OBJ_DC)
+      AbortDoc (hPrnDC);
+  }
+  
+  // return OpenGl to the previous state
+  aPrinterContext.Deactivate ();
+  glPixelStorei (GL_PACK_ALIGNMENT, anAlignBack);
+  aFrameBuffer->UnbindBuffer();
+  glViewport (aViewPortBack[0], aViewPortBack[1], 
+              aViewPortBack[2], aViewPortBack[3]);
+  if (aPrevBuffer)
+    aPrevBuffer->ChangeViewport (aPrevBufferX, aPrevBufferY);
+  else
+    delete aFrameBuffer;
+
+  // delete resources
+#ifndef HAVE_FREEIMAGE
+  if (hViewBitmap)
+  {
+    SelectObject (hMemDC, hViewBitmapOld);
+    DeleteObject (hViewBitmap);
+  }
+  DeleteDC (hMemDC);
+#endif
+
+  return (Standard_Boolean) isDone;
 
-  /* End main routine ********************************************************************/
-  return;
-#endif /*WNT*/
+#else // not WNT
+  return Standard_False;
+#endif 
 }
+
index 0360916..cfd1e39 100755 (executable)
@@ -87,6 +87,7 @@ if any was defined
 #include <OpenGl_txgl.hxx>
 #include <OpenGl_Memory.hxx>
 #include <Standard_TypeDef.hxx>
+#include <OpenGl_PrinterContext.hxx>
 
 /*----------------------------------------------------------------------*/
 /*
@@ -842,7 +843,22 @@ TelSetViewIndex( Tint  Wsid /* Workstation id */,
   printf("OpenGl_view.c::TelSetViewIndex::glMatrixMode(GL_PROJECTION) \n"); 
 #endif
   glMatrixMode(GL_PROJECTION);
-  glLoadMatrixf((GLfloat *) vptr->vrep.mapping_matrix );
+  glLoadIdentity();
+
+#ifdef WNT
+  // add printing scale/tiling transformation
+  OpenGl_PrinterContext* aPrinterContext = 
+    OpenGl_PrinterContext::GetPrinterContext(GET_GL_CONTEXT());
+
+  if (aPrinterContext)
+  {
+    GLfloat aProjMatrix[16];
+    aPrinterContext->GetProjTransformation(aProjMatrix);
+    glLoadMatrixf((GLfloat*) aProjMatrix);
+  }
+#endif
+
+  glMultMatrixf((GLfloat *) vptr->vrep.mapping_matrix );
 
 #ifdef TRACE_MAT
   printf( "\nTelSetViewIndex WS : %d, view : %d", Wsid, Vid );
index d2c8219..5e4a608 100755 (executable)
@@ -144,7 +144,8 @@ uses
         GradientFillMethod                from Aspect,
         FontAspect                        from OSD,
         AsciiString                       from TCollection,
-        ExtendedString                    from TCollection
+        ExtendedString                    from TCollection,
+        PrintAlgo                         from Aspect
 
 raises
 
@@ -1606,9 +1607,10 @@ is
 
       Print (me; hPrnDC: Handle from Aspect = NULL;
              showDialog: Boolean = Standard_True;
-             showBackground: Boolean = Standard_True;
-             filename: CString = NULL)
-      is static;
+             showBackground : Boolean = Standard_True;
+             filename: CString = NULL;
+             printAlgorithm : PrintAlgo from Aspect = Aspect_PA_STRETCH)
+      returns Boolean from Standard is static;
 
         ---Level: Public
         ---Purpose: print the contents of the view to printer with preview.
@@ -1625,6 +1627,15 @@ is
     -- (background is white)
         -- else set to TRUE for printing with current background color.
     -- <filename>: If != NULL, then the view will be printed to a file.
+    -- <printAlgorithm>: If you want to select the print algorithm, then you can
+        -- specify one of existing algorithms: Aspect_PA_STRETCH, Aspect_PA_TILE.
+    -- Returns Standard_True if the data is passed to the printer, otherwise
+    -- Standard_False if the print operation failed. This might be related to
+    -- insufficient memory or some internal errors. All this errors are
+    -- indicated by the message boxes (on level of OpenGl_GraphicDriver).
+    --  Warning: This function can reuse FBO assigned to the 
+    --  view on level of OpenGl_GraphicDriver; Please take it into account if
+    --  you use it for your purposes;
     --  Warning: Works only under Windows.
 
         ToPixMap ( me : mutable;
index 9bb3164..6b6975a 100755 (executable)
@@ -53,18 +53,20 @@ Device::~Device()
 /* Print Method                                                        */
 /************************************************************************/
 
-void V3d_View::Print (const Aspect_Handle       hPrnDC,
-                      const Standard_Boolean    showDialog,
-                      const Standard_Boolean    showBackground,
-                      const Standard_CString    filename) const 
+Standard_Boolean V3d_View::Print (const Aspect_Handle    hPrnDC,
+                                  const Standard_Boolean showDialog,
+                                  const Standard_Boolean showBackground,
+                                  const Standard_CString filename,
+                                  const Aspect_PrintAlgo printAlgorithm) const
 {
 #ifdef WNT
        if( MyView->IsDefined() ) 
        {
                if (hPrnDC != NULL)
                {
-                       MyView->Print(hPrnDC, showBackground, filename) ;
-                       return;
+                       return MyView->Print(hPrnDC, showBackground,
+                                            filename, printAlgorithm) ;
+                       
                }
 
                if (device._pd.hDC == NULL || showDialog )
@@ -85,7 +87,7 @@ void V3d_View::Print (const Aspect_Handle       hPrnDC,
                
                        if (!ispd)
                        {
-                               return;
+                               return Standard_False;
                        }
                        
                        if (!(device._pd.hDC)) 
@@ -101,12 +103,21 @@ void V3d_View::Print (const Aspect_Handle       hPrnDC,
                                        device._pd.hDevMode = NULL;
                                }
                                MessageBox(0, "Couldn't create Printer Device Context", "Error", MB_OK | MB_ICONSTOP);
-                               return;
+                               return Standard_False;
                        }
                }
-               MyView->Print(device._pd.hDC, showBackground, filename) ;
+
+    // process scale factor accordingly to the new printing approach
+    DEVMODE* aMode = (LPDEVMODE)GlobalLock(device._pd.hDevMode);
+
+    // convert percents to multiplication factor, 100% = 1.0
+    Standard_Real aScaleFactor = (Standard_Real) aMode->dmScale / 100.0;
+    GlobalUnlock (device._pd.hDevMode);
+   return MyView->Print(device._pd.hDC, showBackground,
+                        filename, printAlgorithm, aScaleFactor) ;
        }
 #else
        Standard_NotImplemented::Raise ("V3d_View::Print is implemented only on Windows");
 #endif
+  return Standard_False;
 }
index a5034d7..b3bc92d 100755 (executable)
@@ -24,6 +24,8 @@
 #include <Draw_Interpretor.hxx>
 #include <Draw.hxx>
 #include <Draw_Appli.hxx>
+#include <Aspect_PrintAlgo.hxx>
+#include <Image_PixMap.hxx>
 
 #ifndef WNT
 #include <Graphic3d_GraphicDevice.hxx>
@@ -1760,6 +1762,141 @@ static int VGraduatedTrihedron(Draw_Interpretor& di, Standard_Integer argc, cons
   return 0;
 }
 
+//==============================================================================
+//function : VPrintView
+//purpose  : Test printing algorithm, print the view to image file with given
+//           width and height. Printing implemented only for WNT.
+//==============================================================================
+static int VPrintView (Draw_Interpretor& di, Standard_Integer argc, 
+                       const char** argv)
+{
+#ifndef WNT
+  di << "Printing implemented only for wnt!\n";
+  return 1;
+#else
+
+  Handle(AIS_InteractiveContext) aContextAIS = NULL;
+  Handle(V3d_View) aView = NULL;
+  aContextAIS = ViewerTest::GetAISContext();
+  if (!aContextAIS.IsNull())
+  {
+    const Handle(V3d_Viewer)& Vwr = aContextAIS->CurrentViewer();
+    Vwr->InitActiveViews();
+    if(Vwr->MoreActiveViews())
+      aView = Vwr->ActiveView();
+  }
+
+  // check for errors
+  if (aView.IsNull())
+  {
+    di << "Call vinit before!\n";
+    return 1;
+  }
+  else if (argc < 4)
+  {
+    di << "Use: " << argv[0];
+    di << " width height filename [print algo=0]\n";
+    di << "width, height of the intermediate buffer for operation\n";
+    di << "algo : {0|1}\n";
+    di << "        0 - stretch algorithm\n";
+    di << "        1 - tile algorithm\n";
+    di << "test printing algorithms into an intermediate buffer\n";
+    di << "with saving output to an image file\n";
+    return 1;
+  }
+
+  // get the input params
+  Standard_Integer aWidth  = atoi (argv[1]);
+  Standard_Integer aHeight = atoi (argv[2]);
+  Standard_Integer aMode   = 0;
+  TCollection_AsciiString aFileName = TCollection_AsciiString (argv[3]);
+  if (argc==5)
+    aMode = atoi (argv[4]);
+
+  // check the input parameters
+  if (aWidth <= 0 || aHeight <= 0)
+  {
+    di << "Width and height must be positive values!\n";
+    return 1;
+  }
+  if (aMode != 0 && aMode != 1)
+    aMode = 0;
+
+  Image_CRawBufferData aRawBuffer;
+  HDC anDC = CreateCompatibleDC(0);
+
+  // define compatible bitmap
+  BITMAPINFO aBitmapData;
+  memset (&aBitmapData, 0, sizeof (BITMAPINFOHEADER));
+  aBitmapData.bmiHeader.biSize          = sizeof (BITMAPINFOHEADER);
+  aBitmapData.bmiHeader.biWidth         = aWidth ;
+  aBitmapData.bmiHeader.biHeight        = aHeight;
+  aBitmapData.bmiHeader.biPlanes        = 1;
+  aBitmapData.bmiHeader.biBitCount      = 24;
+  aBitmapData.bmiHeader.biXPelsPerMeter = 0;
+  aBitmapData.bmiHeader.biYPelsPerMeter = 0;
+  aBitmapData.bmiHeader.biClrUsed       = 0;
+  aBitmapData.bmiHeader.biClrImportant  = 0;
+  aBitmapData.bmiHeader.biCompression   = BI_RGB;
+  aBitmapData.bmiHeader.biSizeImage     = 0;
+
+  // Create Device Independent Bitmap
+  HBITMAP aMemoryBitmap = CreateDIBSection (anDC, &aBitmapData, DIB_RGB_COLORS,
+                                            &aRawBuffer.dataPtr, NULL, 0);
+  HGDIOBJ anOldBitmap   = SelectObject(anDC, aMemoryBitmap);
+
+  Standard_Boolean isSaved = Standard_False, isPrinted = Standard_False;
+  if (aRawBuffer.dataPtr != 0)
+  {    
+    if (aMode == 0)
+      isPrinted = aView->Print(anDC,1,1,0,Aspect_PA_STRETCH);
+    else
+      isPrinted = aView->Print(anDC,1,1,0,Aspect_PA_TILE);
+
+    // succesfully printed into an intermediate buffer
+    if (isPrinted)
+    {
+      Handle(Image_PixMap) anImageBitmap =
+                         new Image_PixMap ((Standard_PByte)aRawBuffer.dataPtr,
+                                           aWidth, aHeight,
+                                           aWidth*3 + aWidth%4, 24, 0);
+      isSaved = anImageBitmap->Dump(aFileName.ToCString());
+    }
+    else
+    {
+      di << "Print operation failed due to printing errors or\n";
+      di << "insufficient memory available\n";
+      di << "Please, try to use smaller dimensions for this test\n";
+      di << "command, as it allocates intermediate buffer for storing\n";
+      di << "the result\n";
+    }
+  }
+  else
+  {
+    di << "Can't allocate memory for intermediate buffer\n";
+    di << "Please use smaller dimensions\n";
+  }
+
+  if (aMemoryBitmap)
+  {
+    SelectObject (anDC, anOldBitmap);
+    DeleteObject (aMemoryBitmap);
+    DeleteDC(anDC);
+  }
+
+  if (!isSaved)
+  {
+    di << "Save to file operation failed. This operation may fail\n";
+    di << "if you don't have enough available memory, then you can\n";
+    di << "use smaller dimensions for the output file\n";
+    return 1;
+  }
+
+  return 0;
+
+#endif
+}
+
 //=======================================================================
 //function : ViewerCommands
 //purpose  :
@@ -1826,4 +1963,8 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
   theCommands.Add("vgraduatedtrihedron",
     "vgraduatedtrihedron : 1/0 (display/erase) [Xname Yname Zname [Font [isMultibyte]]]",
     __FILE__,VGraduatedTrihedron,group);
+  theCommands.Add("vprintview" ,
+    "vprintview : width height filename [algo=0] : Test print algorithm: algo = 0 - stretch, algo = 1 - tile",
+    __FILE__,VPrintView,group);
+
 }
index b234198..91ef918 100755 (executable)
@@ -74,6 +74,7 @@ uses
     RenderingContext        from Aspect,
     GraphicCallbackProc     from Aspect,
     ColorScale              from Aspect,
+    PrintAlgo               from Aspect,
 
     CRawBufferData          from Image,
 
@@ -1075,12 +1076,14 @@ is
        --          displayed in <me>.
        ---Category: Private methods
 
-         Print (me; AnUnderLayer       : Layer from Visual3d;
-                        AnOverLayer    : Layer from Visual3d;
-                        hPrnDC: Handle from Aspect;
-                        showBackground: Boolean;
-                        filename: CString)
-         is static;
+         Print (me; AnUnderLayer : Layer from Visual3d;
+                AnOverLayer      : Layer from Visual3d;
+                hPrnDC           : Handle from Aspect;
+                showBackground   : Boolean;
+                filename         : CString;
+                printAlgorithm   : PrintAlgo from Aspect = Aspect_PA_STRETCH;
+                 theScaleFactor   : Real from Standard = 1.0)
+         returns Boolean from Standard is static;
 
        ---Level: Internal
        ---Purpose: print the contents of all layers of the view to the printer.
@@ -1089,12 +1092,21 @@ is
        -- (background is white)
        -- else set to TRUE for printing with current background color.
        -- <filename>: If != NULL, then the view will be printed to a file.
+       -- <printAlgo>: Select print algorithm: stretch, tile.
+        -- <theScaleFactor>: Scaling coefficient, used internally to scale the
+        -- printings accordingly to the scale factor selected in the printer 
+        -- properties dialog.
+        -- Returns Standard_True if the data is passed to the printer, otherwise
+        -- Standard_False if the print operation failed due to printer error
+        -- or insufficient memory.
        --  Warning: Works only under Windows.
 
-         Print (me; hPrnDC: Handle from Aspect;
-                        showBackground: Boolean;
-                        filename: CString)
-         is static;
+         Print (me; hPrnDC     : Handle from Aspect;
+                showBackground : Boolean;
+                filename       : CString;
+                printAlgorithm : PrintAlgo from Aspect = Aspect_PA_STRETCH;
+                 theScaleFactor : Real from Standard = 1.0 )
+         returns Boolean from Standard is static;
 
        ---Level: Internal
        ---Purpose: print the contents of the view to printer.
@@ -1103,6 +1115,13 @@ is
        -- (background is white)
        -- else set to TRUE for printing with current background color.
        -- <filename>: If != NULL, then the view will be printed to a file.
+       -- <printAlgo>: Select print algorithm: stretch, tile.
+        -- <theScaleFactor>: Scaling coefficient, used internally to scale the
+        -- printings accordingly to the scale factor selected in the printer 
+        -- properties dialog.
+        -- Returns Standard_True if the data is passed to the printer, otherwise
+        -- Standard_False if the print operation failed due to printer error
+        -- or insufficient memory.
        --  Warning: Works only under Windows.
 
        SetTransparency ( me : mutable;
index 8b775df..796ea68 100755 (executable)
 /* Print Methods                                                        */
 /************************************************************************/
 
-void Visual3d_View::Print (const Aspect_Handle    hPrintDC, 
-                           const Standard_Boolean showBackground, 
-                           const Standard_CString filename) const
+Standard_Boolean Visual3d_View::Print
+  (const Aspect_Handle    hPrintDC, 
+   const Standard_Boolean showBackground,
+   const Standard_CString filename,
+   const Aspect_PrintAlgo printAlgorithm,
+   const Standard_Real    theScaleFactor) const
 {
-  Print (MyViewManager->UnderLayer (), 
-         MyViewManager->OverLayer (), 
-         hPrintDC, 
-         showBackground, 
-         filename);
+  return Print (MyViewManager->UnderLayer (),
+                MyViewManager->OverLayer (),
+                hPrintDC, showBackground,
+                filename, printAlgorithm, 
+                theScaleFactor);
 }
 
-void Visual3d_View::Print (const Handle(Visual3d_Layer)& AnUnderLayer, 
-                           const Handle(Visual3d_Layer)& AnOverLayer,
-                           const Aspect_Handle           hPrintDC,
-                           const Standard_Boolean        showBackground,
-                           const Standard_CString        aFilename) const
+Standard_Boolean Visual3d_View::Print
+  (const Handle(Visual3d_Layer)& AnUnderLayer,
+   const Handle(Visual3d_Layer)& AnOverLayer,
+   const Aspect_Handle           hPrintDC,
+   const Standard_Boolean        showBackground,
+   const Standard_CString        aFilename,
+   const Aspect_PrintAlgo        printAlgorithm,
+   const Standard_Real           theScaleFactor) const
 {
-  if (IsDeleted ()) return;
+  if (IsDeleted ()) return Standard_False;
 
-  if ((! IsDefined ()) || (! IsActive ())) return;
+  if ((! IsDefined ()) || (! IsActive ())) return Standard_False;
 
-  if (! MyWindow->IsMapped ()) return;
+  if (! MyWindow->IsMapped ()) return Standard_False;
 
   Aspect_CLayer2d OverCLayer;
   Aspect_CLayer2d UnderCLayer;
@@ -44,6 +50,7 @@ void Visual3d_View::Print (const Handle(Visual3d_Layer)& AnUnderLayer,
   if (! AnOverLayer.IsNull ()) OverCLayer = AnOverLayer->CLayer ();
   if (! AnUnderLayer.IsNull ()) UnderCLayer = AnUnderLayer->CLayer ();
 
-  MyGraphicDriver->Print (MyCView, UnderCLayer, OverCLayer,
-                          hPrintDC, showBackground, aFilename);
+  return MyGraphicDriver->Print (MyCView, UnderCLayer, OverCLayer,
+                                 hPrintDC, showBackground, aFilename,
+                                 printAlgorithm, theScaleFactor);
 }