|
View:
New views
3 Messages
—
Rating Filter:
Alert me
|
|
|
Any chance to get trapezoids into public API?Hello,
I am writing a Java2D plugin, which allows to use Cairo's tesselator+ pixman's trapezoid-rasterizer for antialiased rendering. It works quite well, however it uses a lot of cairo-internal stuff like: _cairo_path_fixed_stroke_to_traps, _cairo_path_fixed_fill_to_traps, cairo_path_fixed_t, cairo_path_buf_t, cairo_traps_t, cairo_stroke_style_t I know by completly relying on cairo, I wouldn't have to mess with its internals - however there is a certain impedance mismatch between Java2D and Cairo and thats why I choose to use xrender back then. The ideas I have to deal with this situation would be: - Get that structures/functions public. I guess thats unlikely to happen, as its backend-specific. Would it be possible to some extents? - Fork cairo specifically for this project (just call it different), compile it to a shared library and check at run-time wether its available or not. (fallbacks are available). This would guarantee compatibility with all the assumptions the binding makes. How do you think should this be solved? Thanks, Clemens PS: The file attached is basically the binding. #include <cairo.h> #include <config.h> #include <X11/extensions/Xrender.h> #include <cairoint.h> #include <cairo-path-fixed-private.h> #include <jni.h> #include <jlong.h> #include <pixman.h> #include <math.h> jintArray tesselate(JNIEnv *env, jintArray pointArray, jbyteArray opArray, jint pointCnt, jint opCnt, jintArray xTrapArray, jint xTrapArrayLength, jint windingRule, cairo_stroke_style_t *strokeStyle, cairo_matrix_t *tr, jint clipLowX, jint clipLowY, jint clipHiX, jint clipHiY) { jint* points; jbyte* ops; if((points = (jint *) (*env)->GetPrimitiveArrayCritical(env, pointArray, NULL)) == NULL) { return xTrapArray; } if((ops = (jbyte *) (*env)->GetPrimitiveArrayCritical(env, opArray, NULL)) == NULL) { return xTrapArray; } cairo_traps_t traps; _cairo_traps_init (&traps); traps.has_limits = 1; traps.limits.p1.x = _cairo_fixed_from_double(clipLowX); traps.limits.p1.y = _cairo_fixed_from_double(clipLowY); traps.limits.p2.x = _cairo_fixed_from_double(clipHiX); traps.limits.p2.y = _cairo_fixed_from_double(clipHiY); cairo_path_buf_t buf; cairo_path_fixed_t path; buf.num_ops = opCnt; buf.num_points = pointCnt; buf.buf_size = pointCnt*2; buf.op = (unsigned char*) ops; buf.points = points; buf.next = NULL; buf.prev = &path.buf_head; path.has_current_point = 0; path.has_curve_to = 1; path.buf_tail = &buf; path.buf_head.base.next = &buf; path.buf_head.base.num_ops = 0; path.buf_head.base.num_points = 0; path.buf_head.base.buf_size = 0; if(strokeStyle == NULL) { _cairo_path_fixed_fill_to_traps (&path, windingRule, 0.1, &traps); }else { cairo_matrix_t tr_inv = *tr; cairo_matrix_invert(&tr_inv); _cairo_path_fixed_stroke_to_traps (&path, strokeStyle, tr, &tr_inv, 0.1, &traps); } (*env)->ReleasePrimitiveArrayCritical(env, pointArray, points, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, opArray, ops, JNI_ABORT); cairo_trapezoid_t *trapPtr = traps.traps; jint requiredArraySize = traps.num_traps*10 + 5; if(requiredArraySize > xTrapArrayLength) { xTrapArray = (jintArray) (*env)->NewIntArray(env, requiredArraySize); } jint* xTraps; if((xTraps = (jint *) (*env)->GetPrimitiveArrayCritical(env, xTrapArray, NULL)) == NULL) { return xTrapArray; } xTraps[0] = traps.num_traps; xTraps[1] = (jint) _cairo_fixed_to_double(traps.extents.p1.x); xTraps[2] = (jint) _cairo_fixed_to_double(traps.extents.p1.y); xTraps[3] = (jint) ceil(_cairo_fixed_to_double(traps.extents.p2.x)); xTraps[4] = (jint) ceil(_cairo_fixed_to_double(traps.extents.p2.y)); int i; int intCnt = 5; for (i = 0; i < traps.num_traps; i++) { xTraps[intCnt++] = _cairo_fixed_to_16_16(trapPtr[i].top); xTraps[intCnt++] = _cairo_fixed_to_16_16(trapPtr[i].bottom); xTraps[intCnt++] = _cairo_fixed_to_16_16(trapPtr[i].left.p1.x); xTraps[intCnt++] = _cairo_fixed_to_16_16(trapPtr[i].left.p1.y); xTraps[intCnt++] = _cairo_fixed_to_16_16(trapPtr[i].left.p2.x); xTraps[intCnt++] = _cairo_fixed_to_16_16(trapPtr[i].left.p2.y); xTraps[intCnt++] = _cairo_fixed_to_16_16(trapPtr[i].right.p1.x); xTraps[intCnt++] = _cairo_fixed_to_16_16(trapPtr[i].right.p1.y); xTraps[intCnt++] = _cairo_fixed_to_16_16(trapPtr[i].right.p2.x); xTraps[intCnt++] = _cairo_fixed_to_16_16(trapPtr[i].right.p2.y); } (*env)->ReleasePrimitiveArrayCritical(env, xTrapArray, xTraps, 0); _cairo_traps_fini(&traps); return xTrapArray; } JNIEXPORT jintArray JNICALL Java_sun_java2d_xr_CairoPathBuf_tesselateFillNative (JNIEnv *env, jclass xsd, jintArray pointArray, jbyteArray opArray, jint pointCnt, jint opCnt, jintArray xTrapArray, jint xTrapArrayLength, jint windingRule, jint clipLowX, jint clipLowY, jint clipHiX, jint clipHiY) { return tesselate(env, pointArray, opArray, pointCnt, opCnt, xTrapArray, xTrapArrayLength, windingRule, NULL, NULL, clipLowX, clipLowY, clipHiX, clipHiY); } JNIEXPORT jintArray JNICALL Java_sun_java2d_xr_CairoPathBuf_tesselateStrokeNative (JNIEnv *env, jclass xsd, jintArray pointArray, jbyteArray opArray, jint pointCnt, jint opCnt, jintArray xTrapArray, jint xTrapArrayLength, jdouble lineWidth, jint lineCap, jint lineJoin, jdouble miterLimit, jdoubleArray dashArray, jint dashCnt, jdouble dashOffset, jdouble m00, jdouble m01, jdouble m02, jdouble m10, jdouble m11, jdouble m12, jint clipLowX, jint clipLowY, jint clipHiX, jint clipHiY) { jdouble *dash = NULL; if(dashCnt > 0) { if((dash = (jdouble *) (*env)->GetPrimitiveArrayCritical(env, dashArray, NULL)) == NULL) { return xTrapArray; } } cairo_matrix_t tr; tr.xx = m00; tr.xy = m01; tr.x0 = m02; tr.yx = m10; tr.yy = m11; tr.y0 = m12; cairo_stroke_style_t style; style.line_width = lineWidth; style.line_cap = lineCap; style.line_join = lineJoin; style.miter_limit = miterLimit; style.num_dashes = dashCnt; style.dash_offset = dashOffset; style.dash = dash; jintArray result = tesselate(env, pointArray, opArray, pointCnt, opCnt, xTrapArray, xTrapArrayLength, 0, &style, &tr, clipLowX, clipLowY, clipHiX, clipHiY); if(dashCnt > 0) { (*env)->ReleasePrimitiveArrayCritical(env, dashArray, dash, JNI_ABORT); } return result; } JNIEXPORT jlong JNICALL Java_sun_java2d_xr_CairoAATileGenerator_rasterizeTrapezoidsNative (JNIEnv *env, jclass xsd, jlong maskBitPtr, jintArray xTrapArray, jintArray trapPosArray, jint trapCnt, jbyteArray bufferArray, jint xOff, jint yOff) { jint i; jint *xTraps; jint *trapPos; jbyte *buffer; if((xTraps = (jint *) (*env)->GetPrimitiveArrayCritical(env, xTrapArray, NULL)) == NULL) { return maskBitPtr; } if((trapPos = (jint *) (*env)->GetPrimitiveArrayCritical(env, trapPosArray, NULL)) == NULL) { return maskBitPtr; } if((buffer = (jbyte *) (*env)->GetPrimitiveArrayCritical(env, bufferArray, NULL)) == NULL) { return maskBitPtr; } memset(buffer, 0, 32*32); //TODO: we can optimize this, by comparing wether buffer adress stays the same. //Warning: multithreading!! // pixman_image_t *mask = pixman_image_create_bits(PIXMAN_a8, 32, 32, buffer, 32); pixman_image_t *mask = (pixman_image_t *) jlong_to_ptr(maskBitPtr); if(mask == NULL || pixman_image_get_data(mask) != buffer) { if(mask != NULL) { pixman_image_unref(mask); //printf("Old Mask Freed!\n"); } mask = pixman_image_create_bits(PIXMAN_a8, 32, 32, buffer, 32); maskBitPtr = ptr_to_jlong(mask); // printf("New Mask created!\n"); //fflush(stdout); } pixman_fixed_t xTileStart = pixman_double_to_fixed(xOff); pixman_fixed_t yTileStart = pixman_double_to_fixed(yOff); pixman_fixed_t xTileEnd = xTileStart + pixman_double_to_fixed(32); pixman_fixed_t yTileEnd = yTileStart + pixman_double_to_fixed(32); for(i=0; i < trapCnt; i++) { pixman_trapezoid_t trap; int arrayIndex = trapPos[i]*10 + 5; /* trap.top = xTraps[arrayIndex + 0]; trap.bottom = xTraps[arrayIndex + 1]; trap.left.p1.x = xTraps[arrayIndex + 2]; trap.left.p1.y = xTraps[arrayIndex + 3]; trap.left.p2.x = xTraps[arrayIndex + 4]; trap.left.p2.y = xTraps[arrayIndex + 5]; trap.right.p1.x = xTraps[arrayIndex + 6]; trap.right.p1.y = xTraps[arrayIndex + 7]; trap.right.p2.x = xTraps[arrayIndex + 8]; trap.right.p2.y = xTraps[arrayIndex + 9]; */ memcpy(&trap, &xTraps[arrayIndex], 40); //printf("top:%d, tilestart: %d", trap.top, yTileStart); //printf(" - bottom:%d, tileend %d", trap.bottom, yTileEnd); /*Clip trapezoid to mask bounds*/ if(trap.top < yTileStart) { trap.top = yTileStart; //printf("- start limited"); } if(trap.bottom > yTileEnd) { trap.bottom = yTileEnd; //printf("- bottom limited"); } if (trap.left.p1.x <= xTileStart && trap.left.p2.x <= xTileStart) { trap.left.p1.x = xTileStart; trap.left.p2.x = xTileStart; // printf("- left limited"); } if (trap.right.p1.x >= xTileEnd && trap.right.p2.x >= xTileEnd) { trap.right.p1.x = xTileEnd; trap.right.p2.x = xTileEnd; // printf("- right limited"); } // printf("\n"); // fflush(stdout); pixman_rasterize_trapezoid (mask, &trap, -xOff, -yOff); } (*env)->ReleasePrimitiveArrayCritical(env, xTrapArray, xTraps, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, trapPosArray, trapPos, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, bufferArray, buffer, 0); return maskBitPtr; } /*TODO: Manage tiles statically, not re-allocaing everything, makes that obsolete.*/ JNIEXPORT void JNICALL Java_sun_java2d_xr_CairoAATileGenerator_freePixmanImgPtr (JNIEnv *env, jclass xsd, jlong maskBitPtr) { pixman_image_t *mask = (pixman_image_t *) jlong_to_ptr(maskBitPtr); if(mask == NULL) { pixman_image_unref(mask); } } _______________________________________________ cairo mailing list cairo@... http://lists.cairographics.org/mailman/listinfo/cairo |
|
|
Re: Any chance to get trapezoids into public API?Excerpts from Clemens Eisserer's message of Sat Oct 31 10:47:22 +0000 2009:
> I am writing a Java2D plugin, which allows to use Cairo's tesselator+ > pixman's trapezoid-rasterizer for antialiased rendering. It works > quite well, however it uses a lot of cairo-internal stuff like: [snip] > I know by completly relying on cairo, I wouldn't have to mess with its > internals - however there is a certain impedance mismatch between > Java2D and Cairo and thats why I choose to use xrender back then. My answer is simple: take cairo under the freedoms of its license and incorporate a private copy into your library, and adapt to your needs. Obviously this make me quite sad. I have a grand vision that involves pushing cairo in all directions, both to improve its usage across the desktop and to improve the capabilities for it to be (indirectly) h/w accelerated. Already this means that the interfaces you currently hook into are being phased out as we find faster methods, and Java2D will continue to suffer as the focus for driver development falls elsewhere. (For instance, instead of switching from converting your RenderFillRectangles span renderer to a trapezoid based one, you could join the discussion in how we can expose a method for passing RLE spans to RENDER. And what direction we should take the hardware acceleration for 2D paths. At the moment it appears that we (the cairo/DDX developers) are the ones pushing hardest and so are focused on our use cases. Obviously I'd like to expand those use cases to include yours by encouraging your adoption of Cairo. ;-) If you have identified inadequacies in the public API or bottlenecks anywhere within cairo that prevent you from using the library. Please let us know how we can improve cairo, with profiles if possible! Sorry for not being more helpful, but I want to ensure Cairo stays focused on doing just one task and doing it well. Have fun developing Java2D, I hope you find that Cairo is useful and that you do find ways we can improve. -ickle -- Chris Wilson, Intel Open Source Technology Centre _______________________________________________ cairo mailing list cairo@... http://lists.cairographics.org/mailman/listinfo/cairo |
|
|
Re: Any chance to get trapezoids into public API?Hi Chris,
> My answer is simple: take cairo under the freedoms of its license and > incorporate a private copy into your library, and adapt to your needs. Yes, thats what I thought would be best, too. > Already this means that the interfaces you currently hook > into are being phased out as we find faster methods, and Java2D will > continue to suffer as the focus for driver development falls elsewhere. Sure, but today trapezoids seem to be the best way to push aa coverage values to the xserver. When new interfaces come up, I'll adopt to a newer cairo release. > (For instance, instead of switching from converting your > RenderFillRectangles span renderer to a trapezoid based one, you could > join the discussion in how we can expose a method for passing RLE spans > to RENDER. > And what direction we should take the hardware acceleration > for 2D paths. I only heard once that something like RLE spans are planned for render, its a welcome change. I was never a big fan of trapezoids, and all the complexity and inefficiency caused by them. Does the discussion mainly happen on IRC? > Sorry for not being more helpful, but I want to ensure Cairo stays > focused on doing just one task and doing it well. Have fun developing > Java2D, I hope you find that Cairo is useful and that you do find ways > we can improve. Thanks for beeing that helpful :) Thanks again, Clemens _______________________________________________ cairo mailing list cairo@... http://lists.cairographics.org/mailman/listinfo/cairo |
| Free embeddable forum powered by Nabble | Forum Help |