]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/dcpsg.cpp
added renderer.h/.cpp
[wxWidgets.git] / src / generic / dcpsg.cpp
index c3d1807494fb2c579c3b914a900d74d23a0eff97..5b5ad1c2f743b1af51d20a26f2a8fdf7ae2b7236 100644 (file)
@@ -5,7 +5,7 @@
 // Modified by:
 // Created:     04/01/98
 // RCS-ID:      $Id$
-// Copyright:   (c) Julian Smart and Markus Holzem
+// Copyright:   (c) Julian Smart
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 
 #include "wx/setup.h"
 
-#include "wx/window.h"
 #include "wx/dcmemory.h"
 #include "wx/utils.h"
 #include "wx/intl.h"
-#include "wx/filedlg.h"
 #include "wx/app.h"
-#include "wx/msgdlg.h"
 #include "wx/image.h"
 #include "wx/log.h"
 #include "wx/generic/dcpsg.h"
-#include "wx/printdlg.h"
-#include "wx/button.h"
-#include "wx/stattext.h"
-#include "wx/radiobox.h"
-#include "wx/textctrl.h"
 #include "wx/prntbase.h"
 #include "wx/paper.h"
 #include "wx/filefn.h"
+#if WXWIN_COMPATIBILITY_2_2
+    #include "wx/window.h"
+    #include "wx/printdlg.h"
+#endif
 
 #include <math.h>
 
@@ -204,7 +200,8 @@ static const char *wxPostScriptHeaderColourImage = "\
   } ifelse          %% end of 'false' case\n\
 ";
 
-#ifndef __WXGTK20__
+#if wxUSE_PANGO
+#else
 static char wxPostScriptHeaderReencodeISO1[] =
     "\n/reencodeISO {\n"
 "dup dup findfont dup length dict begin\n"
@@ -253,7 +250,7 @@ static char wxPostScriptHeaderReencodeISO2[] =
 
 IMPLEMENT_DYNAMIC_CLASS(wxPostScriptDC, wxDC)
 
-float wxPostScriptDC::ms_PSScaleFactor = 10.0;
+float wxPostScriptDC::ms_PSScaleFactor = 1.0;
 
 void wxPostScriptDC::SetResolution(int ppi)
 {
@@ -886,7 +883,8 @@ void wxPostScriptDC::SetFont( const wxFont& font )
 
     m_font = font;
 
-#ifndef __WXGTK20__
+#if wxUSE_PANGO
+#else
     int Style = m_font.GetStyle();
     int Weight = m_font.GetWeight();
 
@@ -971,6 +969,7 @@ void wxPostScriptDC::SetFont( const wxFont& font )
     for (int i = 0; i < 100; i++)
         if (buffer[i] == ',') buffer[i] = '.';
     fprintf( m_pstream, buffer );
+
 #endif
 }
 
@@ -1117,13 +1116,18 @@ void wxPostScriptDC::SetBrush( const wxBrush& brush )
     }
 }
 
-#ifdef __WXGTK20__
+#if wxUSE_PANGO
 
 #define PANGO_ENABLE_ENGINE
 
+#ifdef __WXGTK20__
 #include "wx/gtk/private.h"
-#include "wx/fontutil.h"
 #include "gtk/gtk.h"
+#else
+#include "wx/x11/private.h"
+#endif
+
+#include "wx/fontutil.h"
 #include <pango/pangoft2.h>
 #include <freetype/ftglyph.h>
 
