static int bbox_create_compositor(gx_device * dev, gx_device ** pcdev, const gs_composite_t * pcte, gs_imager_state * pis, gs_memory_t * memory, gx_device *cindev) { gx_device_bbox *const bdev = (gx_device_bbox *) dev; gx_device *target = bdev->target; /* * If there isn't a target, all we care about is the bounding box, * so don't bother with actually compositing. */ if (target == 0) { *pcdev = dev; return 0; } /* * Create a compositor for the target, and then wrap another * bbox device around it, but still accumulating the bounding * box in the same place. */ { gx_device *temp_cdev; gx_device_bbox *bbcdev; int code = (*dev_proc(target, create_compositor)) (target, &temp_cdev, pcte, pis, memory, cindev); /* If the target did not create a new compositor then we are done. */ if (code < 0 || target == temp_cdev) { *pcdev = dev; return code; } bbcdev = gs_alloc_struct_immovable(memory, gx_device_bbox, &st_device_bbox, "bbox_create_compositor"); if (bbcdev == 0) { (*dev_proc(temp_cdev, close_device)) (temp_cdev); return_error(gs_error_VMerror); } gx_device_bbox_init(bbcdev, target, memory); gx_device_set_target((gx_device_forward *)bbcdev, temp_cdev); bbcdev->box_procs = box_procs_forward; bbcdev->box_proc_data = bdev; *pcdev = (gx_device *) bbcdev; return 0; } }
int main(int argc, const char *argv[]) { char achar = '0'; gs_memory_t *mem; gs_state *pgs; const gx_device *const *list; gx_device *dev; gx_device_bbox *bbdev; int code; gp_init(); mem = gs_malloc_init(); gs_lib_init1(mem); if (argc < 2 || (achar = argv[1][0]) < '1' || achar > '0' + countof(tests) - 1 ) { lprintf1("Usage: gslib 1..%c\n", '0' + (char)countof(tests) - 1); gs_abort(mem); } gs_debug['@'] = 1; gs_debug['?'] = 1; /*gs_debug['B'] = 1; *//****** PATCH ******/ /*gs_debug['L'] = 1; *//****** PATCH ******/ /* * gs_iodev_init must be called after the rest of the inits, for * obscure reasons that really should be documented! */ gs_iodev_init(mem); /****** WRONG ******/ gs_lib_device_list(&list, NULL); gs_copydevice(&dev, list[0], mem); check_device_separable(dev); gx_device_fill_in_procs(dev); bbdev = gs_alloc_struct_immovable(mem, gx_device_bbox, &st_device_bbox, "bbox"); gx_device_bbox_init(bbdev, dev, mem); code = dev_proc(dev, get_profile)(dev, &bbdev->icc_struct); rc_increment(bbdev->icc_struct); /* Print out the device name just to test the gsparam.c API. */ { gs_c_param_list list; gs_param_string nstr; gs_c_param_list_write(&list, mem); code = gs_getdeviceparams(dev, (gs_param_list *) & list); if (code < 0) { lprintf1("getdeviceparams failed! code = %d\n", code); gs_abort(mem); } gs_c_param_list_read(&list); code = param_read_string((gs_param_list *) & list, "Name", &nstr); if (code < 0) { lprintf1("reading Name failed! code = %d\n", code); gs_abort(mem); } dputs("Device name = "); debug_print_string(nstr.data, nstr.size); dputs("\n"); gs_c_param_list_release(&list); } /* * If this is a device that takes an OutputFile, set the OutputFile * to "-" in the copy. */ { gs_c_param_list list; gs_param_string nstr; gs_c_param_list_write(&list, mem); param_string_from_string(nstr, "-"); code = param_write_string((gs_param_list *)&list, "OutputFile", &nstr); if (code < 0) { lprintf1("writing OutputFile failed! code = %d\n", code); gs_abort(mem); } gs_c_param_list_read(&list); code = gs_putdeviceparams(dev, (gs_param_list *)&list); gs_c_param_list_release(&list); if (code < 0 && code != gs_error_undefined) { lprintf1("putdeviceparams failed! code = %d\n", code); gs_abort(mem); } } dev = (gx_device *) bbdev; pgs = gs_state_alloc(mem); gs_setdevice_no_erase(pgs, dev); /* can't erase yet */ { gs_point dpi; gs_screen_halftone ht; gs_dtransform(pgs, 72.0, 72.0, &dpi); ht.frequency = min(fabs(dpi.x), fabs(dpi.y)) / 16.001; ht.angle = 0; ht.spot_function = odsf; gs_setscreen(pgs, &ht); } /* gsave and grestore (among other places) assume that */ /* there are at least 2 gstates on the graphics stack. */ /* Ensure that now. */ gs_gsave(pgs); gs_erasepage(pgs); code = (*tests[achar - '1']) (pgs, mem); gs_output_page(pgs, 1, 1); { gs_rect bbox; gx_device_bbox_bbox(bbdev, &bbox); dprintf4("Bounding box: [%g %g %g %g]\n", bbox.p.x, bbox.p.y, bbox.q.x, bbox.q.y); } if (code) dprintf1("**** Test returned code = %d.\n", code); dputs("Done. Press <enter> to exit."); fgetc(mem->gs_lib_ctx->fstdin); gs_lib_finit(0, 0, mem); return 0; #undef mem }
/* Open the output file and stream. */ int gdev_vector_open_file_options(gx_device_vector * vdev, uint strmbuf_size, int open_options) { bool binary = !(open_options & VECTOR_OPEN_FILE_ASCII); int code = -1; /* (only for testing, never returned) */ cmm_dev_profile_t *icc_struct; /* Open the file as seekable or sequential, as requested. */ if (!(open_options & VECTOR_OPEN_FILE_SEQUENTIAL)) { /* Try to open as seekable. */ code = gx_device_open_output_file((gx_device *)vdev, vdev->fname, binary, true, &vdev->file); } if (code < 0 && (open_options & (VECTOR_OPEN_FILE_SEQUENTIAL | VECTOR_OPEN_FILE_SEQUENTIAL_OK))) { /* Try to open as sequential. */ code = gx_device_open_output_file((gx_device *)vdev, vdev->fname, binary, false, &vdev->file); } if ((code >= 0) && (dev_proc(vdev, get_profile) != NULL)) { code = dev_proc(vdev, get_profile)((gx_device *)vdev, &icc_struct); } if (code < 0) return code; if ((vdev->strmbuf = gs_alloc_bytes(vdev->v_memory, strmbuf_size, "vector_open(strmbuf)")) == 0 || (vdev->strm = s_alloc(vdev->v_memory, "vector_open(strm)")) == 0 || ((open_options & VECTOR_OPEN_FILE_BBOX) && (vdev->bbox_device = gs_alloc_struct_immovable(vdev->v_memory, gx_device_bbox, &st_device_bbox, "vector_open(bbox_device)")) == 0) ) { if (vdev->bbox_device) gs_free_object(vdev->v_memory, vdev->bbox_device, "vector_open(bbox_device)"); vdev->bbox_device = 0; if (vdev->strm) gs_free_object(vdev->v_memory, vdev->strm, "vector_open(strm)"); vdev->strm = 0; if (vdev->strmbuf) gs_free_object(vdev->v_memory, vdev->strmbuf, "vector_open(strmbuf)"); vdev->strmbuf = 0; gx_device_close_output_file((gx_device *)vdev, vdev->fname, vdev->file); vdev->file = 0; return_error(gs_error_VMerror); } vdev->strmbuf_size = strmbuf_size; swrite_file(vdev->strm, vdev->file, vdev->strmbuf, strmbuf_size); vdev->open_options = open_options; /* * We don't want finalization to close the file, but we do want it * to flush the stream buffer. */ vdev->strm->procs.close = vdev->strm->procs.flush; if (vdev->bbox_device) { gx_device_bbox_init(vdev->bbox_device, NULL, vdev->v_memory); rc_increment(vdev->bbox_device); vdev->bbox_device->icc_struct = icc_struct; rc_increment(vdev->bbox_device->icc_struct); gx_device_set_resolution((gx_device *) vdev->bbox_device, vdev->HWResolution[0], vdev->HWResolution[1]); /* Do the right thing about upright vs. inverted. */ /* (This is dangerous in general, since the procedure */ /* might reference non-standard elements.) */ set_dev_proc(vdev->bbox_device, get_initial_matrix, dev_proc(vdev, get_initial_matrix)); (*dev_proc(vdev->bbox_device, open_device)) ((gx_device *) vdev->bbox_device); } return 0; }