PSPrintDC Class Reference

Provide a device context for printing to a PostScript printer. More...

#include <psdc.h>

Inheritance diagram for PSPrintDC:

KernelDC CCDummyDC CCDC ListItem CCObject SimpleCCObject List of all members.

Public Member Functions

 PSPrintDC (CNativeDC *pDC)
 Initialise a DC for printing PostScript.
 ~PSPrintDC ()
 Clean up the fonts in the DC.
virtual BOOL OutputNewLine ()
 Causes a new line to be started in the PostScript stream.
virtual BOOL OutputToken (TCHAR *)
 Outputs a string token to the EPS file.
virtual BOOL OutputDirect (BYTE *, INT32)
 Send bytes directly to the PostScript stream with no alteration or padding. Used for sending binary/hex data to stream. NB. The data output must NOT affect the rendering context set up by GDI in any way, as this function does not preserve that context (it cannot because it does not change the data passed in in any way).
virtual BOOL OutputCoord (DocCoord &, EPSAccuracy Accuracy=ACCURACY_NORMAL)
 Write out a coordinate x,y pair to the export file, automatically converting from spread coordinates to the user space coordinate system. User space is the coordinate system used for PostScript files. GDI sets up the CTM so that 1 user space unit = 1 device unit, so all we do is use the rendering matrix to convert to Windows co-ordinates and output this directly at 0dp accuracy (because a fractional user space value would equate to a fractional device pixel, which has no effect on output).
virtual BOOL OutputUserSpaceValue (MILLIPOINT, EPSAccuracy Accuracy=ACCURACY_NORMAL)
 Output a 'user space' value to the device context. User space is the coordinate system used for PostScript files. GDI sets up the CTM so that 1 user space unit = 1 device unit, so all we do is use the rendering matrix to convert to Windows co-ordinates and output this directly at 0dp accuracy (because a fractional user space value would equate to a fractional device pixel, which has no effect on output).
void SetDCTransforms (Matrix RenderMatrix, View *pView)
 Inform the DC how to transform user space values when performing output via OutputCoord. and OutputUserSpaceValue().
WinCoord TransformCoord (const DocCoord &)
 Transform a DocCoord to a WinCoord, using this DC's transformations, as set up by SetDCTransforms().
void AttachRenderRegion (PrintPSRenderRegion *pRegion)
void DetachRenderRegion ()
BOOL StartOSOutput ()
 Restore the PostScript DC to the context expected by the host OS (GDI), so we can use OS (GDI) functions. You must call EndOSOutput() before calling any Camelot rendering functions. There may be nested calls to this function.
BOOL EndOSOutput ()
 Inform the DC that we have finished doing GDI output, and so we should prepare the DC for Camelot PS commands (this is deferred until we actually do some output on the stream).
BOOL FlushDC ()
 Tidy up the PostScript DC and reinstate the GDI context if necessary. Should be called when printing is finished. (Won't cause problems if called more often - just more output).
BOOL FlushPSBuffer ()
 Flushes the buffer of pending PostScript data to the PostScript device.
BOOL SelectNewFont (WORD Typeface, BOOL Bold, BOOL Italic, MILLIPOINT Width, MILLIPOINT Height, ANGLE Rotation)
 Selects the specified font into the DC. Performs clever stuff to cache the font so that subsequent requests for the same font don't cause anything to happen.
BOOL SetClipping (BOOL NewState)
 Set the use of a clip region.
BOOL OutputPSClipping ()
 Set the use of a clip region.

Protected Member Functions

BOOL MakeRoomInBuffer (INT32)
 Make sure there is enough room in the PostScript buffer to add the specified number of bytes to the stream. If not, the buffer is flushed to the device.
void WritePSchar (char *pBuf, INT32 nBytes)
 Writes nBytes of TCHAR to the output stream. Uses Buffer.chardata as a scratch area. Max of MAX_PSBUF can be written at a time.
void WritePSTCHAR (TCHAR *pBuf, INT32 nBytes)
 Writes nBytes of TCHAR to the output stream. Uses Buffer.chardata as a scratch area. Max of MAX_PSBUF can be written at a time.

Protected Attributes

PassThruBuffer Buffer
Matrix RenderMatrix
MILLIPOINT PixelSize
ViewpView
INT32 SafeToUseGDI
BOOL StartOfPage
BOOL GDIContextIsCurrent
BOOL UsePSLevelClipping
PSDCFontInfo FontInfo
PrintPSRenderRegionpPSRegion

Detailed Description

Provide a device context for printing to a PostScript printer.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/03/94
See also:
KernelDC; PSPrintRenderRegion

Definition at line 162 of file psdc.h.


Constructor & Destructor Documentation

PSPrintDC::PSPrintDC CNativeDC pDC  ) 
 

Initialise a DC for printing PostScript.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/04/95
Parameters:
The device context of the PostScript printer. [INPUTS]

Definition at line 149 of file psdc.cpp.