@@ -1194,8 +1198,8 @@ void draw_bezier_outline(FILE *file,
                         FT_UInt glyph_index,
                         int pos_x,
                         int pos_y,
-             int scale_x,
-             int scale_y )
+             double scale_x,
+             double scale_y )
 {
   FT_Int load_flags = FT_LOAD_NO_BITMAP;
   FT_Glyph glyph;
@@ -1213,16 +1217,20 @@ void draw_bezier_outline(FILE *file,
 
   fprintf(file, "gsave\n");
   fprintf(file, "%d %d translate\n", pos_x, pos_y );
-  // FT2 scales outlines to 26.6 pixels so the code below
-  // should read 26600 instead of the 60000.
-  fprintf(file, "%d 60000 div %d 60000 div scale\n", scale_x, scale_y );
-  fprintf(file, "0 0 0 setrgbcolor\n");
+  
+  // We have to replace the "," from the German
+  // locale with the Englich "." for PostScript
+  char buf[100];
+  sprintf(buf, "%.8f %.8f scale\n", scale_x, scale_y );
+  for (size_t i = 0; i < strlen(buf); i++)
+     if (buf[i] == ',') buf[i] = '.';
+  fprintf(file, buf);
 
   FT_Load_Glyph(face, glyph_index, load_flags);
   FT_Get_Glyph (face->glyph, &glyph);
   FT_Outline_Decompose (&(((FT_OutlineGlyph)glyph)->outline),
                         &outlinefunc, &outline_info);
-  fprintf(file, "closepath fill grestore \n");
+  fprintf(file, "closepath fill grestore\n");
   
   FT_Done_Glyph (glyph);
 }
@@ -1233,10 +1241,53 @@ void wxPostScriptDC::DoDrawText( const wxString& text, wxCoord x, wxCoord y )
 {
     wxCHECK_RET( m_ok && m_pstream, wxT("invalid postscript dc") );
 
-#ifdef __WXGTK20__
-    int dpi = GetResolution();
-    dpi = 300;
-    PangoContext *context = pango_ft2_get_context ( dpi, dpi );
+    if (m_textForegroundColour.Ok())
+    {
+        unsigned char red = m_textForegroundColour.Red();
+        unsigned char blue = m_textForegroundColour.Blue();
+        unsigned char green = m_textForegroundColour.Green();
+
+        if (!m_colour)
+        {
+            // Anything not white is black
+            if (! (red == (unsigned char) 255 &&
+                        blue == (unsigned char) 255 &&
+                        green == (unsigned char) 255))
+            {
+                red = (unsigned char) 0;
+                green = (unsigned char) 0;
+                blue = (unsigned char) 0;
+            }
+        }
+
+        // maybe setgray here ?
+        if (!(red == m_currentRed && green == m_currentGreen && blue == m_currentBlue))
+        {
+            double redPS = (double)(red) / 255.0;
+            double bluePS = (double)(blue) / 255.0;
+            double greenPS = (double)(green) / 255.0;
+
+            char buffer[100];
+            sprintf( buffer,
+                "%.8f %.8f %.8f setrgbcolor\n",
+                redPS, greenPS, bluePS );
+            for (size_t i = 0; i < strlen(buffer); i++)
+                if (buffer[i] == ',') buffer[i] = '.';
+            fprintf( m_pstream, buffer );
+
+            m_currentRed = red;
+            m_currentBlue = blue;
+            m_currentGreen = green;
+        }
+    }
+    
+#if wxUSE_PANGO
+    int ps_dpi = 72;
+    int pango_dpi = 600;
+    PangoContext *context = pango_ft2_get_context ( pango_dpi, pango_dpi );
+    
+    double scale = (double)pango_dpi / (double)ps_dpi;
+    scale /= m_userScaleY;
 
     pango_context_set_language (context, pango_language_from_string ("en_US"));
     pango_context_set_base_dir (context, PANGO_DIRECTION_LTR );
@@ -1250,22 +1301,29 @@ void wxPostScriptDC::DoDrawText( const wxString& text, wxCoord x, wxCoord y )
     wxCharBuffer buffer = wxConvUTF8.cWC2MB( wxConvLocal.cWX2WC( text ) );
 #endif
        pango_layout_set_text( layout, (const char*) buffer, strlen(buffer) );
+    
+    fprintf( m_pstream, "%%%% %s\n", (const char*)buffer );
 
     PangoRectangle rect;
     pango_layout_get_extents(layout, NULL, &rect);
     
-    int xx = x * PANGO_SCALE;
-    int yy = y * PANGO_SCALE + (rect.height*2/3);
-    
-    int scale_x = LogicalToDeviceXRel( 1000 );
-    int scale_y = LogicalToDeviceYRel( 1000 );
+    int xx = LogicalToDeviceX( x );
+    int yy = LogicalToDeviceY( y );
     
+    int xxx = xx * PANGO_SCALE;
+    int yyy = yy * PANGO_SCALE - (int)(rect.height * 0.66 / scale);  // Move down by estimated baseline. HACK.
+
+#define ps_kludge_factor 2.8
+
     // Loop over lines in layout
     int num_lines = pango_layout_get_line_count( layout );
     for (int i = 0; i < num_lines; i++)
     {
         PangoLayoutLine *line = pango_layout_get_line( layout, i );
         
+        // width of glyphs already printed
+        int all_width = 0;
+        
         // Loop over runs in line
         GSList *runs_list = line->runs;
         while (runs_list)
@@ -1281,21 +1339,23 @@ void wxPostScriptDC::DoDrawText( const wxString& text, wxCoord x, wxCoord y )
             for (int glyph_idx = 0; glyph_idx < num_glyphs; glyph_idx++)
             {
                 PangoGlyphGeometry geometry = glyphs->glyphs[glyph_idx].geometry;
-                int pos_x = xx + geometry.x_offset;
-                int pos_y = yy - geometry.y_offset;
-                xx += geometry.width;
+                int pos_x = xxx + (int)((double)(all_width+geometry.x_offset) / scale);
+                int pos_y = yyy + (int)((double)geometry.y_offset / scale );
+                all_width += geometry.width;
                 
                 draw_bezier_outline( m_pstream, ft_face,
                              (FT_UInt)(glyphs->glyphs[glyph_idx].glyph),
-                             LogicalToDeviceX( pos_x / PANGO_SCALE ), 
-                  LogicalToDeviceY( pos_y / PANGO_SCALE ),
-                  scale_x, scale_y );
+                             pos_x / PANGO_SCALE, 
+                  pos_y / PANGO_SCALE,
+                  1.0/(ps_kludge_factor * scale * 26.6), 
+                  1.0/(ps_kludge_factor * scale * 26.6) );
             }
             runs_list = runs_list->next;
         }
        }
 
     g_object_unref( G_OBJECT( layout ) );
