Scribus Developer Documentation - API
logo-pen

Scribus Developer Documentation - API

scpainterex_ps2.cpp

Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 /* This file is part of the KDE project.
00008    Copyright (C) 2001, 2002, 2003 The Karbon Developers
00009 
00010    This library is free software; you can redistribute it and/or
00011    modify it under the terms of the GNU Library General Public
00012    License as published by the Free Software Foundation; either
00013    version 2 of the License, or (at your option) any later version.
00014 
00015    This library is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018    Library General Public License for more details.
00019 
00020    You should have received a copy of the GNU Library General Public License
00021    along with this library; see the file COPYING.LIB.  If not, write to
00022    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00023    Boston, MA 02111-1307, USA.
00024 */
00025 /* Adapted for Scribus 22.08.2003 by Franz Schmid */
00026 // kopainter/libart wrapper
00027 
00028 #include "scpainterex_ps2.h"
00029 
00030 #include <cfloat>
00031 #include <QPaintDevice>
00032 #include <QPixmap>
00033 #include <QImage>
00034 
00035 #include <iostream>
00036 #include <memory>
00037 using namespace std;
00038  
00039 #include <cmath>
00040 #include "util.h"
00041 #include "sccolorengine.h"
00042 
00043 ScPs2OutputParams::ScPs2OutputParams(ScribusDoc* doc)
00044 {
00045     document = doc;
00046     colorMode = ScPainterExBase::rgbMode;
00047     reloadImages = true;
00048     resolution = 72;
00049     useProfiles = false;
00050     toGray = false;
00051     mirrorH = false;
00052     mirrorV = false;
00053     hProfile = NULL;
00054     rgbToOutputColorTransform = NULL;
00055     rgbToOutputImageTransform = NULL;
00056     cmykToOutputColorTransform = NULL;
00057     cmykToOutputImageTransform = NULL;
00058 }
00059 
00060 ScPainterEx_Ps2::ScPainterEx_Ps2(QIODevice* iodev, QRect& rect, ScPs2OutputParams& options ) : ScPainterExBase()
00061 {
00062     m_stream.setDevice( iodev );
00063     m_colorMode = options.colorMode;
00064     m_encoding  = Ascii85Encoding;
00065     m_options = options;
00066     m_width = rect.width();
00067     m_height= rect.height();
00068     m_x = rect.left();
00069     m_y = rect.top();
00070     m_fillColor = ScColorShade( QColor(0,0,0), 100 );
00071     m_strokeColor = ScColorShade( QColor(0,0,0), 100 );
00072     m_fillTrans = 1.0;
00073     m_strokeTrans = 1.0;
00074     m_fillRule = true;
00075     m_fillMode = 1;
00076     m_lineWidth = 1.0;
00077     m_offset = 0;
00078     m_array.clear();
00079     m_lineEnd = Qt::SquareCap;
00080     m_lineJoin = Qt::RoundJoin;
00081     m_fillGradient = VGradientEx(VGradientEx::linear);
00082     m_strokeGradient = VGradientEx(VGradientEx::linear);
00083     m_matrix = QMatrix();
00084     m_pageTrans = QMatrix();
00085     // Path state
00086     m_pathIsClosed = true;
00087     m_drawingClosedPath = false;
00088     // TODO : set proper values
00089     m_deviceDimX = 0;
00090     m_deviceDimY = 0;
00091     m_deviceResX = 0;
00092     m_deviceResY = 0;
00093     clear();
00094 }
00095 
00096 ScPainterEx_Ps2::~ScPainterEx_Ps2()
00097 {
00098 }
00099 
00100 ScPainterExBase::ImageMode ScPainterEx_Ps2::imageMode()
00101 {
00102     ImageMode imageMode;
00103     if (m_options.hProfile && m_options.rgbToOutputImageTransform && m_options.cmykToOutputImageTransform)
00104         imageMode = rawImages;
00105     else if (m_colorMode == cmykMode)
00106         imageMode = cmykImages;
00107     else
00108         imageMode = rgbImages;
00109     return imageMode;
00110 }
00111 
00112 void ScPainterEx_Ps2::transformImage( QImage* image, uchar* data, int scan)
00113 {
00114     int rgb, grey;
00115     int imageWidth = image->width();
00116     int imageHeight = image->height();
00117 
00118     QRgb*  pscani;
00119     uchar *pscand;
00120 
00121     pscand = data;
00122     for ( int j = 0; j < imageHeight; j++ )
00123     {
00124         pscani = (QRgb *) image->scanLine(j);
00125         for (int i = 0; i < imageWidth; i++ )
00126         {
00127             rgb = pscani[i];
00128             grey = qRound(0.3 * qRed(rgb)) + qRound(0.59 * qGreen(rgb)) + qRound(0.11 * qBlue(rgb));
00129             pscand[i] = grey;
00130         }
00131         pscand += scan;
00132     }
00133 
00134 }
00135 
00136 void ScPainterEx_Ps2::begin()
00137 {
00138 }
00139 
00140 void ScPainterEx_Ps2::end()
00141 {
00142 
00143 }
00144 
00145 void ScPainterEx_Ps2::clear()
00146 {
00147 
00148 }
00149 
00150 void ScPainterEx_Ps2::clear( ScColorShade &c )
00151 {
00152 
00153 }
00154 
00155 const QMatrix ScPainterEx_Ps2::worldMatrix()
00156 {
00157     return m_matrix;
00158 }
00159 
00160 void ScPainterEx_Ps2::setWorldMatrix( const QMatrix &mat )
00161 {
00162     m_matrix = mat;
00163 }
00164 
00165 void ScPainterEx_Ps2::transformPoint( const FPoint& in, FPoint& out )
00166 {
00167     double x, y;
00168     x = in.x() * m_matrix.m11() + in.y() * m_matrix.m21() + m_matrix.dx();
00169     y = in.x() * m_matrix.m12() + in.y() * m_matrix.m22() + m_matrix.dy();
00170     out.setX( x );
00171     out.setY( y );
00172 }
00173 
00174 void ScPainterEx_Ps2::transformPoints( const FPoint* ArrayIn, FPoint* ArrayOut, uint length )
00175 {
00176     for( uint i = 0; i < length; i++ )
00177     {
00178         transformPoint( ArrayIn[i], ArrayOut[i] );
00179     }
00180 }
00181 
00182 void ScPainterEx_Ps2::translate( double x, double y )
00183 {
00184     m_matrix.translate(x, y);
00185 }
00186 
00187 void ScPainterEx_Ps2::rotate( double r )
00188 {
00189     m_matrix.rotate(r);
00190 }
00191 
00192 void ScPainterEx_Ps2::scale( double x, double y )
00193 {
00194     m_matrix.scale(x, y);
00195 }
00196 
00197 void ScPainterEx_Ps2::moveTo( const double &x, const double &y )
00198 {
00199     FPoint pp( x, y );
00200     transformPoint( pp, pp );
00201     m_stream << QString("%1 %2 moveto\n").arg(pp.x()).arg(pp.y());
00202 }
00203 
00204 void ScPainterEx_Ps2::lineTo( const double &x, const double &y )
00205 {
00206     FPoint pp( x, y );
00207     transformPoint( pp, pp );
00208     m_stream << QString("%1 %2 lineto\n").arg(pp.x()).arg(pp.y());
00209 }
00210 
00211 void ScPainterEx_Ps2::curveTo( FPoint p1, FPoint p2, FPoint p3 )
00212 {
00213     FPoint pps[3];
00214     pps[0].setXY( p1.x(), p1.y() );
00215     pps[1].setXY( p2.x(), p2.y() );
00216     pps[2].setXY( p3.x(), p3.y() );
00217     transformPoints( pps, pps, 3 );
00218     m_stream << QString("%1 %2 %3 %4 %5 %6 curveto\n").arg(pps[0].x()).arg(pps[0].y()).arg(pps[1].x()).arg(pps[1].y()).arg(pps[2].x()).arg(pps[2].y());
00219 }
00220 
00221 void ScPainterEx_Ps2::newPath()
00222 {
00223    m_stream << "newpath\n";
00224    //pathIsClosed = false;
00225 }
00226 
00227 void ScPainterEx_Ps2::closePath()
00228 {
00229     m_stream << "closepath\n";
00230     m_pathIsClosed = true;
00231 }
00232 
00233 void ScPainterEx_Ps2::setFillRule( bool fillRule )
00234 {
00235     m_fillRule = fillRule;
00236 }
00237 
00238 void ScPainterEx_Ps2::setFillMode( int fill )
00239 {
00240     m_fillMode = fill;
00241 }
00242 
00243 void ScPainterEx_Ps2::setGradient(VGradientEx::Type mode, FPoint orig, FPoint vec, FPoint foc)
00244 {
00245     m_fillGradient.setType(mode);
00246     m_fillGradient.setOrigin(orig);
00247     m_fillGradient.setVector(vec);
00248     m_fillGradient.setFocalPoint(foc);
00249 }
00250 
00251 void ScPainterEx_Ps2::setPattern( ScPattern* pattern, QMatrix& patternTransform )
00252 {
00253     m_pattern = pattern;
00254     m_patternTransform = patternTransform;
00255 }
00256 
00257 void ScPainterEx_Ps2::fillTextPath()
00258 {
00259     drawVPath( 0 );
00260 }
00261 
00262 void ScPainterEx_Ps2::strokeTextPath()
00263 {
00264     if( m_lineWidth == 0 )
00265         return;
00266     drawVPath( 1 );
00267 }
00268 
00269 void ScPainterEx_Ps2::fillPath()
00270 {
00271     if(!m_pathIsClosed)
00272         closePath();
00273     if( m_fillMode != 0)
00274         drawVPath( 0 );
00275 }
00276 
00277 void ScPainterEx_Ps2::strokePath()
00278 {
00279     if( m_lineWidth == 0 )
00280         return;
00281     save();
00282     if(!m_pathIsClosed)
00283         closePath();
00284     drawVPath( 1 );
00285     restore();
00286 }
00287 
00288 ScColorShade ScPainterEx_Ps2::pen()
00289 {
00290     return m_strokeColor;
00291 }
00292 
00293 ScColorShade ScPainterEx_Ps2::brush()
00294 {
00295     return m_fillColor;
00296 }
00297 
00298 void ScPainterEx_Ps2::setPen( const ScColorShade &c )
00299 {
00300     m_strokeColor = c;
00301 }
00302 
00303 void ScPainterEx_Ps2::setPen( const ScColorShade &c, double w, Qt::PenStyle st, Qt::PenCapStyle ca, Qt::PenJoinStyle jo )
00304 {
00305     m_offset = 0;
00306     m_strokeColor = c;
00307     m_lineWidth = w;
00308     m_lineEnd = ca;
00309     m_lineJoin = jo;
00310     double Dt = qMax(2*w, 1.0);
00311     double Da = qMax(6*w, 1.0);
00312     m_array.clear();
00313     if (st == Qt::DashLine)
00314         m_array << Da << Dt;
00315     else if (st == Qt::DotLine)
00316         m_array << Dt;
00317     else if (st == Qt::DashDotLine)
00318         m_array << Da << Dt << Dt << Dt;
00319     else if (st == Qt::DashDotDotLine)
00320         m_array << Da << Dt << Dt << Dt << Dt << Dt; 
00321 }
00322 
00323 void ScPainterEx_Ps2::setLineWidth( double w )
00324 {
00325     m_lineWidth = w;
00326 }
00327 
00328 void ScPainterEx_Ps2::setPenOpacity( double op )
00329 {
00330     m_strokeTrans = op;
00331 }
00332 
00333 void ScPainterEx_Ps2::setDash(const QList<double>& array, double ofs)
00334 {
00335     m_array = array;
00336     m_offset = ofs;
00337 }
00338 
00339 void ScPainterEx_Ps2::setBrush( const ScColorShade &c )
00340 {
00341     m_fillColor = c;
00342 }
00343 
00344 void ScPainterEx_Ps2::setBrushOpacity( double op )
00345 {
00346     m_fillTrans = op;
00347 }
00348 
00349 void ScPainterEx_Ps2::setOpacity( double op )
00350 {
00351     m_fillTrans = op;
00352     m_strokeTrans = op;
00353 }
00354 
00355 void ScPainterEx_Ps2::setFont( const QFont &f)
00356 {
00357     m_font = f;
00358 }
00359 
00360 QFont ScPainterEx_Ps2::font()
00361 {
00362     return m_font;
00363 }
00364 
00365 void ScPainterEx_Ps2::save()
00366 {
00367     m_stack.push( m_matrix );
00368     m_stream << "gsave\n";
00369 }
00370 
00371 void ScPainterEx_Ps2::restore()
00372 {
00373     m_matrix = m_stack.pop();
00374     m_stream << "grestore\n";
00375 }
00376 
00377 void ScPainterEx_Ps2::setRasterOp( int   )
00378 {
00379 }
00380 
00381 void ScPainterEx_Ps2::drawVPath( int mode )
00382 {
00383     save();
00384     if (mode == 0)
00385     {
00386         if (m_fillMode == ScPainterExBase::Gradient)
00387             drawGradient( m_fillGradient );
00388         else
00389             putColor( m_fillColor, true );
00390     }
00391     else
00392     {
00393         double m11 = m_matrix.m11();
00394         double m12 = m_matrix.m12();
00395         double m21 = m_matrix.m21();
00396         double m22 = m_matrix.m22();
00397         double norm2 = m11 * m11 + m12 * m12 + m21 * m21 + m22 * m22;
00398         double penScale = sqrt(norm2 /2.0);
00399         double penWidth = (int) (m_lineWidth * penScale);
00400         m_stream << QString("%1 setlinewidth\n").arg(penWidth);
00401 
00402         m_stream << "[";
00403         for( int i = 0; i < m_array.count();++ i )
00404         {
00405             m_stream << QString("%1").arg(m_array[i]) << " ";
00406         }
00407         m_stream << "]";
00408         m_stream << " 0 setdash\n";
00409 
00410         if( m_lineEnd == Qt::RoundCap )
00411             m_stream << "1 setlinecap\n";
00412         else if( m_lineEnd == Qt::SquareCap )
00413             m_stream << "2 setlinecap\n";
00414         else if( m_lineEnd == Qt::FlatCap )
00415             m_stream << "0 setlinecap\n";
00416         else
00417             m_stream << "0 setlinecap\n";
00418 
00419         if( m_lineJoin == Qt::RoundJoin )
00420             m_stream << "1 setlinejoin\n";
00421         else if( m_lineJoin == Qt::BevelJoin )
00422             m_stream << "2 setlinejoin\n";
00423         else if( m_lineJoin == Qt::MiterJoin )
00424             m_stream << "0 setlinejoin\n";
00425         else
00426             m_stream << "0 setlinejoin\n";
00427 
00428         putColor(m_strokeColor, false);
00429     }
00430     restore();
00431 }
00432 
00433 void ScPainterEx_Ps2::setClipPath()
00434 {
00435     //TODO eoclip or clip?
00436     m_stream << "clip newpath\n";
00437     m_clipBBox = m_pathBBox;
00438 }
00439 
00440 void ScPainterEx_Ps2::putColor( ScColorShade& colorShade, bool doFill )
00441 {
00442     ColorMode colorMode = m_colorMode;
00443     int r = 0, g = 0, b = 0, gray = 0;
00444     int c = 0, m = 0, y = 0, k = 0;
00445     if ( m_options.toGray )
00446     {
00447         RGBColor rgb;
00448         ScColorEngine::getShadeColorRGB(colorShade.color, m_options.document, rgb, colorShade.shade);
00449         rgb.getValues(r, g, b);
00450         gray = qRound(0.3 * r + 0.59 * g + 0.11 * b);
00451         if ( doFill && m_fillRule )
00452             m_stream << QString("%1 setgray eofill\n").arg(gray/255.0);
00453         else if ( doFill )
00454             m_stream << QString("%1 setgray fill\n").arg(gray/255.0);
00455         else
00456             m_stream << QString("%1 setgray stroke\n").arg(gray/255.0);
00457         return;
00458     }
00459     else if ( m_options.hProfile && m_options.rgbToOutputColorTransform && m_options.cmykToOutputColorTransform)
00460     {
00461         DWORD colorIn[4];
00462         DWORD colorOut[4];
00463         cmsHTRANSFORM cmsTranform = NULL;
00464         if( colorShade.color.getColorModel() == colorModelRGB )
00465         {
00466             RGBColor rgb;
00467             ScColorEngine::getShadeColorRGB(colorShade.color, m_options.document, rgb, colorShade.shade);
00468             colorIn[0] = rgb.r;
00469             colorIn[1] = rgb.g;
00470             colorIn[2] = rgb.b;
00471             colorMode = rgbMode;
00472             cmsTranform = m_options.rgbToOutputColorTransform;
00473         } 
00474         else
00475         {
00476             CMYKColor cmyk;
00477             ScColorEngine::getShadeColorCMYK(colorShade.color, m_options.document, cmyk, colorShade.shade);
00478             colorIn[0] = cmyk.c;
00479             colorIn[1] = cmyk.m;
00480             colorIn[2] = cmyk.y;
00481             colorIn[3] = cmyk.k;
00482             colorMode = cmykMode;
00483             cmsTranform = m_options.cmykToOutputColorTransform;
00484         }
00485         cmsDoTransform( cmsTranform, colorIn, colorOut, 1 );
00486         if (static_cast<int>(cmsGetColorSpace(m_options.hProfile)) == icSigRgbData)
00487         {
00488             r = colorOut[0] / 257;
00489             g = colorOut[1] / 257;
00490             b = colorOut[2] / 257;
00491             colorMode = rgbMode;
00492         }
00493         else if (static_cast<int>(cmsGetColorSpace(m_options.hProfile)) == icSigCmykData)
00494         {
00495             c = colorOut[0] / 257;
00496             m = colorOut[1] / 257;
00497             y = colorOut[2] / 257;
00498             k = colorOut[3] / 257;
00499             colorMode = cmykMode;
00500         }
00501     }
00502     else if ( m_colorMode == rgbMode )
00503     {
00504         RGBColor rgb;
00505         colorMode = rgbMode;
00506         ScColorEngine::getShadeColorRGB(colorShade.color, m_options.document, rgb, colorShade.shade);
00507         rgb.getValues(r, g, b);
00508     }
00509     else if ( m_colorMode == cmykMode )
00510     {
00511         CMYKColor cmyk;
00512         colorMode = cmykMode;
00513         ScColorEngine::getShadeColorCMYK(colorShade.color, m_options.document, cmyk, colorShade.shade);
00514         cmyk.getValues(c, m, y, k);
00515     }
00516 
00517     // Finally output to file
00518     if ( colorMode == rgbMode )
00519     {
00520         if ( doFill && m_fillRule )
00521             m_stream << QString("%1 %2 %3 setrgbcolor eofill\n").arg(r/255.0).arg(g/255.0).arg(b/255.0);
00522         else if ( doFill )
00523             m_stream << QString("%1 %2 %3 setrgbcolor fill\n").arg(r/255.0).arg(g/255.0).arg(b/255.0);
00524         else
00525             m_stream << QString("%1 %2 %3 setrgbcolor stroke\n").arg(r/255.0).arg(g/255.0).arg(b/255.0);            
00526     }
00527     else if ( colorMode == cmykMode )
00528     {
00529         QString colstr1 = QString("%1 %2 %3 %4 setcmykcolor").arg(c/255.0).arg(m/255.0).arg(y/255.0).arg(k/255.0);
00530         if ( doFill && m_fillRule )
00531             m_stream << colstr1 << " eofill\n";
00532         else if ( doFill )
00533             m_stream << colstr1 << " fill\n";
00534         else
00535             m_stream << colstr1 << " stroke\n"; 
00536     }
00537 }
00538 
00539 void ScPainterEx_Ps2::drawImage( ScImage *image, ScPainterExBase::ImageMode mode )
00540 {
00541     bool rgbMode = (mode == ScPainterExBase::rgbImages || mode == ScPainterExBase::rgbProofImages);
00542     bool rgbPicture = rgbMode || (mode == ScPainterExBase::rawImages && image->imgInfo.colorspace == ColorSpaceRGB);
00543     bool cmykPicture = (mode == ScPainterExBase::cmykImages || (mode == ScPainterExBase::rawImages && image->imgInfo.colorspace == ColorSpaceCMYK)); 
00544 
00545     if( rgbPicture )
00546         drawRGBImage_ps2( image );
00547     else if( cmykPicture )
00548         drawCMYKImage_ps2( image );
00549     else
00550         qDebug( "ScPainterEx_Ps2::drawImage() : unknown image type" );
00551 }
00552 
00553 void ScPainterEx_Ps2::drawRGBImage_ps2( ScImage *image )
00554 {
00555     save();
00556     QString sc("[%1 %2 %3 %4 %5 %6] concat\n");
00557     m_stream << sc.arg(m_matrix.m11()).arg(m_matrix.m12()).arg(m_matrix.m21()).arg(m_matrix.m22()).arg(m_matrix.dx()).arg(m_matrix.dy());
00558     m_stream << QString("%1 %2 scale\n").arg(image->width()).arg(image->height());
00559     m_stream << "/DeviceRGB setcolorspace\n";
00560     if (hasAlphaChannel(image))
00561     {
00562         QImage imgTemp = image->qImage();
00563         QImage mask = imgTemp.createAlphaMask();
00564         if (m_encoding == Ascii85Encoding)
00565         {
00566             m_stream << "currentfile /ASCII85Decode filter /ReusableStreamDecode filter\n";
00567             writeRGBImageToStream_Ascii85(image);
00568         }
00569         else
00570         {
00571             m_stream << "currentfile /ASCIIHexDecode filter /ReusableStreamDecode filter\n";
00572             writeRGBImageToStream_AsciiHex(image);
00573         }
00574         m_stream << "/myImage exch def\n";
00575         m_stream << "currentfile /ASCIIHexDecode filter /ReusableStreamDecode filter\n";
00576         writeMaskToStream(&mask);
00577         m_stream << "/myMask exch def\n";
00578         m_stream << QString("<<\n");
00579         m_stream << QString("    /PaintType   1\n");
00580         m_stream << QString("    /PatternType 1\n");
00581         m_stream << QString("    /TilingType  3\n");
00582         m_stream << QString("    /BBox        [ 0 0 1 1 ]\n");
00583         m_stream << QString("    /XStep       2\n");
00584         m_stream << QString("    /YStep       2\n");
00585         m_stream << QString("    /PaintProc   {\n");
00586         m_stream << QString("        pop\n");
00587         m_stream << QString("        0 0 0 setrgbcolor\n");
00588         m_stream << QString("        <<\n");
00589         m_stream << QString("            /ImageType 1\n");
00590         m_stream << QString("            /Width     %1\n").arg(image->width());
00591         m_stream << QString("            /Height    %1\n").arg(image->height());
00592         m_stream << QString("            /ImageMatrix [ %1 0 0 %2 0 0 ]\n").arg(image->width()).arg(image->height());
00593         m_stream << QString("            /BitsPerComponent 8\n");
00594         m_stream << QString("            /Decode [0 1 0 1 0 1]\n");
00595         m_stream << QString("            /DataSource myImage\n");
00596         m_stream << QString("        >>\n");
00597         m_stream << QString("        image\n");
00598         m_stream << QString("    }\n");
00599         m_stream << QString(">> matrix makepattern setpattern\n");
00600         m_stream << QString("<<\n");
00601         m_stream << QString("    /ImageType 1\n");
00602         m_stream << QString("    /Width %1 \n").arg(image->width());
00603         m_stream << QString("    /Height %1 \n").arg(image->height());
00604         m_stream << QString("    /BitsPerComponent 1\n");
00605         m_stream << QString("    /Decode [1 0]\n");
00606         m_stream << QString("    /ImageMatrix [ %1 0 0 %2 0 0 ]\n").arg(image->width()).arg(image->height());
00607         m_stream << QString("    /DataSource myMask\n");
00608         m_stream << QString(">>\n");
00609         m_stream << QString("imagemask\n");
00610     }
00611     else
00612     {
00613         m_stream << QString("<<\n");
00614         m_stream << QString("    /ImageType 1\n");
00615         m_stream << QString("    /Width %1\n").arg(image->width());
00616         m_stream << QString("    /Height %1\n").arg(image->height());
00617         m_stream << QString("    /ImageMatrix [ %1 0 0 %2 0 0 ]\n").arg(image->width()).arg(image->height());
00618         m_stream << QString("    /Decode [0 1 0 1 0 1]\n");
00619         m_stream << QString("    /BitsPerComponent 8\n");
00620         //TODO case where compression is available
00621         if (m_encoding == Ascii85Encoding)
00622         {
00623             m_stream << QString("    /DataSource currentfile /ASCII85Decode filter\n");
00624             m_stream << QString(">>\n");
00625             m_stream << "image\n";
00626             writeRGBImageToStream_Ascii85(image);
00627         }
00628         else
00629         {
00630             m_stream << QString("    /DataSource currentfile /ASCIIHexDecode filter\n");
00631             m_stream << QString(">>\n");
00632             m_stream << "image\n";
00633             writeRGBImageToStream_AsciiHex(image);
00634         }
00635     }
00636     restore();
00637 }
00638 
00639 void ScPainterEx_Ps2::drawCMYKImage_ps2( ScImage *image )
00640 {
00641     save();
00642     QString sc("[%1 %2 %3 %4 %5 %6] concat\n");
00643     m_stream << sc.arg(m_matrix.m11()).arg(m_matrix.m12()).arg(m_matrix.m21()).arg(m_matrix.m22()).arg(m_matrix.dx()).arg(m_matrix.dy());
00644     m_stream << QString("%1 %2 scale\n").arg(image->width()).arg(image->height());
00645     m_stream << "/DeviceCMYK setcolorspace\n";
00646     // TODO case where image have a mask
00647     bool haveMask = false;
00648     if (haveMask)
00649     {
00650 
00651     }
00652     else
00653     {
00654         m_stream << "<<\n";
00655         m_stream << QString("    /ImageType 1\n");
00656         m_stream << QString("    /Width %1\n").arg(image->width());
00657         m_stream << QString("    /Height %1\n").arg(image->height());
00658         m_stream << QString("    /ImageMatrix [ %1 0 0 %2 0 0 ]\n").arg(image->width()).arg(image->height());
00659         m_stream << QString("    /Decode [0 1 0 1 0 1 0 1]\n");
00660         m_stream << QString("    /BitsPerComponent 8\n");
00661         //TODO case where compression is available
00662         if (m_encoding == Ascii85Encoding)
00663         {
00664             m_stream << QString("    /DataSource currentfile /ASCII85Decode filter\n");
00665             m_stream << QString(">>\n");
00666             m_stream << "image\n";
00667             writeCMYKImageToStream_Ascii85(image);
00668         }
00669         else
00670         {
00671             m_stream << QString("    /DataSource currentfile /ASCIIHexDecode filter\n");
00672             m_stream << QString(">>\n");
00673             m_stream << "image\n";
00674             writeCMYKImageToStream_AsciiHex(image);
00675         }
00676     }
00677     restore();
00678 }
00679 
00680 bool ScPainterEx_Ps2::hasAlphaChannel( ScImage* image )
00681 {
00682     bool   hasAlpha = false;
00683     int    width = image->width();
00684     int    height = image->height();
00685     for( int y = 0; y < height; y++ )
00686     {
00687         QRgb* imageBits = (QRgb*)(image->qImage().scanLine(y));
00688         for( int x = 0; x < width; ++x )
00689         {
00690             if( qAlpha(*imageBits) != 255 )
00691             {
00692                 hasAlpha = true;
00693                 break;
00694             }
00695             imageBits++;
00696         }
00697     }
00698     return hasAlpha;
00699 }
00700 
00701 void ScPainterEx_Ps2::writeMaskToStream( QImage* image )
00702 {
00703     int    length = 0;
00704     unsigned char bits;
00705     int    width = image->width() / 8;
00706     int    height = image->height();
00707     if ((image->width() % 8) != 0)
00708         width++;
00709     for( int y = 0; y < height; ++y )
00710     {
00711         unsigned char* imageBits = image->scanLine(y);
00712         for( int x = 0; x < width; x++ )
00713         {
00714             length++;
00715             bits = imageBits[x];
00716             m_stream << toHex(bits);
00717             if ( (length % 49) == 0 )
00718                 m_stream << "\n";
00719         }
00720     }
00721     m_stream << "\n>\n";
00722 }
00723 
00724 void ScPainterEx_Ps2::writeRGBImageToStream_Ascii85( ScImage* image )
00725 {
00726     int  cindex;
00727     int  pending = 0, written = 0;
00728     bool allZero  = true;
00729     unsigned char  four_tuple[4];
00730     const char* ascii85;
00731     quint32 value;
00732 
00733     int width = image->width();
00734     int height = image->height();
00735     for( int y = 0; y < height; ++y )
00736     {
00737         QRgb* imageBits = (QRgb*)(image->qImage().scanLine(y));
00738         for( int x = 0; x < width; ++x )
00739         {
00740             cindex = 0;
00741             while (cindex < 3)
00742             {
00743                 if (cindex == 0)
00744                     four_tuple[pending++] = (uchar) qRed(*imageBits);
00745                 else if (cindex == 1)
00746                     four_tuple[pending++] = (uchar) qGreen(*imageBits);
00747                 else if (cindex == 2)
00748                     four_tuple[pending++] = (uchar) qBlue(*imageBits);
00749                 if (pending == 4) 
00750                 {
00751                     value   = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3];
00752                     ascii85 = toAscii85(value, allZero);
00753                     if (allZero)
00754                         m_stream << "z";
00755                     else
00756                         m_stream << ascii85;
00757                     written += ((allZero) ? 1 : 5);
00758                     if (written > 75)
00759                     {
00760                         m_stream << "\n";
00761                         written = 0;
00762                     }
00763                     pending = 0;
00764                 }
00765                 ++cindex;
00766             }
00767             
00768         }
00769     }
00770     if (pending) 
00771     {
00772         unsigned char five_tuple[6];
00773         memset (four_tuple + pending, 0, 4 - pending);
00774         value   = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3];
00775         ascii85 = toAscii85(value, allZero);
00776         memcpy (five_tuple, ascii85, 5);
00777         five_tuple[pending + 1] = 0;
00778         m_stream << (const char*) five_tuple;
00779     }
00780     m_stream << "~>\n";
00781 }
00782 
00783 void ScPainterEx_Ps2::writeRGBImageToStream_AsciiHex ( ScImage* image )
00784 {
00785     int  length = 0;
00786     int  width = image->width();
00787     int  height = image->height();
00788     for( int y = 0; y < height; ++y )
00789     {
00790         QRgb* imageBits = (QRgb*)(image->qImage().scanLine(y));
00791         for( int x = 0; x < width; ++x )
00792         {
00793             length++;
00794             uchar r = (uchar) qRed(*imageBits);
00795             m_stream << toHex(r);
00796             uchar g = (uchar) qGreen(*imageBits);
00797             m_stream << toHex(g);
00798             uchar b = (uchar) qBlue(*imageBits);
00799             m_stream << toHex(b);
00800             if ( (length % 17) == 0 )
00801                 m_stream << "\n";
00802             imageBits++;
00803         }
00804     }
00805     m_stream << "\n>\n";
00806 }
00807 
00808 void ScPainterEx_Ps2::writeCMYKImageToStream_Ascii85( ScImage* image )
00809 {
00810     int  written = 0;
00811     bool allZero  = true;
00812     unsigned char  four_tuple[4];
00813     const char* ascii85;
00814     quint32 value;
00815 
00816     int width = image->width();
00817     int height = image->height();
00818     for( int y = 0; y < height; y++ )
00819     {
00820         QRgb* imageBits = (QRgb*)(image->qImage().scanLine(y));
00821         for( int x = 0; x < width; x++ )
00822         {
00823             four_tuple[0] = (uchar) qRed(*imageBits);
00824             four_tuple[1] = (uchar) qGreen(*imageBits);
00825             four_tuple[2] = (uchar) qBlue(*imageBits);
00826             four_tuple[3] = (uchar) qAlpha(*imageBits);
00827             value   = four_tuple[0] << 24 | four_tuple[1] << 16 | four_tuple[2] << 8 | four_tuple[3];
00828             ascii85 = toAscii85(value, allZero);
00829             if (allZero)
00830                 m_stream << "z";
00831             else
00832                 m_stream << ascii85;
00833             written += ((allZero) ? 1 : 5);
00834             if (written > 75)
00835             {
00836                 m_stream << "\n";
00837                 written = 0;
00838             }
00839             imageBits++;
00840         }
00841     }
00842     m_stream << "~>\n";
00843 }
00844 
00845 void ScPainterEx_Ps2::writeCMYKImageToStream_AsciiHex( ScImage* image )
00846 {
00847     int length = 0;
00848     int width = image->width();
00849     int height = image->height();
00850     for( int y = 0; y < height; ++y )
00851     {
00852         QRgb* imageBits = (QRgb*)(image->qImage().scanLine(y));
00853         for( int x = 0; x < width; ++x )
00854         {
00855             length++;
00856             uchar c = (uchar) qRed(*imageBits);
00857             m_stream << toHex(c);
00858             uchar m = (uchar) qGreen(*imageBits);
00859             m_stream << toHex(m);
00860             uchar y = (uchar) qBlue(*imageBits);
00861             m_stream << toHex(y);
00862             uchar k = (uchar) qAlpha(*imageBits);
00863             m_stream << toHex(k);
00864             if ( (length % 13) == 0 )
00865                 m_stream << "\n";
00866             imageBits++;
00867         }
00868     }
00869     m_stream << "\n>\n";
00870 }
00871 
00872 void ScPainterEx_Ps2::setupPolygon(FPointArray *points, bool closed)
00873 {
00874     bool nPath = true;
00875     FPoint np, np1, np2, np3;
00876     if (points->size() > 3)
00877     {
00878         newPath();
00879         for (uint poi=0; poi<points->size()-3; poi += 4)
00880         {
00881             if (points->point(poi).x() > 900000)
00882             {
00883                 nPath = true;
00884                 continue;
00885             }
00886             if (nPath)
00887             {
00888                 np = points->point(poi);
00889                 // TODO startfigure needed?
00890                 moveTo( np.x(), np.y() );
00891                 nPath = false;
00892             }
00893             np = points->point(poi);
00894             np1 = points->point(poi+1);
00895             np2 = points->point(poi+3);
00896             np3 = points->point(poi+2);
00897             if ((np == np1) && (np2 == np3))
00898                 lineTo( np3.x(), np3.y() );
00899             else
00900                 curveTo(np1, np2, np3);
00901         }
00902         if (closed)
00903         {
00904             closePath();
00905             m_drawingClosedPath = true;
00906         }
00907     }
00908     getPathBoundingBox( points, m_pathBBox );
00909 }
00910 
00911 void ScPainterEx_Ps2::setupTextPolygon(FPointArray *points)
00912 {
00913     bool nPath = true;
00914     FPoint np, np1, np2, np3;
00915     if (points->size() > 3)
00916     {
00917         newPath();
00918         for (uint poi=0; poi<points->size()-3; poi += 4)
00919         {
00920             if (points->point(poi).x() > 900000)
00921             {
00922                 nPath = true;
00923                 continue;
00924             }
00925             if (nPath)
00926             {
00927                 np = points->point(poi);
00928                 // TODO closefigure / startfigure needed?
00929                 moveTo( np.x(), np.y() );
00930                 nPath = false;
00931             }
00932             np.setXY( points->point(poi).x(), points->point(poi).y() );
00933             np1.setXY( points->point(poi+1).x(), points->point(poi+1).y() );
00934             np2.setXY( points->point(poi+3).x(), points->point(poi+3).y() );
00935             np3.setXY( points->point(poi+2).x(), points->point(poi+2).y() );
00936             if ((np == np1) && (np2 == np3))
00937                 lineTo( np3.x(), np3.