00149                                    : KernelDC(pDC, RENDERTYPE_PRINTER_PS)
00150 {
00151     // Initialise the buffer to being empty.
00152     Buffer.nCount = 0;
00153     Buffer.Data[0] = 0;
00154 
00155     // No view yet
00156     pView = NULL;
00157 
00158     // We haven't set up the Camelot context yet, and no-one has asked to do any GDI
00159     // output yet.
00160     GDIContextIsCurrent = TRUE;
00161     SafeToUseGDI = 0;
00162 
00163     // Once per page
00164     StartOfPage = TRUE;
00165 
00166     // No fonts yet
00167     FontInfo.pRenderFont = NULL;
00168     FontInfo.pOldFont = NULL;
00169 
00170     // No render region yet.
00171     pPSRegion = NULL;
00172 
00173     // Suppress the output of a postscript clipping region
00174     UsePSLevelClipping = FALSE;
00175 
00176 }

PSPrintDC::~PSPrintDC  ) 
 

Clean up the fonts in the DC.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
05/30/95

Definition at line 189 of file psdc.cpp.

00190 {
00191     // Deselect the normal rendering font from the DC
00192     if (FontInfo.pRenderFont != NULL)
00193     {
00194         GetDC()->SetFont(*FontInfo.pOldFont);
00195         FontInfo.pOldFont = NULL;
00196         delete FontInfo.pRenderFont;
00197         FontInfo.pRenderFont = NULL;
00198     }
00199 }


Member Function Documentation

void PSPrintDC::AttachRenderRegion PrintPSRenderRegion pRegion  )  [inline]
 

Definition at line 181 of file psdc.h.

00182         {   pPSRegion = pRegion;   }

void PSPrintDC::DetachRenderRegion  )  [inline]
 

Definition at line 183 of file psdc.h.

00183 { pPSRegion = NULL; }

BOOL PSPrintDC::EndOSOutput  ) 
 

Inform the DC that we have finished doing GDI output, and so we should prepare the DC for Camelot PS commands (this is deferred until we actually do some output on the stream).

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
04/30/95
Returns:
TRUE if ok; FALSE if not (e.g. call has no corresponding call to StartOSOutput()).
See also:
PSPrintDC::StartOSOutput

Definition at line 831 of file psdc.cpp.

00832 {
00833     // Just decrement counter - we do the other stuff in OutputToken().
00834     SafeToUseGDI--;
00835     ERROR2IF(SafeToUseGDI < 0, FALSE, "Unbalanced call to Start/EndOSOutput() functions!");
00836 
00837     // All ok
00838     return TRUE;
00839 }

BOOL PSPrintDC::FlushDC  ) 
 

Tidy up the PostScript DC and reinstate the GDI context if necessary. Should be called when printing is finished. (Won't cause problems if called more often - just more output).

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
04/25/95
Returns:
TRUE if ok; FALSE if not (e.g. output problem)
See also:
PSPrintDC::FlushPSBuffer()

Definition at line 622 of file psdc.cpp.

00623 {
00624     // Restore OS context - just pretend we want to do some OS output
00625     //if (!StartOSOutput())
00626         // Error
00627     //  return FALSE;
00628 
00629     // Clear out the buffer.
00630     if (!FlushPSBuffer())
00631         // Error
00632         return FALSE;
00633 
00634     // Go back to using Camelot context
00635     // (NB this is deferred - it will only be reinstated if we do Camelot output)
00636     //return EndOSOutput();
00637     return TRUE;
00638 }

BOOL PSPrintDC::FlushPSBuffer  ) 
 

Flushes the buffer of pending PostScript data to the PostScript device.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
04/24/95
Returns:
TRUE if data flushed ok; FALSE if not (e.g. printer/driver error)
See also:
PSPrintDC::MakeRoomInBuffer

Definition at line 468 of file psdc.cpp.

00469 {
00470     if (Buffer.nCount <= 0)
00471         // Nothing to flush
00472         return TRUE;
00473 
00474     // Get system to flush any of its data first.
00475     // (don't have to do anything here)
00476 
00477     if (Buffer.nCount>MAX_PSBUF) // MAX_PSBUF itself is legal
00478     {
00479         Buffer.nCount=MAX_PSBUF;
00480         ERROR3("Postscript buffer overrun");
00481     }
00482 
00483     // Ensure the buffer is zero terminated
00484     WritePSTCHAR(Buffer.Data, Buffer.nCount);
00485     
00486     // Clear out buffer
00487     Buffer.nCount = 0;
00488     Buffer.Data[0] = 0;
00489 
00490     return TRUE;
00491 }

BOOL PSPrintDC::MakeRoomInBuffer INT32  nBytesRequired  )  [protected]
 

Make sure there is enough room in the PostScript buffer to add the specified number of bytes to the stream. If not, the buffer is flushed to the device.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
04/24/95
Parameters:
nBytesRequired - how many bytes of free space are needed in the buffer. [INPUTS]
Returns:
TRUE if enough space was found; FALSE if not.

Errors: Printer/driver error => ERROR1 Buffer cannot accomodate requested size even when empty => ERROR2

See also:
PSPrintDC::FlushPSBuffer

Definition at line 589 of file psdc.cpp.

