/************************** * Headers **************************/ #include #include #include #include #include #include #include "pdf.h" /************************** * Using Declarations **************************/ using std::ostringstream; using std::ifstream; using std::complex; using std::cout; using std::endl; using std::ios; /************************** * Local Functions **************************/ // --------------------------------------------------- // Multiply degrees by (2 * pi / 360.0) to // obtain radians // --------------------------------------------------- static double degreesToRadians(int degrees) { return((3.14159 / 180.0) * degrees); } // --------------------------------------------------- // Read 'fileName' and populate 'lines' with its // contents (on success, return true). On error, // populate 'errMsg' and return false. // --------------------------------------------------- static bool getLines( const string &fileName, vector &lines, string &errMsg ) { ifstream in; in.open(fileName.c_str(), ios::binary); if(!in) { errMsg = "Could not open: [" + fileName + "]"; return(false); } string line = ""; for(;;) { char c = (char)in.get(); if(in.eof()) { if(line != "") lines.push_back(line); break; } line += c; if(c == '\n') { lines.push_back(line); line = ""; } } in.close(); return(true); } // --------------------------------------------------- // Draw 'theText' at: [x, y] (using the specified // font and font size) with a box around it // --------------------------------------------------- static void drawBoundedText( const string &theText, int x, int y, PDF::Font theFont, int fontSize, PDF &p ) { p.setFont(theFont, fontSize); p.showTextXY(theText, x, y); int width = PDF::stringWidth( theFont, fontSize, theText ); int offset = (int)(0.4 * fontSize + 0.5); p.drawRect(x, y - offset, width, fontSize + offset); } // --------------------------------------------------- // Demonstrate: // // - text wrapping // - drawing and filling of circles and ellipses // - drawing and filling of rectangles and polygons // - drawing lines, using different line widths // - use of images // --------------------------------------------------- static void demoOne(PDF &p) { p.setFont(PDF::HELVETICA, 12); string s = " \t\t fee \r\nxxxxxxxxxxxxx\r\n\"fi\"fo fum"; s += " a aa aaa aaaa bbb bb b c cc ccc dddd eeeee "; s += " foo bar baz foo bar baz "; s += " mairzy doats and doazy doats and little lambsey divey"; s += " a kiddley divey too, wouldn't you? "; s += " a b c d e f g h i jj kkk llll mmmmmm nnnnnnn oooooooooooo "; s += "----------------------- -------------------------- "; s += "$$$ $$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ "; s += "******************** ************************ ***** "; vector sv = p.wrapText(s, 100, true); for(int i = 0, n = sv.size(); i < n; i ++) { // cout << "sv[" << i << "][" << sv[i] << "]\n"; p.showTextXY(sv[i], 80, 745 - 20 * i); } p.drawLine(80, 760, 80, 300); p.drawLine(180, 760, 180, 300); // cout << endl; p.drawEllipse(400, 550, 150, 75); p.setFillColor(255, 255, 0); p.fillEllipse(400, 550, 40, 65); p.drawEllipse(400, 550, 40, 65); for(int i = 0; i < 12; i ++) { unsigned char value = (unsigned char)(20 * i); p.setFillColor(value, value, value); p.fillCircle(480, 310 + 10 * i, 2 * i); p.drawCircle(480, 310 + 10 * i, 3 * i); } p.setLineColor(255, 0, 0); p.setFillColor(0, 0, 255); for(int i = 0; i < PDF::N_FONTS; i ++) { PDF::Font theFont = (PDF::Font)(i + 1); int fontSize = 9; int x = 10; int y = 36 + (2 * fontSize) * i; string s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" "!@#$%^&*()_-=+[]{};:<>,./?"; drawBoundedText(s, x, y, theFont, fontSize, p); } p.fillRect(300, 700, 40, 40); p.drawRect(400, 700, 40, 40); p.newPage(); p.setLineColor(255, 0, 0); for(int i = 0; i < PDF::N_FONTS; i ++) { p.setFont((PDF::Font)(i + 1), 20); p.showTextXY(PDF::FONTS[i], 100, 100 + 40 * i); } p.newPage(); p.setLineColor(255, 0, 0); for(int i = 0; i < 20; i ++) { p.drawLine(0, 0, 30 * (1 + i), 500 - 15 * i); p.setLineWidth(i/2 + 1); } vector points; points.push_back(XY(300, 500)); points.push_back(XY(325, 550)); points.push_back(XY(350, 480)); points.push_back(XY(375, 570)); points.push_back(XY(400, 460)); points.push_back(XY(425, 590)); points.push_back(XY(450, 450)); p.setLineColor(0, 255, 0); p.drawLine(points); points.clear(); points.push_back(XY(100, 540)); points.push_back(XY(150, 700)); points.push_back(XY( 80, 700)); p.setFillColor(200, 200, 200); p.fillPolygon(points); p.setLineColor(0, 0, 255); p.drawPolygon(points); p.newPage(); // Make an image ImageRow row1; ImageRow row2; row1.push_back(RGB(255, 255, 0)); row1.push_back(RGB(255, 0, 255)); row1.push_back(RGB( 0, 255, 0)); row2.push_back(RGB( 0, 0, 255)); row2.push_back(RGB(255, 0, 0)); row2.push_back(RGB( 0, 0, 255)); Image anImage; anImage.push_back(row1); anImage.push_back(row2); ImageInfo info = p.processImage(anImage); double scale = 50.0; for(int i = 0; i < 10; i ++) { int xValue = 120 + 30 * i; int yValue = 220 + 40 * i; p.showImage(info, xValue, yValue, scale); p.drawRect( xValue, yValue, (int)(scale * info.mWidth + 0.5), (int)(scale * info.mHeight + 0.5) ); } } // --------------------------------------------------- // Demonstrate: // // - the use of 'drawLine' and trigonometry // to create a geometric line drawing // --------------------------------------------------- static void demoTwo(PDF &p) { int xc = p.getWidth() / 2; int yc = p.getHeight() / 2; int smaller = (xc < yc ? xc : yc); int radius = (int)(.9 * smaller); int step = 15; for(int i = 0; i < 360; i += step) { double angle = degreesToRadians(i); int x0 = xc + (int)(radius * cos(angle) + 0.5); int y0 = yc + (int)(radius * sin(angle) + 0.5); for(int j = 0; j < 360; j += step) { if(j != i) { double theAngle = degreesToRadians(j); int x1 = xc + (int)(radius * cos(theAngle) + 0.5); int y1 = yc + (int)(radius * sin(theAngle) + 0.5); p.drawLine(x0, y0, x1, y1); } } } } // --------------------------------------------------- // Demonstrate: // // - ability to embed program code (this function, // 'demoThree' itself) in the pdf // // - use of images to create and store a // generated fractal image // // Note: The comments before and after the // 'demoThree' function that look like this: // // // begin: demoThree // // end: demoThree // // are markers in the source so that the // code for the 'demoThree' function can // be extracted and written to the pdf file // file and that process will fail if those // comments are altered/removed // // --------------------------------------------------- // begin: demoThree static void demoThree(PDF &p) { // Create an image, 500 pixels square int width = 500; int height = 500; Image anImage; RGB theColor(0, 0, 0); for(int i = 0; i < height; i ++) { ImageRow theRow; for(int j = 0; j < width; j ++) theRow.push_back(theColor); anImage.push_back(theRow); } double yStart = -2.0; double yStop = 2.0; double yStep = (yStop - yStart) / (height - 1); double xStart = -2.0; double xStop = 2.0; double xStep = (xStop - xStart) / (width - 1); int maxIterations = 25; double maxDistance = 1000.0; typedef complex Complex; int iValue = 0; for(double y = yStart; y <= yStop; y += yStep) { int jValue = 0; for(double x = xStart; x <= xStop; x += xStep) { Complex z(0.0, 0.0); Complex c(x, y); int iterations = 0; while( iterations < maxIterations && sqrt(z.real() * z.real() + z.imag() * z.imag()) < maxDistance ) { z = z * z + c; iterations ++; } double v1 = (double)iterations / maxIterations; double v2 = sqrt(v1); double v3 = sqrt(v2); v1 *= 255.0; v2 *= 255.0; v3 *= 255.0; unsigned char red = (unsigned char)(v1 + 0.5); unsigned char green = (unsigned char)(v2 + 0.5); unsigned char blue = (unsigned char)(v3 + 0.5); RGB theColor(red, green, blue); anImage[iValue][jValue] = theColor; jValue++; } iValue++; } // Place the image, centered ImageInfo info = p.processImage(anImage); int xValue = (p.getWidth() / 2) - (width / 2); int yValue = (p.getHeight() / 2) - (height / 2); p.showImage(info, xValue, yValue, 1.0); p.newPage(); string errMsg; vector lines; if(!getLines(__FILE__, lines, errMsg)) { cout << errMsg; } else { static const int FONTSIZE = 8; static const int MARGIN = 36; static const int YSTART = 750; int y = YSTART; bool showLine = false; // Avoid false positive by buidling our // markerBegin and markerEnd strings up dynamically string tag = "demoThree"; string markerBegin = "// begin: " + tag; string markerEnd = "// end: " + tag; bool needSetFont = true; for(int i = 0, n = lines.size(); i < n; i ++) { if(!showLine) { if(lines[i].find(markerBegin) != string::npos) showLine = true; } else { if(lines[i].find(markerEnd) != string::npos) showLine = false; if(showLine) { if(needSetFont) { p.setFont(PDF::COURIER, FONTSIZE); needSetFont = false; } p.showTextXY(lines[i], MARGIN, y); y -= FONTSIZE; if(y <= MARGIN) { p.newPage(); needSetFont = true; y = YSTART; } } } } } } // end: demoThree /************************** * Main **************************/ int main() { typedef void (*DemoFunction)(PDF &); DemoFunction functions[] = { demoOne, demoTwo, demoThree }; int n = sizeof(functions) / sizeof(functions[0]); for(int i = 0; i < n; i ++) { ostringstream out; out << "example-" << i << ".pdf"; string fileName = out.str(); cout << "-----------------------------------------" << "\n"; cout << "Creating File: [" << fileName << "]" << "\n"; cout << "-----------------------------------------" << "\n"; PDF pdf; functions[i](pdf); string errMsg; if(!pdf.writeToFile(fileName, errMsg)) { cout << errMsg << endl; } else { cout << "(File Successfully Written)" << endl; } cout << endl; } return(0); }