NS_IMETHODIMP nsDeviceContextOS2 :: GetDeviceContextFor(nsIDeviceContextSpec *aDevice,
                                                        nsIDeviceContext *&aContext)
{
  PRTQUEUE *pq;

  aContext = new nsDeviceContextOS2();
  if(nsnull != aContext){
    NS_ADDREF(aContext);
  } else {
    return NS_ERROR_OUT_OF_MEMORY;
  }
 
  ((nsDeviceContextOS2 *)aContext)->mSpec = aDevice;
  NS_ADDREF(aDevice);
  
  int numCopies = 0;
  int printerDest = 0;
  char *file = nsnull;

  ((nsDeviceContextSpecOS2 *)aDevice)->GetPRTQUEUE(pq);
  ((nsDeviceContextSpecOS2 *)aDevice)->GetCopies(numCopies);
  ((nsDeviceContextSpecOS2 *)aDevice)->GetDestination(printerDest);
  if (!printerDest) 
     ((nsDeviceContextSpecOS2 *)aDevice)->GetPath(&file);

  HDC dc = PrnOpenDC(pq, "Mozilla", numCopies, printerDest, file);

  if (!dc) {
     return NS_ERROR_FAILURE; //PMERROR("DevOpenDC");
  } /* endif */

  return ((nsDeviceContextOS2 *)aContext)->Init((nsNativeDeviceContext)dc, this);
}
Example #2
0
NS_IMETHODIMP nsDeviceContextSpecOS2::GetSurfaceForPrinter(gfxASurface **surface)
{
  NS_ASSERTION(mQueue, "Queue can't be NULL here");

  nsRefPtr<gfxASurface> newSurface;

  PRInt16 outputFormat;
  mPrintSettings->GetOutputFormat(&outputFormat);
  // for now always set the output format to PDF, see bug 415522:
  printf("print output format is %d but we are setting it to %d (PDF)\n",
         outputFormat, nsIPrintSettings::kOutputFormatPDF);
  outputFormat = nsIPrintSettings::kOutputFormatPDF;
  mPrintSettings->SetOutputFormat(outputFormat); // save PDF format in settings

  if (outputFormat == nsIPrintSettings::kOutputFormatPDF) {
    nsXPIDLString filename;
    mPrintSettings->GetToFileName(getter_Copies(filename));
    nsresult rv;
    if (filename.IsEmpty()) {
      // print to a file that is visible, like one on the Desktop
      nsCOMPtr<nsIFile> pdfLocation;
      rv = NS_GetSpecialDirectory(NS_OS_DESKTOP_DIR, getter_AddRefs(pdfLocation));
      NS_ENSURE_SUCCESS(rv, rv);

      // construct a print output name using the current time, to make it
      // unique and not overwrite existing files
      char printName[CCHMAXPATH];
      PRExplodedTime time;
      PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &time);
      snprintf(printName, CCHMAXPATH-1, "%s_%04d%02d%02d_%02d%02d%02d.pdf",
               MOZ_APP_DISPLAYNAME, time.tm_year, time.tm_month+1, time.tm_mday,
               time.tm_hour, time.tm_min, time.tm_sec);
      printName[CCHMAXPATH-1] = '\0';

      nsCAutoString printString(printName);
      rv = pdfLocation->AppendNative(printString);
      NS_ENSURE_SUCCESS(rv, rv);
      rv = pdfLocation->GetPath(filename);
      NS_ENSURE_SUCCESS(rv, rv);
    }
#ifdef debug_thebes_print
    printf("nsDeviceContextSpecOS2::GetSurfaceForPrinter(): print to filename=%s\n",
           NS_LossyConvertUTF16toASCII(filename).get());
#endif

    double width, height;
    mPrintSettings->GetEffectivePageSize(&width, &height);
    // convert twips to points
    width  /= TWIPS_PER_POINT_FLOAT;
    height /= TWIPS_PER_POINT_FLOAT;

    nsCOMPtr<nsILocalFile> file = do_CreateInstance("@mozilla.org/file/local;1");
    rv = file->InitWithPath(filename);
    if (NS_FAILED(rv))
      return rv;

    nsCOMPtr<nsIFileOutputStream> stream = do_CreateInstance("@mozilla.org/network/file-output-stream;1");
    rv = stream->Init(file, -1, -1, 0);
    if (NS_FAILED(rv))
      return rv;

    newSurface = new(std::nothrow) gfxPDFSurface(stream, gfxSize(width, height));
  } else {
    int numCopies = 0;
    int printerDest = 0;
    char *filename = nsnull;

    GetCopies(numCopies);
    GetDestination(printerDest);
    if (!printerDest) {
      GetPath(&filename);
    }
    mPrintingStarted = PR_TRUE;
    mPrintDC = PrnOpenDC(mQueue, "Mozilla", numCopies, printerDest, filename);

    double width, height;
    mPrintSettings->GetEffectivePageSize(&width, &height);
#ifdef debug_thebes_print
    printf("nsDeviceContextSpecOS2::GetSurfaceForPrinter(): %fx%ftwips, copies=%d\n",
           width, height, numCopies);
#endif

    // we need pixels, so scale from twips to the printer resolution
    // and take into account that CAPS_*_RESOLUTION are in px/m, default
    // to approx. 100dpi
    double hDPI = 3937., vDPI = 3937.;
    LONG value;
    if (DevQueryCaps(mPrintDC, CAPS_HORIZONTAL_RESOLUTION, 1, &value))
      hDPI = value * 0.0254;
    if (DevQueryCaps(mPrintDC, CAPS_VERTICAL_RESOLUTION, 1, &value))
      vDPI = value * 0.0254;
    width = width * hDPI / 1440;
    height = height * vDPI / 1440;
#ifdef debug_thebes_print
    printf("nsDeviceContextSpecOS2::GetSurfaceForPrinter(): %fx%fpx (res=%fx%f)\n"
           "  expected size: %7.2f MiB\n",
           width, height, hDPI, vDPI, width*height*4./1024./1024.);
#endif

    // perhaps restrict to usable area
    // (this or scaling down won't help, we will just get more pages and still crash!)
    if (DevQueryCaps(mPrintDC, CAPS_WIDTH, 1, &value) && width > (double)value)
      width = (double)value;
    if (DevQueryCaps(mPrintDC, CAPS_HEIGHT, 1, &value) && height > (double)value)
      height = (double)value;

#ifdef debug_thebes_print
    printf("nsDeviceContextSpecOS2::GetSurfaceForPrinter(): capped? %fx%fpx (res=%fx%f)\n"
           "  expected size: %7.2f MiB per page\n",
           width, height, hDPI, vDPI, width*height*4./1024./1024.);
#endif

    // Now pass the created DC into the thebes surface for printing.
    // It gets destroyed there.
    newSurface = new(std::nothrow)
      gfxOS2Surface(mPrintDC, gfxIntSize(int(ceil(width)), int(ceil(height))));
  }
  if (!newSurface) {
    *surface = nsnull;
    return NS_ERROR_FAILURE;
  }
  *surface = newSurface;
  NS_ADDREF(*surface);
  return NS_OK;
}