00590 {
00591     if (nBytesRequired >= MAX_PSBUF)
00592     {
00593         // Can't ever do that many bytes!
00594         ERROR2(FALSE, "Too many bytes asked for in PSPrintDC::MakeRoomInBuffer()");
00595     }
00596 
00597     // Do we need to flush?
00598     if (nBytesRequired > (MAX_PSBUF - Buffer.nCount))
00599         // Yes
00600         return FlushPSBuffer();
00601 
00602     // All ok if we get here
00603     return TRUE;
00604 }

BOOL PSPrintDC::OutputCoord DocCoord Coord,
EPSAccuracy  Accuracy = ACCURACY_NORMAL
[virtual]
 

Write out a coordinate x,y pair to the export file, automatically converting from spread coordinates to the user space coordinate system. User space is the coordinate system used for PostScript files. GDI sets up the CTM so that 1 user space unit = 1 device unit, so all we do is use the rendering matrix to convert to Windows co-ordinates and output this directly at 0dp accuracy (because a fractional user space value would equate to a fractional device pixel, which has no effect on output).

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/03/94
Parameters:
Coord - the coordinate to write out to the file. [INPUTS] Accuracy - optional parameter - ignored for GDI PostScript output as GDI sets up a coordinate system where 1 user space unit = 1 device unit.
Returns:
TRUE if the data was written ok; FALSE if not => ERROR1
See also:
PSPrintDC::OutputUserSpaceValue
Returns:
Errors: File/disk error => ERROR1

Reimplemented from KernelDC.

Definition at line 705 of file psdc.cpp.

00706 {
00707     // We need a view to scale the coords.
00708     ERROR2IF(pView == NULL, FALSE, "No view attached to PostScript DC!");
00709 
00710     WinCoord PSCoord = TransformCoord(Coord);
00711 
00712     // Output to PostScript stream.
00713     BOOL Ok = (OutputValue(PSCoord.x) && OutputValue(PSCoord.y));
00714 
00715     return Ok;
00716 }

BOOL PSPrintDC::OutputDirect BYTE *  Buf,
INT32  nBytes
[virtual]
 

Send bytes directly to the PostScript stream with no alteration or padding. Used for sending binary/hex data to stream. NB. The data output must NOT affect the rendering context set up by GDI in any way, as this function does not preserve that context (it cannot because it does not change the data passed in in any way).

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/04/95
Parameters:
Buf - the bytes to send to the stream. [INPUTS] nBytes - the number of bytes to send to the stream.
Returns:
TRUE if all the bytes were sent ok; FALSE if not.
Do NOT use this to send commands that will render something, as the CTM will NOT be set up correctly for Camelot's co-ordinate system.

See also:
KernelDC::OutputNewLine; KernelDC::OutputToken

Reimplemented from KernelDC.

Definition at line 429 of file psdc.cpp.

00430 {
00431     // This could be anything, so we flush the buffer first, and then write directly
00432     // to stream.
00433     if (!FlushPSBuffer())
00434         // Error occured in buffer handling
00435         return FALSE;
00436 
00437     // Copy data to our buffer - do it in stages if necessary
00438     while (nBytes > 0)
00439     {
00440         // Work out how much we can send this time around.
00441         INT32 nBytesToSend = min(nBytes, MAX_PSBUF);
00442 
00443         WritePSchar((char *)Buf, nBytesToSend);
00444 
00445         // Update variables to reflect sending this number of bytes
00446         nBytes -= nBytesToSend;
00447         Buf += nBytesToSend;
00448     }
00449 
00450     // All ok
00451     return TRUE;
00452 }

BOOL PSPrintDC::OutputNewLine  )  [virtual]
 

Causes a new line to be started in the PostScript stream.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/04/95
Returns:
TRUE if the data was written ok; FALSE if not => ERROR1
See also:
PSPrintDC; PSPrintDC::OutputToken
Returns:
Errors: Disk/file/print error => ERROR1

Reimplemented from KernelDC.

Definition at line 217 of file psdc.cpp.

00218 {
00219     static TCHAR NewLine[] = _T("\n");
00220 
00221     // Make sure we have enough room in the buffer
00222     if (!MakeRoomInBuffer(camStrlen(NewLine)))
00223         // Error occured in buffer handling.
00224         return FALSE;
00225 
00226     // Add newline to buffer
00227     camStrcat(Buffer.Data, NewLine);
00228     Buffer.nCount += camStrlen(NewLine);
00229 
00230     // Update line width record.
00231     LineWidth = 0;
00232 
00233     // Success
00234     return TRUE;
00235 }

BOOL PSPrintDC::OutputPSClipping  ) 
 

Set the use of a clip region.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
09/09/96
Returns:
TRUE if a clip region has been exported

Definition at line 1109 of file psdc.cpp.

