Exemplo n.º 1
0
int main(int argc,char **argv)
{
    unsigned int window_width=-1, window_height=-1;  // sage window size

    sage::initUtil();

    // parse command line arguments
    if (argc < 2){
	sage::printLog("PDF> pdfviewer filename [width] [height] [-show_original] [-page num]");
	return 0;
    }
    for (int argNum=2; argNum<argc; argNum++)
    {
	if (strcmp(argv[argNum], "-show_original") == 0) {
	    useDXT = false;
	}
	else if(strcmp(argv[argNum], "-page") == 0) {
	    int p = atoi(argv[argNum+1]);
	    if (p != 0)
		firstPage = p-1;
	    argNum++;
	}
	else if(atoi(argv[argNum]) != 0 && atoi(argv[argNum+1]) != 0) {
	    window_width = atoi( argv[argNum] );
	    window_height = atoi( argv[argNum+1] );
	    argNum++;  // increment because we read two args here
	}
    }


    fileName = string(argv[1]);

#if defined(USE_POPPLER)
#if SAGE_POPPLER_VERSION == 5
  g_type_init();
  sage::printLog("PDF> Poppler version %s", poppler_get_version());
  backend = poppler_get_backend ();
  enum_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (POPPLER_TYPE_BACKEND), backend);
  sage::printLog ("PDF> Backend is %s", enum_value->value_name);

  error = NULL;
  const string filename = string((const char*)"file://") + string(argv[1]);
  document = poppler_document_new_from_file (filename.c_str(), NULL, &error);
  if (document == NULL) {
    sage::printLog("PDF> error for [%s]: %s", filename.c_str(), error->message);
    exit(0);
  }
  // get the number of pages
  numImages = poppler_document_get_n_pages(document);

  pg_index = 0; // index starts at 0
  page = poppler_document_get_page(document, pg_index);
  if (page == NULL) {
    sage::printLog("PDF> error for [%s]: %s", filename.c_str());
    exit(0);
  }

  // page size
  double mwidth, mheight;
  poppler_page_get_size (page, &mwidth, &mheight);
  sage::printLog ("PDF> page size: %g by %g ", mwidth, mheight);

  x_resolution = 200.0;
  pg_w = mwidth  * (x_resolution / 72.0);
  pg_h = mheight * (x_resolution / 72.0);

  if (pg_w > 4096) {
	pg_w = 4096.0;
	pg_h = 4096.0 / (mwidth/mheight);
	x_resolution = pg_w * 72.0 / mwidth;
  }
  if (pg_h > 4096) {
	pg_w = 4096.0 / (mheight/mwidth);
	pg_h = 4096.0;
	x_resolution = pg_h * 72.0 / mheight;
  }

  width  = (unsigned int)pg_w;
  height = (unsigned int)pg_h;
  sage::printLog("PDF> Crop @ %d DPI: width %d height %d", int(x_resolution), int(pg_w), int(pg_h));

  pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
  gdk_pixbuf_fill (pixbuf, 0xffffffff);

  // print some information
  print_document_info (document); 

#endif
#if SAGE_POPPLER_VERSION == 12
  GooString *fileName;
  GooString *ownerPW, *userPW;
  Object info;
  UnicodeMap *uMap;

  // read config file
  globalParams = new GlobalParams();

  // get mapping to output encoding
  if (!(uMap = globalParams->getTextEncoding())) {
    sage::printLog("PDF> Couldn't get text encoding");
  }

  fileName = new GooString(argv[1]);
  ownerPW = NULL;
  userPW = NULL;
  doc = new PDFDoc(fileName, ownerPW, userPW, NULL);
  sage::printLog("PDF> file [%s] is OK: %d", argv[1], doc->isOk() );
  numImages = doc->getNumPages();
  sage::printLog("PDF> num pages: %d", numImages );

  SplashColor paperColor;
  paperColor[0] = 255;
  paperColor[1] = 255;
  paperColor[2] = 255;

  splashOut = new SplashOutputDev(splashModeRGB8, 3, gFalse, paperColor);
  splashOut->startDoc(doc->getXRef());

  pg_index = firstPage+1;
  double mwidth  = doc->getPageMediaWidth(pg_index);
  double mheight = doc->getPageMediaHeight(pg_index);
  sage::printLog("PDF> Media width %d height %d", int(mwidth), int(mheight));

  x_resolution = 200.0;
  pg_w = mwidth  * (x_resolution / 72.0);
  pg_h = mheight * (x_resolution / 72.0);

  if (pg_w > 4096) {
	pg_w = 4096.0;
	pg_h = 4096.0 / (mwidth/mheight);
	x_resolution = pg_w * 72.0 / mwidth;
  }
  if (pg_h > 4096) {
	pg_w = 4096.0 / (mheight/mwidth);
	pg_h = 4096.0;
	x_resolution = pg_h * 72.0 / mheight;
  }

  width  = pg_w;
  height = pg_h;
  sage::printLog("PDF> Crop @ %d DPI: width %d height %d", int(x_resolution), int(pg_w), int(pg_h));

  doc->displayPageSlice(splashOut, 1, x_resolution, x_resolution, 0, gTrue, gFalse, gFalse, 0, 0, pg_w, pg_h);

  // print doc info
  doc->getDocInfo(&info);
  if (info.isDict()) {
    printInfoString(info.getDict(), (char*)"Title",        (char*)"Title:          ", uMap);
    printInfoString(info.getDict(), (char*)"Subject",      (char*)"Subject:        ", uMap);
    printInfoString(info.getDict(), (char*)"Keywords",     (char*)"Keywords:       ", uMap);
    printInfoString(info.getDict(), (char*)"Author",       (char*)"Author:         ", uMap);
    printInfoString(info.getDict(), (char*)"Creator",      (char*)"Creator:        ", uMap);
    printInfoString(info.getDict(), (char*)"Producer",     (char*)"Producer:       ", uMap);
    printInfoDate(info.getDict(),   (char*)"CreationDate", (char*)"CreationDate:   ");
    printInfoDate(info.getDict(),   (char*)"ModDate",      (char*)"ModDate:        ");
  }
  info.free();
