/* Heed well the words of Owen Taylor: * "Any patch that works around a render bug, or claims to, without a * specific reference to the bug filed in bugzilla.freedesktop.org will * never pass approval."
*/
#include"cairoint.h"
/** * CAIRO_HAS_XLIB_XCB_FUNCTIONS: * * Defined if Cairo has support for XCB integration with Xlib. * This macro can be used to conditionally compile backend-specific code. * * Since: 1.10
**/
/** * SECTION:cairo-xlib * @Title: XLib Surfaces * @Short_Description: X Window System rendering using XLib * @See_Also: #cairo_surface_t * * The XLib surface is used to render cairo graphics to X Window System * windows and pixmaps using the XLib library. * * Note that the XLib surface automatically takes advantage of X render extension * if it is available.
**/
/** * CAIRO_HAS_XLIB_SURFACE: * * Defined if the Xlib surface backend is available. * This macro can be used to conditionally compile backend-specific code. * * Since: 1.0
**/
/** * SECTION:cairo-xlib-xrender * @Title: XLib-XRender Backend * @Short_Description: X Window System rendering using XLib and the X Render extension * @See_Also: #cairo_surface_t * * The XLib surface is used to render cairo graphics to X Window System * windows and pixmaps using the XLib and Xrender libraries. * * Note that the XLib surface automatically takes advantage of X Render extension * if it is available.
**/
/** * CAIRO_HAS_XLIB_XRENDER_SURFACE: * * Defined if the XLib/XRender surface functions are available. * This macro can be used to conditionally compile backend-specific code. * * Since: 1.6
**/
/* Xlib doesn't define a typedef, so define one ourselves */ typedefint (*cairo_xlib_error_func_t) (Display *display,
XErrorEvent *event);
static cairo_surface_t *
_cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
Drawable drawable,
Visual *visual,
XRenderPictFormat *xrender_format, int width, int height, int depth);
/* * Instead of taking two round trips for each blending request, * assume that if a particular drawable fails GetImage that it will * fail for a "while"; use temporary pixmaps to avoid the errors
*/
/* XXX Consider searching through the list of known cairo_visual_t for * the reverse mapping.
*/
for (d = 0; d < screen->ndepths; d++) {
Depth *d_info = &screen->depths[d];
if (d_info->depth != xrender_format->depth) continue;
for (v = 0; v < d_info->nvisuals; v++) {
Visual *visual = &d_info->visuals[v];
switch (visual->class) { case TrueColor: if (xrender_format->type != PictTypeDirect) continue; break;
case DirectColor: /* Prefer TrueColor to DirectColor. * (XRenderFindVisualFormat considers both TrueColor and DirectColor * Visuals to match the same PictFormat.)
*/ continue;
case StaticGray: case GrayScale: case StaticColor: case PseudoColor: if (xrender_format->type != PictTypeIndexed) continue; break;
}
if (xrender_format ==
XRenderFindVisualFormat (DisplayOfScreen(screen), visual)) return visual;
}
}
/* This only happens when using a non-Render server. Let's punt
* and say there's no alpha here. */ if (xrender_format == NULL) return CAIRO_CONTENT_COLOR;
content = 0; if (xrender_format->direct.alphaMask)
content |= CAIRO_CONTENT_ALPHA; if (xrender_format->direct.redMask |
xrender_format->direct.greenMask |
xrender_format->direct.blueMask)
content |= CAIRO_CONTENT_COLOR;
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) return NULL;
if (width == 0 || height == 0) return NULL;
if (_cairo_xlib_display_acquire (src->base.device, &display)) return NULL;
/* If we never found an XRenderFormat or if it isn't compatible * with the content being requested, then we fallback to just * constructing a cairo_format_t instead, (which will fairly * arbitrarily pick a visual/depth for the similar surface.
*/
xrender_format = NULL; if (src->xrender_format &&
_xrender_format_to_content (src->xrender_format) == content)
{
xrender_format = src->xrender_format;
} if (xrender_format == NULL) {
xrender_format =
_cairo_xlib_display_get_xrender_format (display,
_cairo_format_from_content (content));
} if (xrender_format) {
Visual *visual;
/* We've got a compatible XRenderFormat now, which means the * similar surface will match the existing surface as closely in
* visual/depth etc. as possible. */
pix = XCreatePixmap (display->display, src->drawable,
width, height, xrender_format->depth);
/* No compatible XRenderFormat, see if we can make an ordinary pixmap,
* so that we can still accelerate blits with XCopyArea(). */ if (content != CAIRO_CONTENT_COLOR) {
cairo_device_release (&display->base); return NULL;
}
if (surface->embedded_source.picture)
XRenderFreePicture (display->display, surface->embedded_source.picture); if (surface->picture)
XRenderFreePicture (display->display, surface->picture);
_cairo_xlib_surface_discard_shm (surface);
if (surface->owns_pixmap)
XFreePixmap (display->display, surface->drawable);
staticvoid
_swap_ximage_bits (XImage *ximage)
{ int i, j; char *line = ximage->data; int unit = ximage->bitmap_unit; int line_bytes = ((ximage->width + unit - 1) & ~(unit - 1)) / 8;
for (i = line_bytes; i; i--) { char b = *p;
b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55);
b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33);
b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f);
*p = b;
p++;
}
line += ximage->bytes_per_line;
}
}
staticvoid
_swap_ximage_to_native (XImage *ximage)
{ int unit_bytes = 0; int native_byte_order = _cairo_is_little_endian () ? LSBFirst : MSBFirst;
if (ximage->bits_per_pixel == 1 &&
ximage->bitmap_bit_order != native_byte_order)
{
_swap_ximage_bits (ximage); if (ximage->bitmap_bit_order == ximage->byte_order) return;
}
if (ximage->byte_order == native_byte_order) return;
switch (ximage->bits_per_pixel) { case 1:
unit_bytes = ximage->bitmap_unit / 8; break; case 4:
_swap_ximage_nibbles (ximage); /* fall-through */ case 8: case 16: case 20: case 24: case 28: case 30: case 32:
unit_bytes = (ximage->bits_per_pixel + 7) / 8; break; default: /* This could be hit on some rare but possible cases. */
ASSERT_NOT_REACHED;
}
switch (unit_bytes) { case 1: break; case 2:
_swap_ximage_2bytes (ximage); break; case 3:
_swap_ximage_3bytes (ximage); break; case 4:
_swap_ximage_4bytes (ximage); break; default:
ASSERT_NOT_REACHED;
}
}
/* Given a mask, (with a single sequence of contiguous 1 bits), return * the number of 1 bits in 'width' and the number of 0 bits to its
* right in 'shift'. */ staticvoid
_characterize_field (uint32_t mask, int *width, int *shift)
{
*width = _cairo_popcount (mask); /* The final '& 31' is to force a 0 mask to result in 0 shift. */
*shift = _cairo_popcount ((mask - 1) & ~mask) & 31;
}
/* Convert a field of 'width' bits to 'new_width' bits with correct
* rounding. */ staticinline uint32_t
_resize_field (uint32_t field, int width, int new_width)
{ if (width == 0) return 0;
if (width >= new_width) { return field >> (width - new_width);
} else {
uint32_t result = field << (new_width - width);
while (width < new_width) {
result |= result >> width;
width <<= 1;
} return result;
}
}
staticinline uint32_t
_adjust_field (uint32_t field, int adjustment)
{ return MIN (255, MAX(0, (int)field + adjustment));
}
/* Given a shifted field value, (described by 'width' and 'shift), * resize it 8-bits and return that value. * * Note that the original field value must not have any non-field bits * set.
*/ staticinline uint32_t
_field_to_8 (uint32_t field, int width, int shift)
{ return _resize_field (field >> shift, width, 8);
}
staticinline uint32_t
_field_to_8_undither (uint32_t field, int width, int shift, int dither_adjustment)
{ return _adjust_field (_field_to_8 (field, width, shift), - dither_adjustment>>width);
}
/* Given an 8-bit value, convert it to a field of 'width', shift it up
* to 'shift, and return it. */ staticinline uint32_t
_field_from_8 (uint32_t field, int width, int shift)
{ return _resize_field (field, 8, width) << shift;
}
staticinline uint32_t
_field_from_8_dither (uint32_t field, int width, int shift,
int8_t dither_adjustment)
{ return _field_from_8 (_adjust_field (field, dither_adjustment>>width), width, shift);
}
/* If we get an error, the surface must have been a window, * so retry with the safe code path.
*/ if (!ximage)
surface->use_pixmap = CAIRO_ASSUME_PIXMAP;
} else {
surface->use_pixmap--;
ximage = NULL;
}
if (ximage == NULL) { /* XGetImage from a window is dangerous because it can * produce errors if the window is unmapped or partially * outside the screen. We could check for errors and * retry, but to keep things simple, we just create a * temporary pixmap
*/
Pixmap pixmap;
GC gc;
status = _cairo_xlib_surface_get_gc (display, surface, &gc); if (unlikely (status)) goto BAIL;
if (ximage == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY); goto BAIL;
}
}
_swap_ximage_to_native (ximage);
/* We can't use pixman to simply write to image if: * (a) the pixels are not appropriately aligned, * (b) pixman does not the pixel format, or * (c) if the image is palettized and we need to convert.
*/ if (pixman_format &&
ximage->bitmap_unit == 32 && ximage->bitmap_pad == 32 &&
(surface->visual == NULL || surface->visual->class == TrueColor))
{
image = (cairo_image_surface_t*)
_cairo_image_surface_create_with_pixman_format ((unsignedchar *) ximage->data,
pixman_format,
ximage->width,
ximage->height,
ximage->bytes_per_line);
status = image->base.status; if (unlikely (status)) goto BAIL;
/* Let the surface take ownership of the data */
_cairo_image_surface_assume_ownership_of_data (image);
ximage->data = NULL;
} else { /* The visual we are dealing with is not supported by the * standard pixman formats. So we must first convert the data
* to a supported format. */
cairo_format_t format; unsignedchar *data;
uint32_t *row;
uint32_t in_pixel, out_pixel; unsignedint rowstride;
uint32_t a_mask=0, r_mask=0, g_mask=0, b_mask=0; int a_width=0, r_width=0, g_width=0, b_width=0; int a_shift=0, r_shift=0, g_shift=0, b_shift=0; int x, y, x0, y0, x_off, y_off;
cairo_xlib_visual_info_t *visual_info = NULL;
if (has_color) { if (has_alpha) {
format = CAIRO_FORMAT_ARGB32;
} else {
format = CAIRO_FORMAT_RGB24;
}
} else { /* XXX: Using CAIRO_FORMAT_A8 here would be more * efficient, but would require slightly different code in * the image conversion to put the alpha channel values
* into the right place. */
format = CAIRO_FORMAT_ARGB32;
}
if (display->force_precision != -1)
precision = display->force_precision; elseswitch (antialias) { default: case CAIRO_ANTIALIAS_DEFAULT: case CAIRO_ANTIALIAS_GRAY: case CAIRO_ANTIALIAS_NONE: case CAIRO_ANTIALIAS_FAST: case CAIRO_ANTIALIAS_GOOD:
precision = PolyModeImprecise; break; case CAIRO_ANTIALIAS_BEST: case CAIRO_ANTIALIAS_SUBPIXEL:
precision = PolyModePrecise; break;
}
if (surface->precision != precision) {
XRenderPictureAttributes pa;
/* If the incoming image has no alpha channel, then the input * is opaque and the output should have the maximum alpha value. * For all other channels, their absence implies 0.
*/ if (image_masks.alpha_mask == 0x0)
a = 0xff; else
a = _field_to_8 (in_pixel & image_masks.alpha_mask, i_a_width, i_a_shift);
r = _field_to_8 (in_pixel & image_masks.red_mask , i_r_width, i_r_shift);
g = _field_to_8 (in_pixel & image_masks.green_mask, i_g_width, i_g_shift);
b = _field_to_8 (in_pixel & image_masks.blue_mask , i_b_width, i_b_shift);
/** * _cairo_surface_is_xlib: * @surface: a #cairo_surface_t * * Checks if a surface is a #cairo_xlib_surface_t * * Return value: True if the surface is an xlib surface
**/ static cairo_bool_t
_cairo_surface_is_xlib (cairo_surface_t *surface)
{ return surface->backend == &cairo_xlib_surface_backend;
}
static cairo_surface_t *
_cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
Drawable drawable,
Visual *visual,
XRenderPictFormat *xrender_format, int width, int height, int depth)
{
cairo_xlib_surface_t *surface;
cairo_xlib_display_t *display;
cairo_status_t status;
if (depth == 0) { if (xrender_format) {
depth = xrender_format->depth;
if (visual == DefaultVisualOfScreen (scr)) {
depth = DefaultDepthOfScreen (scr);
} else { int j, k;
/* This is ugly, but we have to walk over all visuals * for the display to find the correct depth.
*/
depth = 0; for (j = 0; j < scr->ndepths; j++) {
Depth *d = &scr->depths[j]; for (k = 0; k < d->nvisuals; k++) { if (&d->visuals[k] == visual) {
depth = d->depth; goto found;
}
}
}
}
}
if (depth == 0) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
/* * Compute the pixel format masks from either a XrenderFormat or * else from a visual; failing that we assume the drawable is an * alpha-only pixmap as it could only have been created that way * through the cairo_xlib_surface_create_for_bitmap function.
*/ if (xrender_format) {
surface->a_mask = (unsignedlong)
surface->xrender_format->direct.alphaMask
<< surface->xrender_format->direct.alpha;
surface->r_mask = (unsignedlong)
surface->xrender_format->direct.redMask
<< surface->xrender_format->direct.red;
surface->g_mask = (unsignedlong)
surface->xrender_format->direct.greenMask
<< surface->xrender_format->direct.green;
surface->b_mask = (unsignedlong)
surface->xrender_format->direct.blueMask
<< surface->xrender_format->direct.blue;
} elseif (visual) {
surface->a_mask = 0;
surface->r_mask = visual->red_mask;
surface->g_mask = visual->green_mask;
surface->b_mask = visual->blue_mask;
} else { if (depth < 32)
surface->a_mask = (1 << depth) - 1; else
surface->a_mask = 0xffffffff;
surface->r_mask = 0;
surface->g_mask = 0;
surface->b_mask = 0;
}
for (d = 0; d < screen->ndepths; d++) {
Depth *depth;
depth = &screen->depths[d]; for (v = 0; v < depth->nvisuals; v++) if (visual == &depth->visuals[v]) return screen;
}
}
return NULL;
}
static cairo_bool_t valid_size (int width, int height)
{ /* Note: the minimum surface size allowed in the X protocol is 1x1. * However, as we historically did not check the minimum size we * allowed applications to lie and set the correct size later (one hopes). * To preserve compatibility we must allow applications to use * 0x0 surfaces.
*/ return (width >= 0 && width <= XLIB_COORD_MAX &&
height >= 0 && height <= XLIB_COORD_MAX);
}
/** * cairo_xlib_surface_create: * @dpy: an X Display * @drawable: an X Drawable, (a Pixmap or a Window) * @visual: the visual to use for drawing to @drawable. The depth * of the visual must match the depth of the drawable. * Currently, only TrueColor visuals are fully supported. * @width: the current width of @drawable. * @height: the current height of @drawable. * * Creates an Xlib surface that draws to the given drawable. * The way that colors are represented in the drawable is specified * by the provided visual. * * Note: If @drawable is a Window, then the function * cairo_xlib_surface_set_size() must be called whenever the size of the * window changes. * * When @drawable is a Window containing child windows then drawing to * the created surface will be clipped by those child windows. When * the created surface is used as a source, the contents of the * children will be included. * * Return value: the newly created surface * * Since: 1.0
**/
cairo_surface_t *
cairo_xlib_surface_create (Display *dpy,
Drawable drawable,
Visual *visual, int width, int height)
{
Screen *scr;
cairo_xlib_screen_t *screen;
cairo_status_t status;
if (! valid_size (width, height)) { /* you're lying, and you know it! */ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
}
/** * cairo_xlib_surface_create_for_bitmap: * @dpy: an X Display * @bitmap: an X Drawable, (a depth-1 Pixmap) * @screen: the X Screen associated with @bitmap * @width: the current width of @bitmap. * @height: the current height of @bitmap. * * Creates an Xlib surface that draws to the given bitmap. * This will be drawn to as a %CAIRO_FORMAT_A1 object. * * Return value: the newly created surface * * Since: 1.0
**/
cairo_surface_t *
cairo_xlib_surface_create_for_bitmap (Display *dpy,
Pixmap bitmap,
Screen *scr, int width, int height)
{
cairo_xlib_screen_t *screen;
cairo_status_t status;
if (! valid_size (width, height)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
status = _cairo_xlib_screen_get (dpy, scr, &screen); if (unlikely (status)) return _cairo_surface_create_in_error (status);
#if CAIRO_HAS_XLIB_XRENDER_SURFACE /** * cairo_xlib_surface_create_with_xrender_format: * @dpy: an X Display * @drawable: an X Drawable, (a Pixmap or a Window) * @screen: the X Screen associated with @drawable * @format: the picture format to use for drawing to @drawable. The depth * of @format must match the depth of the drawable. * @width: the current width of @drawable. * @height: the current height of @drawable. * * Creates an Xlib surface that draws to the given drawable. * The way that colors are represented in the drawable is specified * by the provided picture format. * * Note: If @drawable is a Window, then the function * cairo_xlib_surface_set_size() must be called whenever the size of the * window changes. * * Return value: the newly created surface * * Since: 1.0
**/
cairo_surface_t *
cairo_xlib_surface_create_with_xrender_format (Display *dpy,
Drawable drawable,
Screen *scr,
XRenderPictFormat *format, int width, int height)
{
cairo_xlib_screen_t *screen;
cairo_status_t status;
if (! valid_size (width, height)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
status = _cairo_xlib_screen_get (dpy, scr, &screen); if (unlikely (status)) return _cairo_surface_create_in_error (status);
/** * cairo_xlib_surface_get_xrender_format: * @surface: an xlib surface * * Gets the X Render picture format that @surface uses for rendering with the * X Render extension. If the surface was created by * cairo_xlib_surface_create_with_xrender_format() originally, the return * value is the format passed to that constructor. * * Return value: the XRenderPictFormat* associated with @surface, * or %NULL if the surface is not an xlib surface * or if the X Render extension is not available. * * Since: 1.6
**/
XRenderPictFormat *
cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface)
{
cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface;
/* Throw an error for a non-xlib surface */ if (! _cairo_surface_is_xlib (surface)) {
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); return NULL;
}
return xlib_surface->xrender_format;
} #endif
/** * cairo_xlib_surface_set_size: * @surface: a #cairo_surface_t for the XLib backend * @width: the new width of the surface * @height: the new height of the surface * * Informs cairo of the new size of the X Drawable underlying the * surface. For a surface created for a Window (rather than a Pixmap), * this function must be called each time the size of the window * changes. (For a subwindow, you are normally resizing the window * yourself, but for a toplevel window, it is necessary to listen for * ConfigureNotify events.) * * A Pixmap can never change size, so it is never necessary to call * this function on a surface created for a Pixmap. * * Since: 1.0
**/ void
cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface, int width, int height)
{
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
cairo_status_t status;
if (unlikely (abstract_surface->status)) return; if (unlikely (abstract_surface->finished)) {
_cairo_surface_set_error (abstract_surface,
_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); return;
}
/** * cairo_xlib_surface_set_drawable: * @surface: a #cairo_surface_t for the XLib backend * @drawable: the new drawable for the surface * @width: the width of the new drawable * @height: the height of the new drawable * * Informs cairo of a new X Drawable underlying the * surface. The drawable must match the display, screen * and format of the existing drawable or the application * will get X protocol errors and will probably terminate. * No checks are done by this function to ensure this * compatibility. * * Since: 1.0
**/ void
cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface,
Drawable drawable, int width, int height)
{
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *)abstract_surface;
cairo_status_t status;
if (unlikely (abstract_surface->status)) return; if (unlikely (abstract_surface->finished)) {
status = _cairo_surface_set_error (abstract_surface,
_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); return;
}
if (! _cairo_surface_is_xlib (abstract_surface)) {
status = _cairo_surface_set_error (abstract_surface,
_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); return;
}
if (! valid_size (width, height)) {
status = _cairo_surface_set_error (abstract_surface,
_cairo_error (CAIRO_STATUS_INVALID_SIZE)); return;
}
/* XXX: and what about this case? */ if (surface->owns_pixmap) return;
status = _cairo_surface_flush (abstract_surface, 0); if (unlikely (status)) {
_cairo_surface_set_error (abstract_surface, status); return;
}
if (surface->drawable != drawable) {
cairo_xlib_display_t *display;
status = _cairo_xlib_display_acquire (surface->base.device, &display); if (unlikely (status)) return;
/** * cairo_xlib_surface_get_display: * @surface: a #cairo_xlib_surface_t * * Get the X Display for the underlying X Drawable. * * Return value: the display. * * Since: 1.2
**/
Display *
cairo_xlib_surface_get_display (cairo_surface_t *abstract_surface)
{ if (! _cairo_surface_is_xlib (abstract_surface)) {
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); return NULL;
}
/** * cairo_xlib_surface_get_drawable: * @surface: a #cairo_xlib_surface_t * * Get the underlying X Drawable used for the surface. * * Return value: the drawable. * * Since: 1.2
**/
Drawable
cairo_xlib_surface_get_drawable (cairo_surface_t *abstract_surface)
{
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
if (! _cairo_surface_is_xlib (abstract_surface)) {
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); return 0;
}
return surface->drawable;
}
/** * cairo_xlib_surface_get_screen: * @surface: a #cairo_xlib_surface_t * * Get the X Screen for the underlying X Drawable. * * Return value: the screen. * * Since: 1.2
**/
Screen *
cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface)
{
cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
if (! _cairo_surface_is_xlib (abstract_surface)) {
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); return NULL;
}
return surface->screen->screen;
}
/** * cairo_xlib_surface_get_visual: * @surface: a #cairo_xlib_surface_t * * Gets the X Visual associated with @surface, suitable for use with the * underlying X Drawable. If @surface was created by * cairo_xlib_surface_create(), the return value is the Visual passed to that * constructor. * * Return value: the Visual or %NULL if there is no appropriate Visual for * @surface. * * Since: 1.2
**/
Visual *
cairo_xlib_surface_get_visual (cairo_surface_t *surface)
{
cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface;
if (! _cairo_surface_is_xlib (surface)) {
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); return NULL;
}
return xlib_surface->visual;
}
/** * cairo_xlib_surface_get_depth: * @surface: a #cairo_xlib_surface_t *
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.59 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.