dcpsg.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,062 行 · 第 1/5 页
CPP
2,062 行
wxCHECK_RET( m_ok, wxT("invalid postscript dc") );
if (m_clipping)
{
m_clipping = false;
PsPrint( "grestore\n" );
}
if ( m_pstream ) {
fclose( m_pstream );
m_pstream = (FILE *) NULL;
}
#if 0
// THE FOLLOWING HAS BEEN CONTRIBUTED BY Andy Fyfe <andy@hyperparallel.com>
wxCoord wx_printer_translate_x, wx_printer_translate_y;
double wx_printer_scale_x, wx_printer_scale_y;
wx_printer_translate_x = (wxCoord)m_printData.GetPrinterTranslateX();
wx_printer_translate_y = (wxCoord)m_printData.GetPrinterTranslateY();
wx_printer_scale_x = m_printData.GetPrinterScaleX();
wx_printer_scale_y = m_printData.GetPrinterScaleY();
// Compute the bounding box. Note that it is in the default user
// coordinate system, thus we have to convert the values.
wxCoord minX = (wxCoord) LogicalToDeviceX(m_minX);
wxCoord minY = (wxCoord) LogicalToDeviceY(m_minY);
wxCoord maxX = (wxCoord) LogicalToDeviceX(m_maxX);
wxCoord maxY = (wxCoord) LogicalToDeviceY(m_maxY);
// LOG2DEV may have changed the minimum to maximum vice versa
if ( minX > maxX ) { wxCoord tmp = minX; minX = maxX; maxX = tmp; }
if ( minY > maxY ) { wxCoord tmp = minY; minY = maxY; maxY = tmp; }
// account for used scaling (boundingbox is before scaling in ps-file)
double scale_x = m_printData.GetPrinterScaleX() / ms_PSScaleFactor;
double scale_y = m_printData.GetPrinterScaleY() / ms_PSScaleFactor;
wxCoord llx, lly, urx, ury;
llx = (wxCoord) ((minX+wx_printer_translate_x)*scale_x);
lly = (wxCoord) ((minY+wx_printer_translate_y)*scale_y);
urx = (wxCoord) ((maxX+wx_printer_translate_x)*scale_x);
ury = (wxCoord) ((maxY+wx_printer_translate_y)*scale_y);
// (end of bounding box computation)
// If we're landscape, our sense of "x" and "y" is reversed.
if (m_printData.GetOrientation() == wxLANDSCAPE)
{
wxCoord tmp;
tmp = llx; llx = lly; lly = tmp;
tmp = urx; urx = ury; ury = tmp;
// We need either the two lines that follow, or we need to subtract
// min_x from real_translate_y, which is commented out below.
llx = llx - (wxCoord)(m_minX*wx_printer_scale_y);
urx = urx - (wxCoord)(m_minX*wx_printer_scale_y);
}
// The Adobe specifications call for integers; we round as to make
// the bounding larger.
PsPrintf( wxT("%%%%BoundingBox: %d %d %d %d\n"),
(wxCoord)floor((double)llx), (wxCoord)floor((double)lly),
(wxCoord)ceil((double)urx), (wxCoord)ceil((double)ury) );
// To check the correctness of the bounding box, postscript commands
// to draw a box corresponding to the bounding box are generated below.
// But since we typically don't want to print such a box, the postscript
// commands are generated within comments. These lines appear before any
// adjustment of scale, rotation, or translation, and hence are in the
// default user coordinates.
PsPrint( "% newpath\n" );
PsPrintf( wxT("%% %d %d moveto\n"), llx, lly );
PsPrintf( wxT("%% %d %d lineto\n"), urx, lly );
PsPrintf( wxT("%% %d %d lineto\n"), urx, ury );
PsPrintf( wxT("%% %d %d lineto closepath stroke\n"), llx, ury );
#endif
#ifndef __WXMSW__
wxPostScriptPrintNativeData *data =
(wxPostScriptPrintNativeData *) m_printData.GetNativeData();
if (m_ok && (m_printData.GetPrintMode() == wxPRINT_MODE_PRINTER))
{
wxString command;
command += data->GetPrinterCommand();
command += wxT(" ");
command += data->GetPrinterOptions();
command += wxT(" ");
command += m_printData.GetFilename();
wxExecute( command, true );
wxRemoveFile( m_printData.GetFilename() );
}
#endif
}
void wxPostScriptDC::StartPage()
{
wxCHECK_RET( m_ok, wxT("invalid postscript dc") );
PsPrintf( wxT("%%%%Page: %d\n"), wxPageNumber++ );
// What is this one supposed to do? RR.
// *m_pstream << "matrix currentmatrix\n";
// Added by Chris Breeze
// Each page starts with an "initgraphics" which resets the
// transformation and so we need to reset the origin
// (and rotate the page for landscape printing)
// Output scaling
wxCoord translate_x, translate_y;
double scale_x, scale_y;
wxPostScriptPrintNativeData *data =
(wxPostScriptPrintNativeData *) m_printData.GetNativeData();
translate_x = (wxCoord)data->GetPrinterTranslateX();
translate_y = (wxCoord)data->GetPrinterTranslateY();
scale_x = data->GetPrinterScaleX();
scale_y = data->GetPrinterScaleY();
if (m_printData.GetOrientation() == wxLANDSCAPE)
{
int h;
GetSize( (int*) NULL, &h );
translate_y -= h;
PsPrint( "90 rotate\n" );
// I copied this one from a PostScript tutorial, but to no avail. RR.
// PsPrint( "90 rotate llx neg ury nef translate\n" );
}
char buffer[100];
sprintf( buffer, "%.8f %.8f scale\n", scale_x / ms_PSScaleFactor,
scale_y / ms_PSScaleFactor);
for (int i = 0; i < 100; i++)
if (buffer[i] == ',') buffer[i] = '.';
PsPrint( buffer );
PsPrintf( wxT("%d %d translate\n"), translate_x, translate_y );
}
void wxPostScriptDC::EndPage ()
{
wxCHECK_RET( m_ok , wxT("invalid postscript dc") );
PsPrint( "showpage\n" );
}
bool wxPostScriptDC::DoBlit( wxCoord xdest, wxCoord ydest,
wxCoord fwidth, wxCoord fheight,
wxDC *source,
wxCoord xsrc, wxCoord ysrc,
int rop, bool WXUNUSED(useMask), wxCoord WXUNUSED(xsrcMask), wxCoord WXUNUSED(ysrcMask) )
{
wxCHECK_MSG( m_ok, false, wxT("invalid postscript dc") );
wxCHECK_MSG( source, false, wxT("invalid source dc") );
/* blit into a bitmap */
wxBitmap bitmap( (int)fwidth, (int)fheight );
wxMemoryDC memDC;
memDC.SelectObject(bitmap);
memDC.Blit(0, 0, fwidth, fheight, source, xsrc, ysrc, rop); /* TODO: Blit transparently? */
memDC.SelectObject(wxNullBitmap);
/* draw bitmap. scaling and positioning is done there */
DrawBitmap( bitmap, xdest, ydest );
return true;
}
wxCoord wxPostScriptDC::GetCharHeight() const
{
if (m_font.Ok())
return m_font.GetPointSize();
else
return 12;
}
void wxPostScriptDC::DoGetTextExtent(const wxString& string,
wxCoord *x, wxCoord *y,
wxCoord *descent, wxCoord *externalLeading,
wxFont *theFont ) const
{
wxFont *fontToUse = theFont;
if (!fontToUse) fontToUse = (wxFont*) &m_font;
wxCHECK_RET( fontToUse, wxT("GetTextExtent: no font defined") );
if (string.empty())
{
if (x) (*x) = 0;
if (y) (*y) = 0;
if (descent) (*descent) = 0;
if (externalLeading) (*externalLeading) = 0;
return;
}
// GTK 2.0
const wxWX2MBbuf strbuf = string.mb_str();
#if !wxUSE_AFM_FOR_POSTSCRIPT
/* Provide a VERY rough estimate (avoid using it).
* Produces accurate results for mono-spaced font
* such as Courier (aka wxMODERN) */
int height = 12;
if (fontToUse)
{
height = fontToUse->GetPointSize();
}
if ( x )
*x = strlen (strbuf) * height * 72 / 120;
if ( y )
*y = (wxCoord) (height * 1.32); /* allow for descender */
if (descent) *descent = 0;
if (externalLeading) *externalLeading = 0;
#else
/* method for calculating string widths in postscript:
/ read in the AFM (adobe font metrics) file for the
/ actual font, parse it and extract the character widths
/ and also the descender. this may be improved, but for now
/ it works well. the AFM file is only read in if the
/ font is changed. this may be chached in the future.
/ calls to GetTextExtent with the font unchanged are rather
/ efficient!!!
/
/ for each font and style used there is an AFM file necessary.
/ currently i have only files for the roman font family.
/ I try to get files for the other ones!
/
/ CAVE: the size of the string is currently always calculated
/ in 'points' (1/72 of an inch). this should later on be
/ changed to depend on the mapping mode.
/ CAVE: the path to the AFM files must be set before calling this
/ function. this is usually done by a call like the following:
/ wxSetAFMPath("d:\\wxw161\\afm\\");
/
/ example:
/
/ wxPostScriptDC dc(NULL, true);
/ if (dc.Ok()){
/ wxSetAFMPath("d:\\wxw161\\afm\\");
/ dc.StartDoc("Test");
/ dc.StartPage();
/ wxCoord w,h;
/ dc.SetFont(new wxFont(10, wxROMAN, wxNORMAL, wxNORMAL));
/ dc.GetTextExtent("Hallo",&w,&h);
/ dc.EndPage();
/ dc.EndDoc();
/ }
/
/ by steve (stefan.hammes@urz.uni-heidelberg.de)
/ created: 10.09.94
/ updated: 14.05.95 */
/* these static vars are for storing the state between calls */
static int lastFamily= INT_MIN;
static int lastSize= INT_MIN;
static int lastStyle= INT_MIN;
static int lastWeight= INT_MIN;
static int lastDescender = INT_MIN;
static int lastWidths[256]; /* widths of the characters */
double UnderlinePosition = 0.0;
double UnderlineThickness = 0.0;
// Get actual parameters
int Family = fontToUse->GetFamily();
int Size = fontToUse->GetPointSize();
int Style = fontToUse->GetStyle();
int Weight = fontToUse->GetWeight();
// If we have another font, read the font-metrics
if (Family!=lastFamily || Size!=lastSize || Style!=lastStyle || Weight!=lastWeight)
{
// Store actual values
lastFamily = Family;
lastSize = Size;
lastStyle = Style;
lastWeight = Weight;
const wxChar *name;
switch (Family)
{
case wxMODERN:
case wxTELETYPE:
{
if ((Style == wxITALIC) && (Weight == wxBOLD)) name = wxT("CourBoO.afm");
else if ((Style != wxITALIC) && (Weight == wxBOLD)) name = wxT("CourBo.afm");
else if ((Style == wxITALIC) && (Weight != wxBOLD)) name = wxT("CourO.afm");
else name = wxT("Cour.afm");
break;
}
case wxROMAN:
{
if ((Style == wxITALIC) && (Weight == wxBOLD)) name = wxT("TimesBoO.afm");
else if ((Style != wxITALIC) && (Weight == wxBOLD)) name = wxT("TimesBo.afm");
else if ((Style == wxITALIC) && (Weight != wxBOLD)) name = wxT("TimesO.afm");
else name = wxT("TimesRo.afm");
break;
}
case wxSCRIPT:
{
name = wxT("Zapf.afm");
break;
}
case wxSWISS:
default:
{
if ((Style == wxITALIC) && (Weight == wxBOLD)) name = wxT("HelvBoO.afm");
else if ((Style != wxITALIC) && (Weight == wxBOLD)) name = wxT("HelvBo.afm");
else if ((Style == wxITALIC) && (Weight != wxBOLD)) name = wxT("HelvO.afm");
else name = wxT("Helv.afm");
break;
}
}
FILE *afmFile = NULL;
// Get the directory of the AFM files
wxString afmName;
// VZ: I don't know if the cast always works under Unix but it clearly
// never does under Windows where the pointer is
// wxWindowsPrintNativeData and so calling GetFontMetricPath() on
// it just crashes
#ifndef __WIN32__
wxPostScriptPrintNativeData *data =
wxDynamicCast(m_printData.GetNativeData(), wxPostScriptPrintNativeData);
if (data && !data->GetFontMetricPath().empty())
{
afmName = data->GetFontMetricPath();
afmName << wxFILE_SEP_PATH << name;
}
#endif // __WIN32__
if ( !afmName.empty() )
afmFile = wxFopen(afmName, wxT("r"));
if ( !afmFile )
{
}
if ( !afmFile )
{
#if defined(__UNIX__) && !defined(__VMS__)
afmName = wxGetDataDir();
#else // !__UNIX__
afmName = wxStandardPaths::Get().GetDataDir();
#endif // __UNIX__/!__UNIX__
afmName << wxFILE_SEP_PATH
#if defined(__LINUX__) || defined(__FREEBSD__)
<< wxT("gs_afm") << wxFILE_SEP_PATH
#else
<< wxT("afm") << wxFILE_SEP_PATH
#endif
<< name;
afmFile = wxFopen(afmName,wxT("r"));
}
/* 2. open and process the file
/ a short explanation of the AFM format:
/ we have for each character a line, which gives its size
/ e.g.:
/
/ C 63 ; WX 444 ; N question ; B 49 -14 395 676 ;
/
/ that means, we have a character with ascii code 63, and width
/ (444/1000 * fontSize) points.
/ the other data is ignored for now!
/
/ when the font has changed, we read in the right AFM file and store the
/ character widths in an array, which is processed below (see point 3.). */
if (afmFile==NULL)
{
wxLogDebug( wxT("GetTextExtent: can't open AFM file '%s'"), afmName.c_str() );
wxLogDebug( wxT(" using approximate values"));
for (int i=0; i<256; i++) lastWidths[i] = 500; /* an approximate value */
lastDescender = -150; /* dito. */
}
else
{
/* init the widths array */
for(int i=0; i<256; i++) lastWidths[i] = INT_MIN;
/* some variables for holding parts of a line */
char cString[10], semiString[10], WXString[10];
char descString[20];
char upString[30], utString[30];
char encString[50];
char line[256];
int ascii,cWidth;
/* read in the file and parse it */
while(fgets(line,sizeof(line),afmFile)!=NULL)
{
/* A.) check for descender definition */
if (strncmp(line,"Descender",9)==0)
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?