SIGSEGV在Canvas.clipPath在第二clipPath [英] SIGSEGV in Canvas.clipPath at the second clipPath

查看:130
本文介绍了SIGSEGV在Canvas.clipPath在第二clipPath的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个华硕的Nexus 7运行Android 4.2.2运行以下code时,我的应用程序generatng在sk_malloc_flags一个SIGSEGV:

I have a ASUS Nexus 7 running Android 4.2.2 My application is generatng a SIGSEGV in sk_malloc_flags when running the following code:

static Picture createDrawing() {

    Path firstPath = new Path();
    firstPath.moveTo(3058, 12365);
    firstPath.lineTo(8499, 3038);
    firstPath.lineTo(9494, 3619);
    firstPath.lineTo(4053, 12946);
    firstPath.close();

    Path fourthPath = new Path();
    fourthPath.moveTo(3065, 12332);
    fourthPath.lineTo(4053, 12926);
    fourthPath.lineTo(9615, 3669);
    fourthPath.lineTo(8628, 3075);
    fourthPath.close();

    Picture picture = new Picture();
    Canvas canvas = picture.beginRecording(12240, 15840);
    canvas.clipPath(firstPath);
    canvas.clipPath(fourthPath); << SIGSEGV occurs here
    picture.endRecording();
    return picture;
}

该SIGSEGV报道如下:

The SIGSEGV is reported as follows:

    I/DEBUG   (  124): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad
    I/DEBUG   (  124):     r0 00000027  r1 deadbaad  r2 4017f258  r3 00000000
    I/DEBUG   (  124):     r4 00000000  r5 bed72434  r6 bed72508  r7 1be773bc
    I/DEBUG   (  124):     r8 1be730f9  r9 000042c3  sl 00000001  fp 67185010
    I/DEBUG   (  124):     ip 40443f3c  sp bed72430  lr 401522f9  pc 4014e992  cpsr 60000030
...
    I/DEBUG   (  124): backtrace:
    I/DEBUG   (  124):     #00  pc 0001a992  /system/lib/libc.so
    I/DEBUG   (  124):     #01  pc 00018070  /system/lib/libc.so (abort+4)
    I/DEBUG   (  124):     #02  pc 000be4b4  /system/lib/libskia.so (sk_malloc_flags(unsigned int, unsigned int)+28)
    I/DEBUG   (  124):     #03  pc 0008afc0  /system/lib/libskia.so (SkRegion::op(SkRegion const&, SkRegion const&, SkRegion::Op)+1716)
    I/DEBUG   (  124):     #04  pc 00089448  /system/lib/libskia.so (SkRasterClip::op(SkRasterClip const&, SkRegion::Op)+128)

我已经明显简化了code到上面显示,全面应用程序使用变换等基于一些输入数据来生成值。他们是任何建议,如何解决这个问题,而不实现我自己的code在一般情况下,裁剪?

I have obviously simplified the code to that shown above, the full application uses transforms, etc based on some input data to generate the values. Are they any suggestions as to how to fix this without implementing my own code for clipping in the general case?

推荐答案

这看起来像一个恶运的角落案例 clipPath 处理。

This looks like an ill fated corner case for clipPath handling.

canvas.clipPath(fourthPath);

会导致previous合并 firstPath 然而,因为这些都是复杂(非矩形)形状系统试图拉拢他们为扫描线事后合并。为了使本次合并,就需要分配一些内存,但<一个href=\"https://android.googlesource.com/platform/external/skia/+/android-4.2.2_r1.2/src/core/SkRegion.cpp\">as您可以在SkRegion.cpp 看到,这是不言而喻的启发式最坏的情况下

causes a merge with previous firstPath however since these are complex (non-rectangular) shapes system tries to draw them as scanlines and merge it afterwards. To make this merge, it needs to allocate some memory but as you can see in SkRegion.cpp, it goes for heuristic worst case.

static int compute_worst_case_count(int a_count, int b_count) {
    int a_intervals = count_to_intervals(a_count);
    int b_intervals = count_to_intervals(b_count);
    // Our heuristic worst case is ai * (bi + 1) + bi * (ai + 1)
    int intervals = 2 * a_intervals * b_intervals + a_intervals + b_intervals;
    // convert back to number of RunType values
    return intervals_to_count(intervals);
}

有关你的路该 worst_case_count 变得接近到2GB,你会得到中止,由于没有得到来自的malloc

For your paths this worst_case_count becomes close to 2GB and you get an abort due to not getting that big memory from malloc.

我看不到任何出路它使用不同的参数。任何避免了合并 clipPath 取值必须帮助,比如调用clipPath与 Region.Op.REPLACE Region.Op.INTERSECT 应该失败了。

I couldn't see any way out of it using different parameters. Anything which avoids merging clipPaths must help, like calling clipPath with Region.Op.REPLACE. Region.Op.INTERSECT should fail too.

我会集中精力避免与一个复杂路径的顶部复杂的路径调用clipPath。

如果它适合你的使用情况,您可以使用相同的路径目标设置 canvas.clipPath()。例如:

If it suits your use case, you can use same Path object for setting canvas.clipPath(). For example:

Picture picture = new Picture();
Canvas canvas = picture.beginRecording(12240, 15840);
Path path = new Path();
path.moveTo(3058, 12365);
path.lineTo(8499, 3038);
path.lineTo(9494, 3619);
path.lineTo(4053, 12946);
path.close();
canvas.clipPath(path);
// do stuff with canvas
path.moveTo(3065, 12332);
path.lineTo(4053, 12926);
path.lineTo(9615, 3669);
path.lineTo(8628, 3075);
path.close();
canvas.clipPath(path, Region.Op.REPLACE);
// do more stuff with canvas
picture.endRecording();
return picture;

由于路径包含previous图纸,你可以继续更新它。如果这并不适用于你的情况,您可能需要使这些数字更小的或复杂区域划分成更小的,以避免最坏的情况下启发式变得太大。

Since path contains previous drawings, you can just continue updating it. If this is not applicable to your case, you either need to make those numbers smaller or partition your complex regions into smaller ones to avoid worst case heuristic to become too big.

这篇关于SIGSEGV在Canvas.clipPath在第二clipPath的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