微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Ghostscript 显示设备 rectangle_request 工作吗?

如何解决Ghostscript 显示设备 rectangle_request 工作吗?

我正在编写一个与 PDF 相关的小应用程序,因此我选择了 Ghostscript 进行渲染。我已将 Ghostscript v9.54.0 中的 gsdll64.dll 带入我的项目中。该库启动正常,但有一个怪癖:当我使用 rectangle_request 回调时,它会产生内存访问冲突错误。首先,我认为这是因为 C# 绑定(最初我在 WPF 平台上,使用 Ghostscript.NET,当然),但经过数小时的尝试,我最终得到了一个产生相同错误的 C++ 演示应用程序。

以下是我在该测试应用中所做的:

/*
 * 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;
}

接下来可以看到回调构成:

// 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
};

我的问题很简单:我做错了什么? =)

P.S.:我也在检查 Ghostscript 的开源;设备/devdsp.c 特别。尽管被大量代码淹没,但我强烈感觉到显示设备不支持 rectangle_request 回调。希望我错了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。