Example #1
0
int eprn_output_page(gx_device *dev, int num_copies, int flush)
{
  eprn_Eprn *eprn = &((eprn_Device *)dev)->eprn;
  int rc;

#ifdef EPRN_TRACE
  clock_t start_time = clock();
  if_debug0(EPRN_TRACE_CHAR, "! eprn_output_page()...\n");
#endif

  /* Initialize eprn_get_planes() data */
  eprn->next_y = 0;
  if (eprn->intensity_rendering == eprn_IR_FloydSteinberg) {
    /* Fetch the first line and store it in 'next_scan_line'. */
    if (eprn_fetch_scan_line((eprn_Device *)dev, &eprn->next_scan_line) == 0)
      eprn->next_y++;
  }

  /* Ship out */
  rc = gdev_prn_output_page(dev, num_copies, flush);

  /*  CUPS page accounting message. The CUPS documentation is not perfectly
      clear on whether one should generate this message before printing a page
      or after printing has been successful. The rasterto* filters generate it
      before sending the page, but as the scheduler uses these messages for
      accounting, this seems unfair.
  */
  if (rc == 0 && eprn->CUPS_accounting)
    eprintf2("PAGE: %ld %d\n", dev->ShowpageCount, num_copies);
    /* The arguments are the number of the page, starting at 1, and the number
       of copies of that page. */

#ifndef EPRN_NO_PAGECOUNTFILE
  /* On success, record the number of pages printed */
  if (rc == 0 && eprn->pagecount_file != NULL) {
    assert(num_copies > 0);     /* because of signed/unsigned */
    if (pcf_inccount(eprn->pagecount_file, num_copies) != 0) {
      /* pcf_inccount() has issued an error message. */
      eprintf(
        "  No further attempts will be made to access the page count file.\n");
      gs_free(dev->memory->non_gc_memory, eprn->pagecount_file, strlen(eprn->pagecount_file) + 1,
        sizeof(char), "eprn_output_page");
      eprn->pagecount_file = NULL;
    }
  }
#endif  /* !EPRN_NO_PAGECOUNTFILE */

  /* If soft tumble has been demanded, ensure the get_initial_matrix procedure
     is consulted for the next page */
  if (eprn->soft_tumble) eprn_forget_defaultmatrix(dev->memory->non_gc_memory);

#ifdef EPRN_TRACE
  if_debug1(EPRN_TRACE_CHAR, "! eprn_output_page() terminates after %f s.\n",
    ((float)(clock() - start_time))/CLOCKS_PER_SEC);
#endif

  return rc;
}
Example #2
0
/*
 * Must be called by async device driver implementation (see gdevprna.h
 * under "Synchronizing the Instances"). This is the rendering loop, which
 * requires its own thread for as long as the device is open. This proc only
 * returns after the device is closed, or if the open failed. NB that an
 * open error leaves things in a state where the writer thread will not be
 * able to close since it's expecting the renderer to acknowledge its
 * requests before the writer can close.  Ergo, if this routine fails you'll
 * crash unless the caller fixes the problem & successfully retries this.
 */
int				/* rets 0 ok, -ve error code if open failed */
gdev_prn_async_render_thread(
                             gdev_prn_start_render_params * params
)
{
    gx_device_printer *const pwdev = params->writer_device;
    gx_device_printer *const prdev = pwdev->async_renderer;
    gx_page_queue_entry_t *entry;
    int code;

    /* Open device, but don't use default if user didn't override */
    if (prdev->printer_procs.open_render_device ==
          gx_default_open_render_device)
        code = gdev_prn_async_render_open(prdev);
    else
        code = (*prdev->printer_procs.open_render_device) (prdev);
    reinit_printer_into_renderer(prdev);

    /* The cmd list logic assumes reader's & writer's tile caches are same size */
    if (code >= 0 &&
          ((gx_device_clist *) pwdev)->writer.page_tile_cache_size !=
            ((gx_device_clist *) prdev)->writer.page_tile_cache_size) {
        gdev_prn_async_render_close_device(prdev);
        code = gs_note_error(gs_error_VMerror);
    }
    params->open_code = code;
    gx_semaphore_signal(params->open_semaphore);
    if (code < 0)
        return code;

    /* fake open, since not called by gs_opendevice */
    prdev->is_open = true;

    /* Successful open */
    while ((entry = gx_page_queue_start_dequeue(prdev->page_queue))
           && entry->action != GX_PAGE_QUEUE_ACTION_TERMINATE) {
        /* Force printer open again if it mysteriously closed. */
        /* This shouldn't ever happen, but... */
        if (!prdev->is_open) {
            if (prdev->printer_procs.open_render_device ==
                  gx_default_open_render_device)
                code = gdev_prn_async_render_open(prdev);
            else
                code = (*prdev->printer_procs.open_render_device) (prdev);
            reinit_printer_into_renderer(prdev);

            if (code >= 0) {
                prdev->is_open = true;
                gdev_prn_output_page((gx_device *) prdev, 0, true);
            }
        }
        if (prdev->is_open) {
            /* Force retrieved entry onto render device */
            ((gx_device_clist *) prdev)->common.page_info = entry->page_info;

            /* Set up device geometry */
            if (clist_setup_params((gx_device *) prdev) >= 0)
                /* Go this again, since setup_params may have trashed it */
                ((gx_device_clist *) prdev)->common.page_info = entry->page_info;

            /* Call appropriate renderer routine to deal w/buffer */
            /* Ignore status, since we don't know how to deal w/errors! */
            switch (entry->action) {

                case GX_PAGE_QUEUE_ACTION_FULL_PAGE:
                    (*dev_proc(prdev, output_page))((gx_device *) prdev,
                                                    entry->num_copies, true);
                    break;

                case GX_PAGE_QUEUE_ACTION_PARTIAL_PAGE:
                case GX_PAGE_QUEUE_ACTION_COPY_PAGE:
                    (*dev_proc(prdev, output_page))((gx_device *) prdev,
                                                    entry->num_copies, false);
                    break;
            }
            /*
             * gx_page_queue_finish_dequeue will close and free the band
             * list files, so we don't need to call clist_close_output_file.
             */
        }
        /* Finalize dequeue & free retrieved queue entry */
        gx_page_queue_finish_dequeue(entry);
    }

    /* Close device, but don't use default if user hasn't overriden. */
    /* Ignore status, since returning bad status means open failed */
    if (prdev->printer_procs.close_render_device ==
          gx_default_close_render_device)
        gdev_prn_async_render_close_device(prdev);
    else
        (*prdev->printer_procs.close_render_device)(prdev);

    /* undo fake open, since not called by gs_closedevice */
    prdev->is_open = false;

    /* Now that device is closed, acknowledge gx_page_queue_terminate */
    gx_page_queue_finish_dequeue(entry);

    return 0;
}