void YZPrinter::doPrint( ) { const double fontsize = 10.0; PSDoc *doc = PS_new(); if (!doc) return ; QByteArray p = m_path.toLatin1(); PS_open_file(doc, p.data()); PS_set_info(doc, "Creator", "Yzis"); PS_set_info(doc, "Author", ""); PS_set_info(doc, "Title", p.data()); // Set so it'll fit on both A4 and letter paper; // some of us live in the US, with archaic paper sizes. ;-) PS_set_info(doc, "BoundingBox", "0 0 596 792"); int font; font = PS_findfont(doc, "Fixed", "", 0); dbg() << "findfont returned " << font << endl; if ( !font ) return ; //no font => abort QPrinter lpr(QPrinter::PrinterResolution); QPainter p( &lpr ); QFont f( "fixed" ); f.setFixedPitch( true ); f.setStyleHint( QFont::TypeWriter ); p.setFont( f ); unsigned int height = lpr.height(); unsigned int width = lpr.width(); unsigned int linespace = p.fontMetrics().lineSpacing(); unsigned int maxwidth = p.fontMetrics().maxWidth(); p.end(); PS_set_value(doc, "leading", linespace); unsigned int clipw = width / maxwidth - 1; unsigned int cliph = height / linespace - 1; unsigned int oldLinesVis = mView->getLinesVisible( ); unsigned int oldColumnsVis = mView->getColumnsVisible( ); //should be current's view setting no ? XXX bool number = mView->getLocalBooleanOption( "number" ); unsigned int marginLeft = 0; double red, green, blue; if ( number ) { marginLeft = ( 2 + QString::number( mView->buffer()->lineCount() ).length() ); } YOptionValue* ov_wrap = mView->getLocalOption( "wrap" ); bool oldWrap = ov_wrap->boolean(); ov_wrap->setBoolean( true ); mView->setVisibleArea( clipw - marginLeft, cliph, false ); unsigned int totalHeight = mView->drawTotalHeight(); mView->setVisibleArea( clipw - marginLeft, totalHeight, false ); mView->initDraw( 0, 0, 0, 0 ); unsigned int lastLineNumber = 0; unsigned int pageNumber = 0; QRect titleRect( 0, 0, width, linespace + linespace / 2 ); unsigned int topY = titleRect.height() + linespace; unsigned int curY = topY; unsigned int curX; cliph = ( height - topY ) / linespace; int nbPages = totalHeight / cliph + ( totalHeight % cliph ? 1 : 0 ); PS_begin_page(doc, 596, 792); PS_setfont(doc, font, fontsize); PS_set_parameter(doc, "hyphenation", "false"); PS_set_parameter(doc, "linebreak", "true"); PS_set_parameter(doc, "parbreak", "false"); PS_set_value(doc, "parindent", 0.0); PS_set_value(doc, "numindentlines", 0.0); while ( mView->drawNextLine( ) ) { if ( curY == topY ) { if ( pageNumber ) { PS_end_page(doc); PS_begin_page(doc, 596, 792); PS_setfont(doc, font, fontsize); PS_set_value(doc, "leading", linespace); } ++pageNumber; convertColor(Qt::black, red, green, blue); PS_setcolor(doc, "fillstroke", "rgb", red, green, blue, 0.0); QByteArray n = ( ' ' + mView->buffer()->fileName() ).toLatin1(); PS_show_boxed(doc, n.data(), titleRect.x(), titleRect.y(), titleRect.width(), titleRect.height(), "left", ""); QByteArray nb = ( QString::number( pageNumber ) + '/' + QString::number( nbPages ) + ' ' ).toLatin1(); PS_show_boxed(doc, nb.data(), titleRect.x(), titleRect.y(), titleRect.width(), titleRect.height(), "right", ""); } if ( number ) { unsigned int lineNumber = mView->drawLineNumber(); if ( lineNumber != lastLineNumber ) { //p.setPen( Qt::gray ); convertColor(Qt::gray, red, green, blue); PS_setcolor(doc, "fillstroke", "rgb", red, green, blue, 0.0); PS_moveto(doc, 0, curY); QByteArray m = QString::number( lineNumber ).rightJustified( marginLeft - 1, ' ' ).toLatin1(); PS_show(doc, m.data()); lastLineNumber = lineNumber; } } curX = marginLeft * maxwidth; while ( mView->drawNextCol( ) ) { QColor c = mView->drawColor( ); if ( c.isValid() && c != Qt::white ) convertColor(mView->drawColor(), red, green, blue); else convertColor(Qt::black, red, green, blue); PS_setcolor(doc, "fillstroke", "rgb", red, green, blue, 0.0); char buf[2] = { 0, 0 }; buf[0] = mView->drawChar().toLatin1(); PS_show_xy(doc, buf, curX, curY); curX += mView->drawLength( ) * maxwidth; } curY += linespace * mView->drawHeight(); if ( curY >= cliph * linespace + topY ) { // draw Rect convertColor(Qt::black, red, green, blue); PS_setcolor(doc, "fillstroke", "rgb", red, green, blue, 0.0); PS_rect(doc, 0, 0, width, curY); if ( number ) { PS_moveto(doc, marginLeft*maxwidth - maxwidth / 2, titleRect.height()); PS_lineto(doc, marginLeft*maxwidth - maxwidth / 2, curY); } PS_moveto(doc, titleRect.x(), titleRect.height()); PS_lineto(doc, titleRect.width(), titleRect.height()); curY = topY; } } if ( curY != topY ) { // draw Rect convertColor(Qt::black, red, green, blue); PS_setcolor(doc, "fillstroke", "rgb", red, green, blue, 0.0); PS_rect(doc, 0, 0, width, curY); if ( number ) { PS_moveto(doc, marginLeft*maxwidth - maxwidth / 2, titleRect.height()); PS_lineto(doc, marginLeft*maxwidth - maxwidth / 2, curY); } PS_moveto(doc, titleRect.x(), titleRect.height()); PS_lineto(doc, titleRect.width(), titleRect.height()); } PS_end_page(doc); PS_deletefont(doc, font); PS_close(doc); PS_delete(doc); PS_shutdown(); ov_wrap->setBoolean( oldWrap ); mView->setVisibleArea( oldColumnsVis, oldLinesVis, false ); }
void pslibHacks() { # ifndef USE_PSLIB Warning("Warning: pslib support is mandatory for the PostScript driver to handle the following"); Warning(" keywords: [X,Y]OFFSET, SCALE_FACTOR, ENCAPSULATED"); # else PSDoc *ps = PS_new(); GDLGuard<PSDoc> psGuard( ps, PS_delete); if (ps == NULL) { Warning("Warning: pslib failed to allocate memory."); return; } FILE *fp = tmpfile(); // this creates a file which should be deleted automaticaly when it is closed FILEGuard fpGuard( fp, fclose); if (fp == NULL) { Warning("Warning: failed to create temporary PostScript file."); // PS_delete(ps); return; } if (PS_open_fp(ps, fp) == -1) { Warning("Warning: pslib failed to open a new PostScript file."); goto cleanup; } PS_set_parameter(ps, "imagereuse", "false"); PS_set_info(ps, "Title", "Graphics produced by GDL"); PS_set_info(ps, "Orientation", orient_portrait ? "Portrait" : "Landscape"); { struct utsname uts; uname(&uts); string tmp; tmp = "GDL Version " + string(VERSION) + ", " + string(uts.sysname) + " " + string(uts.machine); PS_set_info(ps, "Creator", tmp.c_str()); char* login = getlogin(); if (login == NULL) Warning("Warning: getlogin() failed!"); tmp = (login == NULL ? "?" : login) + string("@") + uts.nodename; PS_set_info(ps, "Author", tmp.c_str()); } //bug: PSLIB does not return the correct boundingbox, it forgets offx and offy. Try to get it //back (using pslib own code!)! char *bb; FILE *feps; char buffer[1024]; //largely sufficient int nbytes; feps=fopen(fileName.c_str(), "r"); nbytes=fread(buffer,sizeof(char),1023,feps); fclose(feps); buffer[1023]=0; bb = strstr(buffer, "%%BoundingBox:"); float offx, offy, width, height; if(bb) { bb += 15; sscanf(bb, "%f %f %f %f", &offx, &offy, &width, &height); } else { offx=0; offy=0; width=500; height=500; //silly values, will be replaced afterwards hopefully. } // TODO //psfont = PS_findfont(ps, "Helvetica", "", 0); //PS_setfont(ps, psfont, 8.0); char bbstr [20], offstr [20]; int bbXSize, bbYSize; { int bbXoff = XOffset*cm2in*dpi; int bbYoff = YOffset*cm2in*dpi; bbXSize = orient_portrait ? bbXoff + XPageSize*cm2in*dpi*scale : bbXoff + YPageSize*cm2in*dpi*scale; bbYSize = orient_portrait ? bbYoff + YPageSize*cm2in*dpi*scale : bbYoff + XPageSize*cm2in*dpi*scale; sprintf(bbstr,"%i %i %i %i",bbXoff,bbYoff,bbXSize,bbYSize); sprintf(offstr,"%i %i",bbXoff,bbYoff); PS_set_info(ps,"BoundingBox",bbstr); PS_begin_page(ps, bbXSize, bbYSize); { int psimage = PS_open_image_file(ps, "eps", fileName.c_str(), NULL, 0); if (psimage == 0) { Warning("Warning: pslib failed to load plPlot output file."); goto cleanup; } float scl = 0.98*min((bbXSize-bbXoff) / (width-offx), (bbYSize-bbYoff) / (height-offy) ); int margx = ((bbXSize-bbXoff) - scl*(width-offx))/2; int margy = ((bbYSize-bbYoff) - scl*(height-offy))/2; PS_place_image(ps, psimage, bbXoff-offx*scl + margx, bbYoff-offy*scl + margy, scl ); PS_close_image(ps, psimage); } PS_end_page(ps); PS_close(ps); } // Replace PageBoundingBox and CropBox and write contents to fileName { rewind(fp); FILE *fp_plplot = fopen(fileName.c_str(), "w"); FILEGuard fp_plplotGuard( fp_plplot, fclose); if (fp_plplot == NULL) { Warning("Warning: failed to open plPlot-generated file"); goto cleanup; } // When multiple pages are supported, PageBoundingBox and the cropbox // will appear more than once. Then this section will need to be redone. // Edit: change the two 0's after the PageBoundingBox string pbstr=string("%%PageBoundingBox: ")+offstr; // edits will be in the first 12288 bytes; add the length of offstr-3 const size_t buflen=12288 + pbstr.length()-22; //const size_t buflen=4096; char buff[buflen]; //do the first read: size_t cnt = fread(&buff, 1, 12288, fp); string sbuff; sbuff = string(buff); // find the PageBoundingBox statement size_t pos = sbuff.find("%%PageBoundingBox: 0 0"); if (pos != string::npos) { sbuff.replace(pos,22,pbstr); // will change the size of sbuff by offstr-3 cnt = cnt + pbstr.length()-22; } // PSlib outputs pdfmarks which resize the PDF to the size of the boundingbox // this is nice, but not IDL behaviour (and anyway, the two 0's are wrong) char mychar[60]; sprintf(mychar,"[ /CropBox [0 0 %i.00 %i.00] /PAGE pdfmark",bbXSize,bbYSize); string pdfstr=string(mychar); string pdfrepl(pdfstr.length(),' '); pos = sbuff.find(pdfstr); if (pos != string::npos) {sbuff.replace(pos,pdfstr.length(),pdfrepl);} // will not change size of sbuff // write the first buflen to file strcpy(buff,sbuff.c_str()); if (fwrite(&buff, 1, buflen, fp_plplot) < buflen) { Warning("Warning: failed to overwrite the plPlot-generated file with pslib output"); } // read the rest of fp and write to file while (true) { cnt = fread(&buff, 1, buflen, fp); if (!cnt) break; if (fwrite(&buff, 1, cnt, fp_plplot) < cnt) { Warning("Warning: failed to overwrite the plPlot-generated file with pslib output"); } } // fclose(fp_plplot); } cleanup: // PS_delete(ps); // fclose(fp); // this deletes the temporary file as well // PSlib changes locale - bug no. 3428043 # ifdef HAVE_LOCALE_H setlocale(LC_ALL, "C"); # endif # endif }