01110 {
01111     if (UsePSLevelClipping)
01112     {
01113         // DocRect theRect =  pPSRegion->CurrentClipRect;
01114 
01115         // BODGE - Currently need to deflate this clip region
01116         // by the bleed size. This only works because we know we are not
01117         // stripping but rendering complete pages. Hence this clip rectangle represents
01118         // the page with bleed applied in the document area. We need to output a clip
01119         // rectangle which will clip all objects beyond the bleed. This is quite a complex process.
01120 
01121         PrintView* pView = (PrintView*)(pPSRegion->GetRenderView());
01122         ERROR2IF(pView==NULL,FALSE,"No printview in this PS render region");
01123         ERROR3IF(!pView->IsKindOf(CC_RUNTIME_CLASS(PrintView)), "Not a PrintView in PSPrintDC output token");
01124 
01125         // Get the current patch clip rectangle
01126         DocRect theRect = pView->PatchInfo.GetClipRect(FALSE,FALSE);
01127 
01128         // read the regions render matrix.
01129         Matrix RMatrix = pPSRegion->GetMatrix();
01130         Matrix IMatrix = RMatrix.Inverse();
01131         RMatrix.transform(&theRect.lo);
01132         RMatrix.transform(&theRect.hi);
01133         PrintView::CorrectRotatedRectangle((Rect*)&theRect);
01134         pView->PatchInfo.InflateRectBy(&theRect,TRUE,FALSE);
01135         IMatrix.transform(&theRect.lo);
01136         IMatrix.transform(&theRect.hi);
01137         PrintView::CorrectRotatedRectangle((Rect*)&theRect);
01138 
01139         // And finally write the clip region out
01140         if (!pPSRegion->WriteClipRegion(this, theRect))
01141             return FALSE;
01142     }
01143     return TRUE;
01144 }

BOOL PSPrintDC::OutputToken TCHAR Str  )  [virtual]
 

Outputs a string token to the EPS file.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
23/04/95
Parameters:
Str - the character string to write to the file. [INPUTS]
Returns:
TRUE if the data was written ok; FALSE if not => ERROR1
See also:
PSPrintDC; KernelDC::OutputToken
Returns:
Errors: Disk/file error => ERROR1

Reimplemented from KernelDC.

Definition at line 252 of file psdc.cpp.

00253 {
00254 #ifndef STANDALONE
00255     // Should we re-instate the Camelot context?
00256     if (!SafeToUseGDI && GDIContextIsCurrent)
00257     {
00258         // Yes - just save the context (so we can restore GDI's context) and put our
00259         // dictionary on the dict stack.
00260         // Must do this first or else we get an infinite loop!
00261         GDIContextIsCurrent = FALSE;
00262 
00263         // Code by Mike
00264         // We need to work out where we are in order to render the correct bits of postscript header.
00265         BOOL AtStartOfPaper = FALSE;
00266         BOOL AtStartOfPatch = StartOfPage;
00267         StartOfPage=FALSE;
00268 
00269         // Work out whether this is the first call to output token for this page
00270         if (AtStartOfPatch)
00271         {
00272             PrintView* pView = (PrintView*)(pPSRegion->GetRenderView());
00273             ERROR2IF(pView==NULL,FALSE,"No printview in this PS render region");
00274             ERROR3IF(!pView->IsKindOf(CC_RUNTIME_CLASS(PrintView)), "Not a PrintView in PSPrintDC output token");
00275             AtStartOfPaper = ((pView->PatchInfo.PatchNumber)==1);
00276         }
00277         
00278         OutputNewLine();
00279 
00280         // ok now check our flag. This may be the first time we've
00281         // been called from this PSPrintDC construction. If so we
00282         // need to output page header stuff.
00283         if (AtStartOfPaper)
00284         {
00285             // We need to get the name of the output plate here
00286             // this might be a bit tricky! Na easy...
00287             if (!pPSRegion->WritePlateName(this))
00288                 return FALSE;
00289         }
00290 
00291         // save the graphics state
00292         OutputToken(_T("save"));
00293         OutputNewLine();
00294 
00295         // wxWidgets and Windows both use (0,0) to mean the top left hand origin of the
00296         // paper in logical coordinates. However, they do something rather different in
00297         // terms of physical coordinates. What windows printer drivers do (and thus what
00298         // Camelot expects) is use a postcript page transformation matrix to invert the
00299         // page, and for the postscript to be written in native DPI coordinates with the
00300         // origin at the TOP left of the page. What wxWidgets does is write its postscript
00301         // in the more natural way with the origin at the BOTTOM of the page, and handle
00302         // the coordinate inversion wihin wxWidgets.
00303         //
00304         // Note that this means while our internally generated PS expects a transformation
00305         // matrix that flips the Y coordinate (as the windows drivers produce). We
00306         // can't change the transformation matrix in the prologue because this would
00307         // affect wxWidgets output (and also it's technically difficult to do). We can't
00308         // change our own rendering matrix (so we produce the right coordinates) because
00309         // lots of things seem to explode with a matrix which flips the Y access (negative
00310         // scale factors etc.). We can't just change the coordinates we write because
00311         // other things (e.g. bitmaps) use the native render matrix. So what we do is
00312         // temporarily invert the PS transformation matrix during the period of our output.
00313         // This seems arcane but reasonably extensive research suggests it is the best
00314         // way forward. It's restored before we do any OS output.
00315 
00316         TCHAR flipbuf[256];
00317         INT32 translate = GetDC()->GetSize().GetHeight();
00318         camSprintf(flipbuf, _T("0 %d translate 1 -1 scale"), translate);
00319         OutputToken(flipbuf);
00320         OutputNewLine();
00321 
00322         // Now start plate writing etc.
00323 
00324         if (!pPSRegion->WritePhotoNegative(this))
00325             return FALSE;
00326 
00327         if (AtStartOfPaper)
00328         {
00329             // We need to fill the page with black if the plate says we
00330             // need to negate everything.
00331             if (!pPSRegion->WriteRenderPaper(this))
00332                 return FALSE;
00333         }
00334 
00335         // Write out our procset.
00336         if (!pPSRegion->WriteProlog(this))
00337             // Error 
00338             return FALSE;
00339 
00340         OutputNewLine();
00341         OutputToken(_T("XaraStudio1Dict begin"));
00342         OutputNewLine();
00343 
00344         // Now output the setscreen function for this plate
00345         if (!pPSRegion->WritePlateScreen(this))
00346             return FALSE;
00347 
00348         // try to write out the sep tables if we need them
00349         if (!pPSRegion->WriteSepTables(this))
00350             return FALSE;
00351 
00352         // export any clip region we might need.
00353         if (!OutputPSClipping())
00354             return FALSE;
00355     }   
00356 
00357     // Special tokens
00358 //  static TCHAR Space = _T(' ');
00359 //  static TCHAR NewLine[] = _T("\n");
00360 
00361     if (LineWidth > 70)
00362     {
00363         // Line is getting INT32 - wrap around
00364         OutputNewLine();
00365     }
00366 
00367     // Pad with a space (unless at the beginning of the line)
00368     if (LineWidth > 0)
00369     {
00370         // Make sure we have enough room in the buffer
00371         if (!MakeRoomInBuffer(1))
00372             // Error occured in buffer handling.
00373             return FALSE;
00374 
00375         // Add space to buffer
00376         camStrcat(Buffer.Data, _T(" "));
00377         Buffer.nCount++;
00378 
00379         // Update line width record.
00380         LineWidth++;
00381     }
00382 
00383     // Write the token out to the file
00384     INT32 Len = camStrlen(Str);
00385 
00386     // Make sure we have enough room in the buffer
00387     if (!MakeRoomInBuffer(Len))
00388         // Error occured in buffer handling.
00389         return FALSE;
00390 
00391     // Add space to buffer
00392     camStrcat(Buffer.Data, Str);
00393     Buffer.nCount += Len;
00394 
00395     // Update line width record.
00396     LineWidth += Len;
00397 
00398     // Success
00399     return TRUE;
00400 #else
00401     return FALSE;
00402 #endif
00403 }

