#include <iostream>
#include <fstream>
#include <stdexcept>
#include <LASi.h>

using namespace LASi;
using namespace std;

int main(const int argc, char* const argv[]) 
{

  ofstream strm;

  try {

    //
    // This is the Postscript document object:
    //
    PostscriptDocument doc;

    //double x, y;
    
    double xAdvance,yMinimum,yMaximum,lineSpacing,yDelta;

    /////////////////////////////////////////////////
    //
    // DOCUMENT HEADER:
    //
    // Here is where you put user-defined Postscript
    // procedures.  LASi's glyph procedures also end up
    // in the header of the final Postscript document:
    //
    /////////////////////////////////////////////////
    doc.osHeader() << "%%%%%%%%%%%%%%%             " << endl;
    doc.osHeader() << "%                           " << endl;
    doc.osHeader() << "% Unit metrics:             " << endl;
    doc.osHeader() << "%                           " << endl;
    doc.osHeader() << "%%%%%%%%%%%%%%%             " << endl;
    doc.osHeader() << "/inch {72 mul}      bind def" << endl;
    doc.osHeader() << "/cm {inch 2.54 div} bind def" << endl;
    doc.osHeader() << "/mm {cm 10 div}     bind def" << endl;

    /////////////////////////////////////////////////
    //
    // DOCUMENT BODY:
    //
    /////////////////////////////////////////////////
    
    //
    // The Vera font family is available from www.gnome.org
    // See http://www.unifont.org/fontguide/ for download site
    //
    doc.osBody() << setFont("Vera Sans",LASi::NORMAL_STYLE,LASi::BOLD) << setFontSize(30);
    doc.osBody() << "gsave" << endl;
    doc.osBody() << "2 cm 26 cm moveto" << endl;
    doc.osBody() << "0.61 0.22 0.10 setrgbcolor" << endl;
    doc.osBody() << show("L");
    doc.osBody() << "0.93 0.85 0.65 setrgbcolor" << endl;
    doc.osBody() << show("A");
    doc.osBody() << "0.83 0.58 0.32 setrgbcolor" << endl;
    doc.osBody() << show("S");
    doc.osBody() << "0.16 0.07 0.07 setrgbcolor" << endl;
    doc.osBody() << show("i");
    doc.osBody() << "grestore" << endl;
    
    //
    // Set the standard font that we are going to use for comments in the document:
    //    
    doc.osBody() << setFont("Vera Sans",LASi::ITALIC) << setFontSize(12);
    //
    // Determine a line spacing for the Vera Sans 12 point strings:
    // Be sure to pass a string to get_dimensions() that will have the
    // maximum ascenders and descenders that you will need for your text.
    // For example, for Latin text, at least one among "A", "X", "b", "d", and "k" 
    // should be maximally ascendant, while at least one among "g", "p", "q",
    // and "y" should be maximally descendant.
    //
    // For other languages and scripts, you would choose different strings
    // for fixing line spacing.  For a CTL script like Thai or Hindi, you
    // would definitely want to include vowels and other diacritic marks that
    // sit above or below consonants and would use a string like "ดูที่นี้" (Thai) or
    // "कि कु कू कै" (Devanagari).  For Arabic, you might have to decide
    // whether you are going to have vocalized or unvocalized text, since
    // vocalization will increase the required line spacing.
    //
    doc.get_dimensions("AXbdk gpqy",&lineSpacing);
    //
    // Define a Postscript procedure called "newLine" which will use "lineSpacing" for the increment:
    //
    doc.osHeader() << "/leftMargin        2 cm def" << endl;
    doc.osHeader() << "/verticalPosition 25 cm def" << endl;
    doc.osHeader() << "/verticalIncrement " << lineSpacing << " def" << endl;
    doc.osHeader() << "/newLine {" << endl;
    doc.osHeader() << " /verticalPosition verticalPosition verticalIncrement sub def" << endl;  
    doc.osHeader() << " leftMargin verticalPosition moveto" << endl;
    doc.osHeader() << "} bind def" << endl;
    
    doc.osBody() << "leftMargin verticalPosition moveto" << endl;
    doc.osBody() << show("LASi uses Pango's layout services to make laying out left-to-right") << endl;
    doc.osBody() << "newLine" << endl;
    doc.osBody() << show("and right-to-left text trivially easy:") << endl;

    //
    // You can always use the virtual "serif" or "sans" font
    // if you don't want to specify a specific font:
    //    
    doc.osBody() << setFont("serif") << setFontSize(22) << endl;
    //
    // Here we pass the full set of parameters to get dimensions:
    //
    doc.get_dimensions("Hello World! / שלום",&lineSpacing,&xAdvance,&yMinimum,&yMaximum);
    //
    // Draw a rectangle showing the bounding box of the string:
    //
    yDelta=yMaximum-yMinimum;
    doc.osBody() << "gsave" << endl;
    doc.osBody() << "newpath" << endl;
    doc.osBody() << "1 0 0 setrgbcolor" << endl;
    doc.osBody() << "2.5 cm 23.2 cm moveto" << endl;
    doc.osBody() << 0 << " " << yMinimum << " rmoveto " << endl;
    doc.osBody() << 0 << " " << yDelta << " rlineto "  << endl;
    doc.osBody() << xAdvance << " " << 0 << " rlineto "  << endl;
    doc.osBody() << 0 << " " << -yDelta << " rlineto " << endl;
    doc.osBody() << "closepath" << endl;
    doc.osBody() << "stroke" << endl;
    doc.osBody() << "grestore" << endl;
    //
    // Now print the string:
    //
    doc.osBody() << "2.5 cm 23.2 cm moveto" << endl;
    doc.osBody() << show("Hello World! / ") << show("שלום");//shalom

    doc.osBody() << setFont("Vera Sans",LASi::ITALIC) << setFontSize(12);
    doc.osBody() << "leftMargin 22 cm moveto" << endl;
    doc.osBody() << show("Scripts with complex layout requirements, such as Arabic and Thai, are supported:") << endl;

    /////////////////////////////////////////////////
    //
    // "ALEXANDRIA" IN ARABIC: الإسكندرية
    //
    /////////////////////////////////////////////////
    doc.osBody() << "gsave" << endl;
    doc.osBody() << "2.5 cm 20.5 cm moveto" << endl;
    //
    // The Ae_Cortoba font is available from arabeyes.org
    // See http://www.unifont.org/fontguide/ for download site
    //
    doc.osBody() << setFont("Ae_Cortoba") << setFontSize(22) << endl;
    doc.osBody() << "0.6 0.5 0.1 setrgbcolor" << endl;
    doc.osBody() << show("الإسكندرية");
    doc.osBody() << "grestore" << endl;

    /////////////////////////////////////////////////
    //
    // "UTHAITHANI" IN THAI: อุทัยธานี
    //
    /////////////////////////////////////////////////    
    doc.osBody() << "gsave" << endl;
    doc.osBody() << "2.5 cm 19 cm moveto" << endl;
    //
    // Garuda is part of the Thai national font set from NECTEC.
    // See http://www.unifont.org/fontguide/ for download site
    //    
    doc.osBody() << setFont("Garuda") << endl;
    doc.osBody() << setFontSize(30) << endl;
    doc.osBody() << "0.55 0.32 0.21 setrgbcolor" << endl;
    doc.osBody() << show("อุทัยธานี");
    doc.osBody() << "grestore" << endl;

    //
    // Move the vertical position down to 17.5 cm:
    //
    doc.osBody() << "/verticalPosition 17.5 cm def" << endl;
    doc.osBody() << setFont("Vera Sans",LASi::ITALIC) << setFontSize(12);
    doc.osBody() << "leftMargin verticalPosition moveto" << endl;
    doc.osBody() << show("LASi is based on Unicode, so you can produce documents containing virtually any") << endl;
    doc.osBody() << "newLine" << endl;
    doc.osBody() << show("of the world's scripts while still using familiar Postscript operators to manipulate") << endl;
    doc.osBody() << "newLine" << endl;
    doc.osBody() << show("text or graphic elements:") << endl;

    /////////////////////////////////////////////////
    //
    // "NAGANO PREFECTURE" IN JAPANESE: 長野県
    //
    // Here we demonstrate using the Postscript "rotate" command
    // to achieve a nice graphic layout effect and show how easy
    // it is to mix LASi's show() method with Postscript:
    //
    /////////////////////////////////////////////////
    doc.osBody() << "gsave" << endl;
    doc.osBody() << "4.0 cm 14.0 cm moveto" << endl;
    //
    // See http://www.unifont.org/fontguide/ for
    // the Bitstream Cyberbit ftp download site:
    //
    doc.osBody() << setFont("Bitstream Cyberbit") << setFontSize(22) << endl;
    doc.osBody() << "0.4 0.4 0.75 setrgbcolor" << endl;
    doc.osBody() << "45 rotate" << endl;
    doc.osBody() << show("長");
    doc.osBody() << "-15 rotate" << endl;    
    doc.osBody() << show("野");
    doc.osBody() << "-15 rotate" << endl;    
    doc.osBody() << show("県");
    doc.osBody() << "grestore" << endl;

    /////////////////////////////////////////////////
    //
    // "SAINT PETERSBURG" in Cyrillic: Санкт-Петербург
    //
    // Notice the anamorphic scaling just to demonstrate another
    // simple effect in Postscript:
    //
    /////////////////////////////////////////////////
    doc.osBody() << "gsave" << endl;
    doc.osBody() << setFont("Bitstream Cyberbit");
    doc.osBody() << "7.0 cm 14.2 cm moveto" << endl;
    doc.osBody() << "0.6 0.74 0.2 setrgbcolor" << endl;
    doc.osBody() << "0.65 1.75 scale" << endl;
    doc.osBody() << show("Санкт-Петербург");
    doc.osBody() << "grestore" << endl;
    
    /////////////////////////////////////////////////
    //
    // Bengali: First line from UN declaration des droits des hommes (en Bengali):
    //
    /////////////////////////////////////////////////
    doc.osBody() << "gsave" << endl;
    //
    // The Akaash Bengali font is 
    // available from http://savannah.nongnu.org/download/freebangfont/
    // See http://www.unifont.org/fontguide/ for
    // other Bengali font options:
    //
    doc.osBody() << setFont("Akaash");
    doc.osBody() << setFontSize(16);
    doc.osBody() << "6.0 cm 15.7 cm moveto" << endl;
    doc.osBody() << "0.6 0.44 0.42 setrgbcolor" << endl;
    doc.osBody() << show("সমস্ত মানুস স্বাধীনভাবে সমান মর্যাদা এবং অধিকার নিয়ে জন্মগ্রহন করে । ");
    doc.osBody() << "grestore" << endl;

    //
    // Move the vertical position down to 13.0 cm:
    //
    doc.osBody() << "/verticalPosition 13.0 cm def" << endl;
    doc.osBody() << setFont("Vera Sans",LASi::ITALIC) << setFontSize(12);
    doc.osBody() << "leftMargin verticalPosition moveto" << endl;
    doc.osBody() << show("Equally important, the complete repetoire of scientific and mathematical symbols") << endl;
    doc.osBody() << "newLine" << endl;
    doc.osBody() << show("in Unicode are also available to you:") << endl;

    /////////////////////////////////////////////////
    //
    // SOMETHING FROM MAXIMUM LIKELIHOOD STATISTICS: 
    //
    // To demonstrate a layout with scientific symbols:
    //
    /////////////////////////////////////////////////
    doc.osBody() << "gsave" << endl;
    doc.osBody() << "2.5 cm 10.9 cm moveto" << endl;
    doc.osBody() << setFontSize(22) << endl;
    doc.osBody() << "0.5 setgray" << endl;
    doc.osBody() << setFont("Bitstream Cyberbit") << endl;
    doc.osBody() << show("∴ ∂SS(δ) ∕ ∂δ ≡ 2Z′WX + 2(Z′WZδ)");
    doc.osBody() << "grestore" << endl;

    doc.osBody() << "showpage" << endl;

    /////////////////////////////////////////////////
    //
    // DOCUMENT FOOTER:
    //
    // Additional Postscript Document Structuring 
    // Conventions may go here:
    //
    /////////////////////////////////////////////////    
    doc.osFooter() << "%%Pages: 1" << endl;
    //cerr << "doc.write(cout);\n";
    
    //
    // Write it all out:
    // Is this easy or what?
    //
    //
    // If you need to write out an Encapsulated Postscript
    // (EPS) document, just include the BoundingBox parameters
    // llx, lly, urx, ury as additional parameters to the write()
    // method:
    //
    // doc.write(cout, llx, lly, urx, ury);
    //
    if (argc == 1) {
      doc.write(cout);
    }
    else {
      strm.open(argv[1]);
      doc.write(strm);
      strm.close();
    }
    
  } catch (runtime_error& e) {
    cerr << e.what() << endl;
    return 1;
  }

  return 0;
}
