Does Ghostscript Display device rectangle_request work?

136 views Asked by At

I am writing a little PDF-related app, thus I have chosen Ghostscript for the rendering purposes. I have taken gsdll64.dll from Ghostscript v9.54.0 into my project. The library starts up fine, but there is a quirk: it produces a memory access violation error when I am using rectangle_request callback. First I was thinking it happened because of C# binding (initially I was on WPF platform, with Ghostscript.NET, sure), but after hours of trying I ended up with a C++ demo app that produces the same error.

The following is what I am doing in that test app:

/*
 * This is how Ghostscript is initialized
 * 
 * The code is taken partly from https://www.ghostscript.com/doc/demos/c/api_test.c
 */
INT InitGhostscript() {
    int code, argc;

    LPCWSTR cmdl = GetCommandLine();
    LPWSTR* argv = CommandLineToArgvW(cmdl, &argc);

    if (argc < 2) return -1;
    std::tstring filePath = argv[1];

    auto args = std::vector<std::tstring>();
    std::tstringstream arg;

    /* Create a GS instance. */
    code = gsapi_new_instance(&instance, NULL);
    if (code < 0) {
        printf("Error %d in gsapi_new_instance\n", code);
        goto failearly;
    }

    args.push_back(str__(arg__ << _T("-gsnet")));

    // TODO: init std io
    // App interacts with PDF through gs_std_out; what happens inside is taken from 
    // https://github.com/jhabjan/Ghostscript.NET/blob/master/Ghostscript.NET/Viewer/FormatHandlers/GhostscriptViewerPdfFormatHandler.cs
    gsapi_set_stdio(instance, NULL, gs_std_out, NULL);
    
    // TOOD: init display handler
    args.push_back(str__(arg__ << _T("-sDEVICE=display")));
    args.push_back(str__(arg__ << _T("-sDisplayHandle=0")));
    args.push_back(str__(arg__ << _T("-dDisplayFormat=")
                               << (DISPLAY_COLORS_RGB
                                    | DISPLAY_ALPHA_NONE
                                    | DISPLAY_DEPTH_8
                                    | DISPLAY_LITTLEENDIAN
                                    | DISPLAY_BOTTOMFIRST)));

    args.push_back(str__(arg__ << _T("-dInterpolateControl=-1")));
    args.push_back(str__(arg__ << _T("-dGridFitTT=0")));
    args.push_back(str__(arg__ << _T("-dMaxBitmap=1g")));

    gsapi_set_display_callback(instance, &cb);

    args.push_back(str__(arg__ << _T("--permit-file-read=")
                               << filePath));

    arg.clear();

    /* Run our test. */
    code = InitWithArgs(args);
    if (code < 0) {
        printf("Error %d in gsapi_init_with_args\n", code);
        goto fail;
    }

    code = OpenPdfFile(to_mbcs_str(filePath));
    if (code < 0) {
        goto fail;
    }
    
    ShowPage(1);

    /* Close the interpreter down (important, or we will leak!) */
    code = gsapi_exit(instance);
    if (code < 0) {
        printf("Error %d in gsapi_exit\n", code);
        goto fail;
    }

fail:
    /* Delete the gs instance. */
    gsapi_delete_instance(instance);
    instance = NULL;

failearly:

    return code;
}

One can see the callbacks constitution next:

// This contains info regarding the area of memory I would like to get display rectangle output into.
bitmap_context ctx; 

static int rectangle_request(void* handle, void* device,
    void** memory, int* ox, int* oy,
    int* raster, int* plane_raster,
    int* x, int* y, int* w, int* h)
{
    GdiFlush();

    *memory = ctx.bitmap; // This is a pointer to ppvBits as returned by CreateDIBSection (Bitmap: 24bpp RGB)
    *ox = *oy = 0;

    *raster = ctx.raster; // aligned by 4 boundary
    *plane_raster = 0;

    *x = *y = 0;
    *w = ctx.w;
    *h = ctx.h;

    return 0;
}

static display_callback cb = {
    sizeof(cb),
    DISPLAY_VERSION_MAJOR,
    DISPLAY_VERSION_MINOR,

    // All of these are empty at the moment, returning zero.
    open,
    preclose,
    close,
    presize,
    size,
    sync,
    page,
    update,
    memalloc,
    memfree,
    separation,
    adjust_band_height,

    // Except this one (see above)
    rectangle_request
};

My question is simple: what am I doing wrong with this? =)

P.S.: I was also examining Ghostscript's open sources; devices/devdsp.c specifically. Despite being overwhelmed by the amount of code I've got a strong feeling that rectangle_request callback is not supported by Display device. Hope I am wrong.

0

There are 0 answers