+    g_object_unref( G_OBJECT( context ) );
 #else
     wxCoord text_w, text_h, text_descent;
 
@@ -1305,45 +1365,6 @@ void wxPostScriptDC::DoDrawText( const wxString& text, wxCoord x, wxCoord y )
     //     doesn't create any problems, remove this comment entirely
     //SetFont( m_font );
 
-    if (m_textForegroundColour.Ok())
-    {
-        unsigned char red = m_textForegroundColour.Red();
-        unsigned char blue = m_textForegroundColour.Blue();
-        unsigned char green = m_textForegroundColour.Green();
-
-        if (!m_colour)
-        {
-            // Anything not white is black
-            if (! (red == (unsigned char) 255 &&
-                        blue == (unsigned char) 255 &&
-                        green == (unsigned char) 255))
-            {
-                red = (unsigned char) 0;
-                green = (unsigned char) 0;
-                blue = (unsigned char) 0;
-            }
-        }
-
-        // maybe setgray here ?
-        if (!(red == m_currentRed && green == m_currentGreen && blue == m_currentBlue))
-        {
-            double redPS = (double)(red) / 255.0;
-            double bluePS = (double)(blue) / 255.0;
-            double greenPS = (double)(green) / 255.0;
-
-            char buffer[100];
-            sprintf( buffer,
-                "%.8f %.8f %.8f setrgbcolor\n",
-                redPS, greenPS, bluePS );
-            for (int i = 0; i < 100; i++)
-                if (buffer[i] == ',') buffer[i] = '.';
-            fprintf( m_pstream, buffer );
-
-            m_currentRed = red;
-            m_currentBlue = blue;
-            m_currentGreen = green;
-        }
-    }
 
     int size = m_font.GetPointSize();
 
@@ -1458,11 +1479,8 @@ void wxPostScriptDC::DoDrawRotatedText( const wxString& text, wxCoord x, wxCoord
 
     int size = m_font.GetPointSize();
 
-    long by = y + (long)floor( double(size) * 2.0 / 3.0 ); // approximate baseline
-
-    // FIXME only correct for 90 degrees
     fprintf(m_pstream, "%d %d moveto\n",
-            LogicalToDeviceX((wxCoord)(x + size)), LogicalToDeviceY((wxCoord)by) );
+            LogicalToDeviceX(x), LogicalToDeviceY(y));
 
     char buffer[100];
     sprintf(buffer, "%.8f rotate\n", angle);
@@ -1546,13 +1564,13 @@ void wxPostScriptDC::DoDrawSpline( wxList *points )
     double a, b, c, d, x1, y1, x2, y2, x3, y3;
     wxPoint *p, *q;
 