#endif
#else
    // read file
    wand=NewMagickWand();  

    // set the resolution (pixel density)
    MagickSetResolution(wand, 200,200);
    
    status=MagickReadImage(wand, fileName.data());
    if (status == MagickFalse)
	ThrowWandException(wand);
    numImages = MagickGetNumberImages(wand);
    MagickSetImageIndex(wand, firstPage);

    // get the image size
    width = MagickGetImageWidth(wand);
    height = MagickGetImageHeight(wand);

    // -------  TODO: need to keep track of images that have been flipped already...

    // crop the image if necessary to make sure it's a multiple of 4
    if (useDXT)
    {
	if (width%4 != 0 || height%4 != 0)
	{
	    fprintf(stderr, "\n**** Image cropped a few pixels to be a multiple of 4 for dxt");
	    width -= width%4;
	    height -= height%4;
	}
	
	// flip the image to have the correct orientation for dxt
	MagickFlipImage(wand);
    }
#endif

    // allocate buffers 
    rgba = (byte*) memalign(16, width*height*4);
    if (useDXT)
	dxt = (byte*) memalign(16, width*height*4/8);

    // get the first page
    getRGBA();

    // if the user didn't specify the window size, use the image size
    if (window_height == -1 && window_width == -1)
    {
	window_width = width;
	window_height = height;
    }
  
    // initialize SAIL

    // Search for a configuration file
    char *tmpconf = getenv("SAGE_APP_CONFIG");
    if (tmpconf) {
      sage::printLog("PDFViewer> found SAGE_APP_CONFIG variable: [%s]", tmpconf);
      scfg.init(tmpconf);
    }
    else {
      sage::printLog("PDFViewer> using default pdfviewer.conf");
      scfg.init((char*)"pdfviewer.conf");
    }

    scfg.setAppName("pdfviewer");

    scfg.resX = width;
    scfg.resY = height;

    // if it hasn't been specified by the config file, use the app-determined size
    if (scfg.winWidth == -1 || scfg.winHeight == -1) {
	scfg.winWidth = window_width;
	scfg.winHeight = window_height;
    }
    
    if (useDXT)
    {
	scfg.pixFmt = PIXFMT_DXT;
	scfg.rowOrd = BOTTOM_TO_TOP;
    }
    else
    {
	scfg.pixFmt = PIXFMT_888;
	scfg.rowOrd = TOP_TO_BOTTOM;
    }

    sageInf.init(scfg);

    // finally swap the first buffer
    swapBuffer();


    // Wait the end
    while (1)
    {
	usleep(50000);  // so that we don't keep spinning too frequently (0.5s)
	sageMessage msg;
	if (sageInf.checkMsg(msg, false) > 0) {
	    char *data = (char*) msg.getData();

	    switch (msg.getCode()) {
	    case APP_QUIT:
		// release the memory
		free(dxt);
		free(rgba);
#if ! defined(USE_POPPLER)
		DestroyMagickWand(wand);
#endif

		sageInf.shutdown();
		exit(1);
		break;

	    case EVT_CLICK:
		// Click event x and y location normalized to size of window
		float clickX, clickY;

		// Ckick device Id, button Id, and is down flag
		int clickDeviceId, clickButtonId, clickIsDown, clickEvent;

		// Parse message
		sscanf(data, 
		       "%d %f %f %d %d %d", 
		       &clickDeviceId, &clickX, &clickY, 
		       &clickButtonId, &clickIsDown, &clickEvent);

		// record the click position so we know how far we moved
		if (clickIsDown && clickEvent == EVT_PAN) {
		    lastX = clickX;
		    lastY = clickY;
		}


		if (clickIsDown) {
		    bool doSwap = false;
#if ! defined(USE_POPPLER)
		    if (clickButtonId==1)
			doSwap = MagickPreviousImage(wand);
		    else if(clickButtonId==2)
			doSwap = MagickNextImage(wand);
#endif
			
		    // if everything went well, swap the new page
		    if (doSwap) {
			getRGBA();
			swapBuffer();
		    }
		}
		

		break;


	    case EVT_PAN: 

		// Pan event properties
		int panDeviceId;
		bool doSwap = false;

		// Pan event x and y location and change in x, y and z direction
		// normalized to size of window
		float startX, startY, panDX, panDY, panDZ;
		sscanf(data, 
		       "%d %f %f %f %f %f", 
		       &panDeviceId, &startX, &startY, &panDX, &panDY, &panDZ);
		
		// keep track of distance
		dist += panDX;

		// we started a new drag
		if (lastX != startX) {
		    lastX = startX;
		    dist = 0;
		}

		// if we dragged more than a certain distance, change a page
		else if( fabs(dist) > 0.07 ) {
#if ! defined(USE_POPPLER)
		    if (dist > 0)
			doSwap = MagickPreviousImage(wand);
		    else
			doSwap = MagickNextImage(wand);
#endif

		    // reset the counter
		    lastX = startX;
		    dist = 0;

		    if (doSwap) {
			getRGBA();
			swapBuffer();
			//sprintf(l, "Page %ld of %d", MagickGetImageIndex(wand)+1, numImages);
		    }
		}

		break;
	    }   // end switch
	}  // end if
    } // end while

    return 0;
}