BOOL PSPrintDC::OutputUserSpaceValue MILLIPOINT  n,
EPSAccuracy  Accuracy = ACCURACY_NORMAL
[virtual]
 

Output a 'user space' value to the device context. User space is the coordinate system used for PostScript files. GDI sets up the CTM so that 1 user space unit = 1 device unit, so all we do is use the rendering matrix to convert to Windows co-ordinates and output this directly at 0dp accuracy (because a fractional user space value would equate to a fractional device pixel, which has no effect on output).

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
28/04/95
Parameters:
n - the value (in millipoints) to output. [INPUTS] Accuracy - optional parameter - ignored for GDI PostScript output as GDI sets up a coordinate system where 1 user space unit = 1 device unit.
Returns:
TRUE if the data was written ok; FALSE if not => ERROR1
See also:
KernelDC::OutputCoord; KernelDC::OutputToken; KernelDC::SetFullAccuracy
Returns:
Errors: Disk/file error => ERROR1

Reimplemented from KernelDC.

Definition at line 668 of file psdc.cpp.

00669 {
00670     // We need a view to scale the value.
00671     ERROR2IF(pView == NULL, FALSE, "No view attached to PostScript DC!");
00672 
00673     // Use pixel size to scale to device units.
00674     n /= PixelSize;
00675 
00676     // Output as device units
00677     return OutputValue(n);
00678 }

BOOL PSPrintDC::SelectNewFont WORD  Typeface,
BOOL  Bold,
BOOL  Italic,
MILLIPOINT  Width,
MILLIPOINT  Height,
ANGLE  Rotation
 

Selects the specified font into the DC. Performs clever stuff to cache the font so that subsequent requests for the same font don't cause anything to happen.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
05/28/95
Parameters:
Details of the font to select. [INPUTS] NB. Width is not the actual width; it expresses the aspect ratio required. So, e.g. if Width == Height/2 then the aspect ratio is 50%, and so on.
Returns:
TRUE if the font was selected ok; FALSE if not.

Definition at line 860 of file psdc.cpp.