-    wxNode *node = points->First();
-    p = (wxPoint *)node->Data();
+    wxList::compatibility_iterator node = points->GetFirst();
+    p = (wxPoint *)node->GetData();
     x1 = p->x;
     y1 = p->y;
 
-    node = node->Next();
-    p = (wxPoint *)node->Data();
+    node = node->GetNext();
+    p = (wxPoint *)node->GetData();
     c = p->x;
     d = p->y;
     x3 = a = (double)(x1 + c) / 2;
@@ -1568,9 +1586,9 @@ void wxPostScriptDC::DoDrawSpline( wxList *points )
     CalcBoundingBox( (wxCoord)x1, (wxCoord)y1 );
     CalcBoundingBox( (wxCoord)x3, (wxCoord)y3 );
 
-    while ((node = node->Next()) != NULL)
+    while ((node = node->GetNext()))
     {
-        q = (wxPoint *)node->Data();
+        q = (wxPoint *)node->GetData();
 
         x1 = x3;
         y1 = y3;
@@ -1699,9 +1717,9 @@ bool wxPostScriptDC::StartDoc( const wxString& message )
 {
     wxCHECK_MSG( m_ok, FALSE, wxT("invalid postscript dc") );
 
-    if (m_printData.GetFilename() == "")
+    if (m_printData.GetFilename() == wxT(""))
     {
-        wxString filename = wxGetTempFileName("ps");
+        wxString filename = wxGetTempFileName( wxT("ps") );
         m_printData.SetFilename(filename);
     }
 
@@ -1727,7 +1745,7 @@ bool wxPostScriptDC::StartDoc( const wxString& message )
     
     // fprintf( m_pstream, "%%%%Pages: %d\n", (wxPageNumber - 1) );
     
-    char *paper = "A4";
+    const char *paper;
     switch (m_printData.GetPaperId())
     {
        case wxPAPER_LETTER: paper = "Letter"; break;             // Letter: paper ""; 8 1/2 by 11 inches
@@ -1754,7 +1772,8 @@ bool wxPostScriptDC::StartDoc( const wxString& message )
     fprintf( m_pstream, wxPostScriptHeaderEllipse );
     fprintf( m_pstream, wxPostScriptHeaderEllipticArc );
     fprintf( m_pstream, wxPostScriptHeaderColourImage );
-#ifndef __WXGTK20__
+#if wxUSE_PANGO
+#else
     fprintf( m_pstream, wxPostScriptHeaderReencodeISO1 );
     fprintf( m_pstream, wxPostScriptHeaderReencodeISO2 );
 #endif
@@ -1862,6 +1881,8 @@ void wxPostScriptDC::EndDoc ()
         wxString command;
         command += m_printData.GetPrinterCommand();
         command += wxT(" ");
+        command += m_printData.GetPrinterOptions();
+        command += wxT(" ");
         command += m_printData.GetFilename();
 
         wxExecute( command, TRUE );
@@ -1969,12 +1990,18 @@ void wxPostScriptDC::DoGetTextExtent(const wxString& string,
     {
         if (x) (*x) = 0;
         if (y) (*y) = 0;
+        if (descent) (*descent) = 0;
+        if (externalLeading) (*externalLeading) = 0;
         return;
     }
     
-#ifdef __WXGTK20__
-    int dpi = GetResolution();
-    PangoContext *context = pango_ft2_get_context ( dpi, dpi );
+#if wxUSE_PANGO
+    int wx_dpi = GetResolution();
+    int pango_dpi = 600;
+    PangoContext *context = pango_ft2_get_context ( pango_dpi, pango_dpi );
+    
+    double scale = pango_dpi / wx_dpi;
+    scale /= m_userScaleY;
     
     pango_context_set_language (context, pango_language_from_string ("en_US"));
     pango_context_set_base_dir (context, PANGO_DIRECTION_LTR );
@@ -1984,20 +2011,19 @@ void wxPostScriptDC::DoGetTextExtent(const wxString& string,
     PangoFontDescription *desc = fontToUse->GetNativeFontInfo()->description;
     pango_layout_set_font_description(layout, desc);
 #if wxUSE_UNICODE
-        const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
-        pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
+    const wxCharBuffer data = wxConvUTF8.cWC2MB( string );
 #else
-        const wxWCharBuffer wdata = wxConvLocal.cMB2WC( string );
-        const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata );
-        pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
+    const wxWCharBuffer wdata = wxConvLocal.cMB2WC( string );
+    const wxCharBuffer data = wxConvUTF8.cWC2MB( wdata );
 #endif
+    pango_layout_set_text(layout, (const char*) data, strlen( (const char*) data ));
     PangoLayoutLine *line = (PangoLayoutLine *)pango_layout_get_lines(layout)->data;
  
     PangoRectangle rect;
     pango_layout_line_get_extents(line, NULL, &rect);
     
-    if (x) (*x) = (wxCoord) ( m_scaleX * rect.width / PANGO_SCALE );
-    if (y) (*y) = (wxCoord) ( m_scaleY * rect.height / PANGO_SCALE );
+    if (x) (*x) = (wxCoord) ( rect.width / PANGO_SCALE / scale );
+    if (y) (*y) = (wxCoord) ( rect.height / PANGO_SCALE / scale );
     if (descent)
     {
         // Do something about metrics here
@@ -2093,40 +2119,40 @@ void wxPostScriptDC::DoGetTextExtent(const wxString& string,
         lastStyle =  Style;
         lastWeight = Weight;
 
-        const char *name = NULL;
+        const wxChar *name = NULL;
 
         switch (Family)
         {
             case wxMODERN:
             case wxTELETYPE:
             {
-                if ((Style == wxITALIC) && (Weight == wxBOLD)) name = "CourBoO.afm";
-                else if ((Style != wxITALIC) && (Weight == wxBOLD)) name = "CourBo.afm";
-                else if ((Style == wxITALIC) && (Weight != wxBOLD)) name = "CourO.afm";
-                else name = "Cour.afm";
+                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 = "TimesBoO.afm";
-                else if ((Style != wxITALIC) && (Weight == wxBOLD)) name = "TimesBo.afm";
-                else if ((Style == wxITALIC) && (Weight != wxBOLD)) name = "TimesO.afm";
-                else name = "TimesRo.afm";
+                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 = "Zapf.afm";
+                name = wxT("Zapf.afm");
                 Style = wxNORMAL;
                 Weight = wxNORMAL;
             }
             case wxSWISS:
             default:
             {
-                if ((Style == wxITALIC) && (Weight == wxBOLD)) name = "HelvBoO.afm";
-                else if ((Style != wxITALIC) && (Weight == wxBOLD)) name = "HelvBo.afm";
-                else if ((Style == wxITALIC) && (Weight != wxBOLD)) name = "HelvO.afm";
-                else name = "Helv.afm";
+                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;
             }
         }
@@ -2260,13 +2286,15 @@ void wxPostScriptDC::DoGetTextExtent(const wxString& string,
            /  the correct way would be to map the character names
            /  like 'adieresis' to corresp. positions of ISOEnc and read
            /  these values from AFM files, too. Maybe later ... */
-        lastWidths[196] = lastWidths['A'];  // Ä
-        lastWidths[228] = lastWidths['a'];  // ä
-        lastWidths[214] = lastWidths['O'];  // Ö
-        lastWidths[246] = lastWidths['o'];  // ö
-        lastWidths[220] = lastWidths['U'];  // Ü
-        lastWidths[252] = lastWidths['u'];  // ü
-        lastWidths[223] = lastWidths[251];  // ß
+
+        // NB: casts to int are needed to suppress gcc 3.3 warnings
+        lastWidths[196] = lastWidths[(int)'A'];  // Ä
+        lastWidths[228] = lastWidths[(int)'a'];  // ä
+        lastWidths[214] = lastWidths[(int)'O'];  // Ö
+        lastWidths[246] = lastWidths[(int)'o'];  // ö
+        lastWidths[220] = lastWidths[(int)'U'];  // Ü
+        lastWidths[252] = lastWidths[(int)'u'];  // ü
+        lastWidths[223] = lastWidths[(int)251];  // ß
 
         /* JC: calculate UnderlineThickness/UnderlinePosition */
 
@@ -2292,7 +2320,7 @@ void wxPostScriptDC::DoGetTextExtent(const wxString& string,
         if(lastWidths[*p]== INT_MIN)
         {
             wxLogDebug(wxT("GetTextExtent: undefined width for character '%c' (%d)"), *p,*p);
-            sum += lastWidths[' ']; /* assume space */
+            sum += lastWidths[(unsigned char)' ']; /* assume space */
         }
         else
         {