00862 {
00863 PORTNOTE("printing", "Removed postscript printing of text")
00864 #ifndef EXCLUDE_FROM_XARALX
00865 
00866     // Check to see if it is cached
00867     if ((FontInfo.pRenderFont != NULL) &&
00868         (FontInfo.Typeface == Typeface) &&
00869         (FontInfo.Bold == Bold) &&
00870         (FontInfo.Italic == Italic) &&
00871         (FontInfo.Width == Width) &&
00872         (FontInfo.Height == Height) &&
00873         (FontInfo.Rotation == Rotation))
00874     {
00875         // It is the same as the currently selected/cached font
00876         TRACEUSER( "Tim", _T("Using the cached font\n"));
00877         return TRUE;
00878     }
00879 
00880     TRACEUSER( "Tim", _T("Font cache invalid - generating font to use\n"));
00881 
00882     // Get ready for GDI operations
00883     if (!StartOSOutput())
00884         return FALSE;
00885 
00886     // Not the cached font - ok, deselect and delete the cached font.
00887     if (FontInfo.pOldFont != NULL)
00888     {
00889         GetDC->SetFont(*FontInfo.pOldFont);
00890         FontInfo.pOldFont = NULL;
00891     }
00892 
00893     if (FontInfo.pRenderFont != NULL)
00894     {
00895         delete FontInfo.pRenderFont;
00896         FontInfo.pRenderFont = NULL;
00897     }
00898 
00899     // Create the font and select it into the DC
00900     FontInfo.pRenderFont = new wxFont;
00901     if (!FontInfo.pRenderFont)
00902         return FALSE;
00903 
00904     // Work out the font weight - bold or normal?
00905     INT32 FontWeight = Bold ? FW_BOLD : FW_NORMAL;
00906 
00907     // Get the typeface name of the font
00908 
00909     ENUMLOGFONT *pEnumLogFont = FONTMANAGER->GetEnumLogFont(Typeface);
00910     if (pEnumLogFont == NULL)
00911         // Error
00912         return FALSE;
00913 
00914     // Work out how big the font is, in logical pixels
00915     FIXED16 fxPixWidth, fxPixHeight;
00916     pView->GetScaledPixelSize(&fxPixWidth, &fxPixHeight);
00917     INT32 FontWidth = (INT32) (Width / fxPixWidth.MakeDouble());
00918     INT32 FontHeight = (INT32) (Height / fxPixHeight.MakeDouble());
00919 
00920     if (FontHeight == FontWidth)
00921     {
00922         // Aspect ratio is 100% - use width of 0, and the GDI font engine gives us 100%
00923         // ratio automatically
00924         FontWidth = 0;
00925     }
00926     else
00927     {
00928         // Aspect ratio is not 100% - we need to do some clever stuff to work out
00929         // how wide we want the font to be.  Because fonts are generally much taller
00930         // than they are wide, we can't just pass in FontWidth directly - we must
00931         // transform it to the correct width.
00932 
00933         // BODGETEXT: ideally, we should use a NEWTEXTMETRIC structure here, to work out
00934         //            the correct width, but this involves calling EnumLogFontFamily() or
00935         //            whatever, which is too slow.  As the text code caches the LOGFONT
00936         //            for each font, it could also cache the NEWTEXTMETRIC structure,
00937         //            which this routine could then use.
00938         //            Having said all that, this code seems to work!
00939 
00940         // Create the font - the first time is to find out how wide the characters are,
00941         // so we can scale the width correctly. (So we give a width of 0 to get the normal
00942         // width for the given height)
00943         if (FontInfo.pRenderFont->CreateFont(-100, 0, 0, 0, FontWeight, Italic, 
00944                                              FALSE, FALSE, DEFAULT_CHARSET, 
00945                                              OUT_TT_PRECIS, CLIP_TT_ALWAYS,
00946                                              PROOF_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
00947                                              pEnumLogFont->elfLogFont.lfFaceName) == 0)
00948         {
00949             // Can't create font - do it as curves
00950             delete FontInfo.pRenderFont;
00951             FontInfo.pRenderFont = NULL;
00952             EndOSOutput();
00953             return FALSE;
00954         }
00955 
00956         if (FALSE)//TRUE)
00957         {
00958             FontInfo.pOldFont = SelectObject(FontInfo.pRenderFont);
00959 
00960             // Get the outlines to see how big the font should be...
00961             INT32 Widths[30];
00962 
00963             // First for lower case
00964             GetOutputCharWidth('a', 'z', Widths);
00965             INT32 AveCharWidth = 0;
00966             for (INT32 i = 0; i < 26; i++)
00967                 AveCharWidth += Widths[i];
00968 
00969             // Now for upper case
00970             GetOutputCharWidth('A', 'Z', Widths);
00971             for (i = 0; i < 26; i++)
00972                 AveCharWidth += Widths[i];
00973 
00974             // Ok, get average width
00975             AveCharWidth /= 52;
00976 
00977             // Scale the width by the font's aspect ratio: 
00978 
00979             // ActualWidth = (RealWidth / Height) * Width
00980             FontWidth = MulDiv(AveCharWidth, FontWidth, 100);
00981 
00982             // Select old font back into DC
00983             SelectObject(FontInfo.pOldFont);
00984         }
00985         else
00986         {
00987             // Get the metrics
00988             TEXTMETRIC Metrics;
00989 
00990             if (TRUE) //RFlags.Metafile)
00991             {
00992                 // Metafile - we need to use the screen DC to do this
00993                 CNativeDC *pDesktopDC = CWnd::GetDesktopWindow()->GetDC();
00994 
00995                 // Get the metrics
00996                 FontInfo.pOldFont = pDesktopDC->SelectObject(FontInfo.pRenderFont);
00997                 pDesktopDC->GetTextMetrics(&Metrics);
00998 
00999                 // Select old font back into screen DC
01000                 pDesktopDC->SelectObject(FontInfo.pOldFont);
01001                 CWnd::GetDesktopWindow()->ReleaseDC(pDesktopDC);
01002             }
01003             else
01004             {
01005                 FontInfo.pOldFont = SelectObject(FontInfo.pRenderFont);
01006 
01007                 GetTextMetrics(&Metrics);
01008 
01009                 // Select old font back into DC
01010                 SelectObject(FontInfo.pOldFont);
01011             }
01012 
01013             // Scale the width by the font's aspect ratio: 
01014 
01015             // ActualWidth = (RealWidth / Height) * Width
01016             FontWidth = MulDiv(Metrics.tmAveCharWidth, FontWidth, 100);
01017         }
01018 
01019         // Delete the font
01020         delete FontInfo.pRenderFont;
01021 
01022         // Create the 'proper' font and select it into the DC
01023         TRY
01024         {
01025             FontInfo.pRenderFont = new CFont;
01026         }
01027         CATCH (CMemoryException, e)
01028         {
01029             return FALSE;
01030         }
01031         END_CATCH
01032     }
01033 
01034     // Work out the rotation of the font, in tenths of degrees.
01035     INT32 lfRotation;
01036     if (Rotation == FIXED16(0))
01037         lfRotation = 0;
01038     else
01039         lfRotation = (INT32) ( (Rotation.MakeDouble() * 360.0 * 10.0) / (2 * PI) );
01040 
01041     // Create the font with the correct width and rotation
01042     if (FontInfo.pRenderFont->CreateFont(-FontHeight, FontWidth, lfRotation, 0, 
01043                                          FontWeight, Italic, 
01044                                          FALSE, FALSE, DEFAULT_CHARSET, 
01045                                          OUT_TT_PRECIS, CLIP_TT_ALWAYS,
01046                                          PROOF_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
01047                                          pEnumLogFont->elfLogFont.lfFaceName) == 0)
01048     {
01049         // Can't create font (device may not support rotation).
01050         delete FontInfo.pRenderFont;
01051         FontInfo.pRenderFont = NULL;
01052         EndOSOutput();
01053         return FALSE;
01054     }
01055 
01056     // Select the real font into the DC.
01057     FontInfo.pOldFont = SelectObject(FontInfo.pRenderFont);
01058 
01059     // Validate the cache
01060     FontInfo.Typeface = Typeface;
01061     FontInfo.Bold     = Bold;
01062     FontInfo.Italic   = Italic;
01063     FontInfo.Width    = Width;
01064     FontInfo.Height   = Height;
01065     FontInfo.Rotation = Rotation;
01066 
01067     // End of GDI operations
01068     if (!EndOSOutput())
01069         return FALSE;
01070 
01071     // Font created and selected ok
01072     return TRUE;
01073 #else
01074     return FALSE; // hopefully it will print as curves
01075 #endif
01076 }

BOOL PSPrintDC::SetClipping BOOL  newstate  ) 
 

Set the use of a clip region.

Author:
Mike_Kenny (Xara Group Ltd) <camelotdev@xara.com>
Date:
09/09/96
Returns:
The old state of the clipping flag

Definition at line 1090 of file psdc.cpp.

01091 {
01092     BOOL oldstate = UsePSLevelClipping;
01093     UsePSLevelClipping = newstate;
01094     return oldstate;
01095 }

void PSPrintDC::SetDCTransforms Matrix  NewRenderMatrix,
View pNewView
 

Inform the DC how to transform user space values when performing output via OutputCoord. and OutputUserSpaceValue().

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/04/95
Parameters:
The matrix and view to transform user space values with. [INPUTS]
See also:
PSPrintDC::OutputCoord; PSPrintDC::OutputUserSpaceValue

Definition at line 732 of file psdc.cpp.

00733 {
00734     // Remember these values
00735     RenderMatrix = NewRenderMatrix;
00736     pView = pNewView;
00737 
00738     // Get the pixel size from the view
00739     FIXED16 fxPixelWidth, fxPixelHeight;
00740     pView->GetScaledPixelSize(&fxPixelWidth, &fxPixelHeight);
00741     PixelSize = (MILLIPOINT) fxPixelWidth.MakeLong();
00742 }

BOOL PSPrintDC::StartOSOutput  ) 
 

Restore the PostScript DC to the context expected by the host OS (GDI), so we can use OS (GDI) functions. You must call EndOSOutput() before calling any Camelot rendering functions. There may be nested calls to this function.

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
04/30/95
Returns:
TRUE if ok; FALSE if not (e.g. file/printer/driver error).

Errors: File/printer error

See also:
PSPrintDC::EndOSOutput

Definition at line 791 of file psdc.cpp.

00792 {
00793     if ((SafeToUseGDI == 0) && !GDIContextIsCurrent)
00794     {
00795         // We need to restore the GDI context - this involves removing our dictionary
00796         // from the dictionary stack, and calling restore.
00797         if (!OutputToken(_T("end restore")) || !OutputNewLine())
00798             // Error
00799             return FALSE;
00800         
00801         // Flush our buffer so Camelot PS syncs correctly with GDI PS.
00802         if (!FlushPSBuffer())
00803             // Error
00804             return FALSE;
00805 
00806         GDIContextIsCurrent = TRUE;
00807     }
00808 
00809     // Increment GDI count
00810     SafeToUseGDI++;
00811 
00812     // Ok to use GDI now
00813     return TRUE;
00814 }

WinCoord PSPrintDC::TransformCoord const DocCoord Coord  ) 
 

Transform a DocCoord to a WinCoord, using this DC's transformations, as set up by SetDCTransforms().

Author:
Tim_Browse (Xara Group Ltd) <camelotdev@xara.com>
Date:
30/6/95
Parameters:
Coord - the co-ordinate to transform. [INPUTS]
Returns:
The transformed co-ordinate.
See also:
PSPrintDC::SetDCTransforms

Definition at line 759 of file psdc.cpp.

00760 {
00761     // Use the rendering matrix of our parent render region to transform
00762     // the co-ordinate to device units before proceeding.
00763     OilCoord NewCoord(Coord.x, Coord.y);
00764     RenderMatrix.transform(&NewCoord);
00765 
00766     // Convert to Windows device units.
00767     WinCoord PSCoord = NewCoord.ToWin(pView);
00768 
00769     // Return to caller
00770     return PSCoord;
00771 }

void PSPrintDC::WritePSchar char *  pBuf,
INT32  nBytes
[protected]
 

Writes nBytes of TCHAR to the output stream. Uses Buffer.chardata as a scratch area. Max of MAX_PSBUF can be written at a time.

Author:
Alex Bligh
Date:
23/06/2006
Returns:
-
See also:
-

Definition at line 545 of file psdc.cpp.

00546 {
00547     if ((nBytes>MAX_PSBUF) || (nBytes<=0))
00548     {
00549         ERROR3("Bad PSPrintDC write");
00550         return;
00551     }
00552 
00553 #ifdef _DEBUG
00554     INT32 i;
00555     for (i=0; i<nBytes; i++)
00556     {
00557         if (!pBuf[i])
00558         {
00559             ERROR3("Zero byte in PS Buffer!");
00560             break;
00561         }
00562     }
00563 #endif
00564 
00565     // Need to copy it so we can safely zero terminate it
00566     memcpy(Buffer.CharData, pBuf, nBytes);
00567     Buffer.CharData[nBytes]=0; // safe as chardata one larger than MAX_PSBUF
00568     ((wxPostScriptDC *)GetDC())->PsPrint(Buffer.CharData);
00569 }

void PSPrintDC::WritePSTCHAR TCHAR pBuf,
INT32  nBytes
[protected]
 

Writes nBytes of TCHAR to the output stream. Uses Buffer.chardata as a scratch area. Max of MAX_PSBUF can be written at a time.

Author:
Alex Bligh
Date:
23/06/2006
Returns:
-
See also:
-

Definition at line 507 of file psdc.cpp.

00508 {
00509     if ((nBytes>MAX_PSBUF) || (nBytes<=0))
00510     {
00511         ERROR3("Bad PSPrintDC write");
00512         return;
00513     }
00514 
00515     if (sizeof(TCHAR) == sizeof(char))
00516     {
00517         WritePSchar((char *)pBuf, nBytes);
00518         return;
00519     }
00520 
00521     INT32 i;
00522     for (i=0; i<nBytes; i++)
00523     {
00524         ERROR3IF(!pBuf[i], "Zero byte in PS buffer");
00525         Buffer.CharData[i]=pBuf[i]; // 1:1 copy
00526     }
00527 
00528     Buffer.CharData[nBytes]=0; // safe as chardata one larger than MAX_PSBUF
00529     ((wxPostScriptDC *)GetDC())->PsPrint(Buffer.CharData);
00530 }


Member Data Documentation

PassThruBuffer PSPrintDC::Buffer [protected]
 

Definition at line 209 of file psdc.h.

PSDCFontInfo PSPrintDC::FontInfo [protected]
 

Definition at line 235 of file psdc.h.

BOOL PSPrintDC::GDIContextIsCurrent [protected]
 

Definition at line 228 of file psdc.h.

MILLIPOINT PSPrintDC::PixelSize [protected]
 

Definition at line 215 of file psdc.h.

PrintPSRenderRegion* PSPrintDC::pPSRegion [protected]
 

Definition at line 238 of file psdc.h.

View* PSPrintDC::pView [protected]
 

Definition at line 216 of file psdc.h.

Matrix PSPrintDC::RenderMatrix [protected]
 

Definition at line 214 of file psdc.h.

INT32 PSPrintDC::SafeToUseGDI [protected]
 

Definition at line 219 of file psdc.h.

BOOL PSPrintDC::StartOfPage [protected]
 

Definition at line 224 of file psdc.h.

BOOL PSPrintDC::UsePSLevelClipping [protected]
 

Definition at line 232 of file psdc.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 04:00:12 2007 for Camelot by  doxygen 1.4.4