diff options
-rw-r--r-- | src/dispextern.h | 11 | ||||
-rw-r--r-- | src/haiku_draw_support.cc | 132 | ||||
-rw-r--r-- | src/haiku_support.h | 11 | ||||
-rw-r--r-- | src/haikuterm.c | 74 | ||||
-rw-r--r-- | src/image.c | 104 |
5 files changed, 159 insertions, 173 deletions
diff --git a/src/dispextern.h b/src/dispextern.h index 8bcd13dbb6d..797b4730cd3 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3070,7 +3070,7 @@ struct image Non-NULL means it and its Pixmap counterpart may be out of sync and the latter is outdated. NULL means the X image has been synchronized to Pixmap. */ - XImage *ximg, *mask_img; +v XImage *ximg, *mask_img; # if !defined USE_CAIRO && defined HAVE_XRENDER /* Picture versions of pixmap and mask for compositing. */ @@ -3085,12 +3085,11 @@ struct image XFORM xform; #endif #ifdef HAVE_HAIKU - /* Non-zero if the image has not yet been transformed for display. */ - int have_be_transforms_p; + /* The affine transformation to apply to this image. */ + double transform[3][3]; - double be_rotate; - double be_scale_x; - double be_scale_y; + /* The original width and height of the image. */ + int original_width, original_height; #endif /* Colors allocated for this image, if any. Allocated via xmalloc. */ diff --git a/src/haiku_draw_support.cc b/src/haiku_draw_support.cc index f0cc084bb37..768ffdabf82 100644 --- a/src/haiku_draw_support.cc +++ b/src/haiku_draw_support.cc @@ -357,134 +357,64 @@ BView_DrawBitmapWithEraseOp (void *view, void *bitmap, int x, } void -BView_DrawMask (void *src, void *view, - int x, int y, int width, int height, - int vx, int vy, int vwidth, int vheight, - uint32_t color) +be_draw_image_mask (void *src, void *view, int x, int y, int width, + int height, int vx, int vy, int vwidth, int vheight, + uint32_t color) { BBitmap *source = (BBitmap *) src; BBitmap bm (source->Bounds (), B_RGBA32); BRect bounds = bm.Bounds (); + int bx, by, bit; + BView *vw; if (bm.InitCheck () != B_OK) return; - for (int y = 0; y < BE_RECT_HEIGHT (bounds); ++y) + + /* Fill the background color or transparency into the bitmap, + depending on the value of the mask. */ + for (by = 0; by < BE_RECT_HEIGHT (bounds); ++by) { - for (int x = 0; x < BE_RECT_WIDTH (bounds); ++x) + for (bx = 0; bx < BE_RECT_WIDTH (bounds); ++bx) { - int bit = haiku_get_pixel ((void *) source, x, y); + bit = haiku_get_pixel ((void *) source, bx, by); if (!bit) - haiku_put_pixel ((void *) &bm, x, y, ((uint32_t) 255 << 24) | color); + haiku_put_pixel ((void *) &bm, bx, by, + ((uint32_t) 255 << 24) | color); else - haiku_put_pixel ((void *) &bm, x, y, 0); + haiku_put_pixel ((void *) &bm, bx, by, 0); } } - BView *vw = get_view (view); + + vw = get_view (view); vw->SetDrawingMode (B_OP_OVER); vw->DrawBitmap (&bm, BRect (x, y, x + width - 1, y + height - 1), BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1)); vw->SetDrawingMode (B_OP_COPY); } -static BBitmap * -rotate_bitmap_270 (BBitmap *bmp) -{ - BRect r = bmp->Bounds (); - BBitmap *bm = new BBitmap (BRect (r.top, r.left, r.bottom, r.right), - bmp->ColorSpace (), true); - if (bm->InitCheck () != B_OK) - gui_abort ("Failed to init bitmap for rotate"); - int w = BE_RECT_WIDTH (r); - int h = BE_RECT_HEIGHT (r); - - for (int y = 0; y < h; ++y) - for (int x = 0; x < w; ++x) - haiku_put_pixel ((void *) bm, y, w - x - 1, - haiku_get_pixel ((void *) bmp, x, y)); - - return bm; -} - -static BBitmap * -rotate_bitmap_90 (BBitmap *bmp) +void +be_apply_affine_transform (void *view, double m0, double m1, double tx, + double m2, double m3, double ty) { - BRect r = bmp->Bounds (); - BBitmap *bm = new BBitmap (BRect (r.top, r.left, r.bottom, r.right), - bmp->ColorSpace (), true); - if (bm->InitCheck () != B_OK) - gui_abort ("Failed to init bitmap for rotate"); - int w = BE_RECT_WIDTH (r); - int h = BE_RECT_HEIGHT (r); + BAffineTransform transform (m0, m2, m1, m3, tx, ty); - for (int y = 0; y < h; ++y) - for (int x = 0; x < w; ++x) - haiku_put_pixel ((void *) bm, h - y - 1, x, - haiku_get_pixel ((void *) bmp, x, y)); - - return bm; + get_view (view)->SetTransform (transform); } -void * -BBitmap_transform_bitmap (void *bitmap, void *mask, uint32_t m_color, - double rot, int desw, int desh) +void +be_apply_inverse_transform (double (*matrix3x3)[3], int x, int y, + int *x_out, int *y_out) { - BBitmap *bm = (BBitmap *) bitmap; - BBitmap *mk = (BBitmap *) mask; - int copied_p = 0; + BAffineTransform transform (matrix3x3[0][0], matrix3x3[1][0], + matrix3x3[0][1], matrix3x3[1][1], + matrix3x3[0][2], matrix3x3[1][2]); + BPoint point (x, y); - if (rot == 90) - { - copied_p = 1; - bm = rotate_bitmap_90 (bm); - if (mk) - mk = rotate_bitmap_90 (mk); - } - - if (rot == 270) - { - copied_p = 1; - bm = rotate_bitmap_270 (bm); - if (mk) - mk = rotate_bitmap_270 (mk); - } - - BRect n = BRect (0, 0, desw - 1, desh - 1); - BView vw (n, NULL, B_FOLLOW_NONE, 0); - BBitmap *dst = new BBitmap (n, bm->ColorSpace (), true); - if (dst->InitCheck () != B_OK) - if (bm->InitCheck () != B_OK) - gui_abort ("Failed to init bitmap for scale"); - dst->AddChild (&vw); + transform.ApplyInverse (&point); - if (!vw.LockLooper ()) - gui_abort ("Failed to lock offscreen view for scale"); - - if (rot != 90 && rot != 270) - { - BAffineTransform tr; - tr.RotateBy (BPoint (desw / 2, desh / 2), rot * M_PI / 180.0); - vw.SetTransform (tr); - } - - vw.MovePenTo (0, 0); - vw.DrawBitmap (bm, n); - if (mk) - { - BRect k = mk->Bounds (); - BView_DrawMask ((void *) mk, (void *) &vw, - 0, 0, BE_RECT_WIDTH (k), - BE_RECT_HEIGHT (k), - 0, 0, desw, desh, m_color); - } - vw.Sync (); - vw.RemoveSelf (); - - if (copied_p) - delete bm; - if (copied_p && mk) - delete mk; - return dst; + *x_out = std::floor (point.x); + *y_out = std::floor (point.y); } void diff --git a/src/haiku_support.h b/src/haiku_support.h index 3484fe0bbec..fcdf6bcb154 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -560,8 +560,6 @@ extern void BView_InvertRect (void *, int, int, int, int); extern void BView_DrawBitmap (void *, void *, int, int, int, int, int, int, int, int); extern void BView_DrawBitmapWithEraseOp (void *, void *, int, int, int, int); -extern void BView_DrawMask (void *, void *, int, int, int, int, int, int, - int, int, uint32_t); extern void BView_DrawBitmapTiled (void *, void *, int, int, int, int, int, int, int, int); @@ -570,8 +568,13 @@ extern void BView_set_view_cursor (void *, void *); extern void BView_move_frame (void *, int, int, int, int); extern void BView_scroll_bar_update (void *, int, int, int, int, bool); -extern void *BBitmap_transform_bitmap (void *, void *, uint32_t, double, - int, int); +extern void *be_transform_bitmap (void *, void *, uint32_t, double, + int, int, bool); +extern void be_apply_affine_transform (void *, double, double, double, + double, double, double); +extern void be_apply_inverse_transform (double (*)[3], int, int, int *, int *); +extern void be_draw_image_mask (void *, void *, int, int, int, int, int, int, + int, int, uint32_t); extern void be_get_display_resolution (double *, double *); extern void be_get_screen_dimensions (int *, int *); diff --git a/src/haikuterm.c b/src/haikuterm.c index a90955ebe73..7c307afa32e 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -1630,6 +1630,14 @@ haiku_draw_image_relief (struct glyph_string *s) } static void +haiku_translate_transform (double (*transform)[3], double dx, + double dy) +{ + transform[0][2] += dx; + transform[1][2] += dy; +} + +static void haiku_draw_image_glyph_string (struct glyph_string *s) { struct face *face = s->face; @@ -1640,6 +1648,7 @@ haiku_draw_image_glyph_string (struct glyph_string *s) struct haiku_rect nr; Emacs_Rectangle cr, ir, r; unsigned long background; + double image_transform[3][3]; height = s->height; if (s->slice.y == 0) @@ -1701,34 +1710,51 @@ haiku_draw_image_glyph_string (struct glyph_string *s) if (gui_intersect_rectangles (&cr, &ir, &r)) { - if (s->img->have_be_transforms_p) - { - bitmap = BBitmap_transform_bitmap (bitmap, - s->img->mask, - face->background, - s->img->be_rotate, - s->img->width, - s->img->height); - mask = NULL; - } + memcpy (&image_transform, &s->img->transform, + sizeof image_transform); - BView_DrawBitmap (view, bitmap, - s->slice.x + r.x - x, - s->slice.y + r.y - y, - r.width, r.height, - r.x, r.y, r.width, r.height); - if (mask) + if (s->slice.x != x || s->slice.y != y + || s->slice.width != s->img->width + || s->slice.height != s->img->height) { - BView_DrawMask (mask, view, - s->slice.x + r.x - x, - s->slice.y + r.y - y, - r.width, r.height, - r.x, r.y, r.width, r.height, - face->background); + BView_StartClip (view); + BView_ClipToRect (view, r.x, r.y, r.width, r.height); } - if (s->img->have_be_transforms_p) - BBitmap_free (bitmap); + haiku_translate_transform (image_transform, + x - s->slice.x, + y - s->slice.y); + + be_apply_affine_transform (view, + image_transform[0][0], + image_transform[0][1], + image_transform[0][2], + image_transform[1][0], + image_transform[1][1], + image_transform[1][2]); + + BView_DrawBitmap (view, bitmap, 0, 0, + s->img->original_width, + s->img->original_height, + 0, 0, + s->img->original_width, + s->img->original_height); + + if (mask) + be_draw_image_mask (mask, view, 0, 0, + s->img->original_width, + s->img->original_height, + 0, 0, + s->img->original_width, + s->img->original_height, + face->background); + + if (s->slice.x != x || s->slice.y != y + || s->slice.width != s->img->width + || s->slice.height != s->img->height) + BView_EndClip (view); + + be_apply_affine_transform (view, 1, 0, 0, 0, 1, 0); } if (!s->img->mask) diff --git a/src/image.c b/src/image.c index 0e4b2e0f62a..5e98945df50 100644 --- a/src/image.c +++ b/src/image.c @@ -2503,17 +2503,17 @@ compute_image_size (double width, double height, finally move the origin back to the top left of the image, which may now be a different corner. - Note that different GUI backends (X, Cairo, w32, NS) want the - transform matrix defined as transform from the original image to - the transformed image, while others want the matrix to describe the - transform of the space, which boils down to inverting the matrix. + Note that different GUI backends (X, Cairo, w32, NS, Haiku) want + the transform matrix defined as transform from the original image + to the transformed image, while others want the matrix to describe + the transform of the space, which boils down to inverting the + matrix. It's possible to pre-calculate the matrix multiplications and just generate one transform matrix that will do everything we need in a single step, but the maths for each element is much more complex and performing the steps separately makes for more readable code. */ -#ifndef HAVE_HAIKU typedef double matrix3x3[3][3]; static void @@ -2528,7 +2528,6 @@ matrix3x3_mult (matrix3x3 a, matrix3x3 b, matrix3x3 result) result[i][j] = sum; } } -#endif /* not HAVE_HAIKU */ static void compute_image_rotation (struct image *img, double *rotation) @@ -2553,6 +2552,21 @@ compute_image_rotation (struct image *img, double *rotation) static void image_set_transform (struct frame *f, struct image *img) { + bool flip; + +#if defined HAVE_HAIKU + matrix3x3 identity = { + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 }, + }; + + img->original_width = img->width; + img->original_height = img->height; + + memcpy (&img->transform, identity, sizeof identity); +#endif + # if (defined HAVE_IMAGEMAGICK \ && !defined DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE) /* ImageMagick images already have the correct transform. */ @@ -2588,11 +2602,8 @@ image_set_transform (struct frame *f, struct image *img) compute_image_rotation (img, &rotation); /* Determine flipping. */ - bool flip; - Lisp_Object m = image_spec_value (img->spec, QCflip, NULL); - flip = !NILP (m); + flip = !NILP (image_spec_value (img->spec, QCflip, NULL)); -#ifndef HAVE_HAIKU # if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS /* We want scale up operations to use a nearest neighbor filter to show real pixels instead of munging them, but scale down @@ -2616,7 +2627,7 @@ image_set_transform (struct frame *f, struct image *img) : img->width / (double) width), [1][1] = (!IEEE_FLOATING_POINT && height == 0 ? DBL_MAX : img->height / (double) height), -# elif defined HAVE_NTGUI || defined HAVE_NS +# elif defined HAVE_NTGUI || defined HAVE_NS || defined HAVE_HAIKU [0][0] = (!IEEE_FLOATING_POINT && img->width == 0 ? DBL_MAX : width / (double) img->width), [1][1] = (!IEEE_FLOATING_POINT && img->height == 0 ? DBL_MAX @@ -2631,12 +2642,23 @@ image_set_transform (struct frame *f, struct image *img) /* Perform rotation transformation. */ int rotate_flag = -1; + + /* Haiku needs this, since the transformation is done on the basis + of the view, and not the image. */ +#ifdef HAVE_HAIKU + int extra_tx, extra_ty; + + extra_tx = 0; + extra_ty = 0; +#endif + if (rotation == 0 && !flip) rotate_flag = 0; else { # if (defined USE_CAIRO || defined HAVE_XRENDER \ - || defined HAVE_NTGUI || defined HAVE_NS) + || defined HAVE_NTGUI || defined HAVE_NS \ + || defined HAVE_HAIKU) int cos_r, sin_r; if (rotation == 0) { @@ -2648,6 +2670,11 @@ image_set_transform (struct frame *f, struct image *img) cos_r = 1; sin_r = 0; rotate_flag = 1; + +#ifdef HAVE_HAIKU + extra_tx = width; + extra_ty = 0; +#endif } else if (rotation == 90) { @@ -2656,12 +2683,24 @@ image_set_transform (struct frame *f, struct image *img) cos_r = 0; sin_r = 1; rotate_flag = 1; + +#ifdef HAVE_HAIKU + if (!flip) + extra_ty = height; + extra_tx = 0; +#endif } else if (rotation == 180) { cos_r = -1; sin_r = 0; rotate_flag = 1; + +#ifdef HAVE_HAIKU + if (!flip) + extra_tx = width; + extra_ty = height; +#endif } else if (rotation == 270) { @@ -2670,6 +2709,13 @@ image_set_transform (struct frame *f, struct image *img) cos_r = 0; sin_r = -1; rotate_flag = 1; + +#ifdef HAVE_HAIKU + extra_tx = width; + + if (flip) + extra_ty = height; +#endif } if (0 < rotate_flag) @@ -2779,35 +2825,17 @@ image_set_transform (struct frame *f, struct image *img) img->xform.eM22 = matrix[1][1]; img->xform.eDx = matrix[2][0]; img->xform.eDy = matrix[2][1]; -# endif -#else - if (rotation != 0 && - rotation != 90 && - rotation != 180 && - rotation != 270 && - rotation != 360) - { - image_error ("No native support for rotation by %g degrees", - make_float (rotation)); - return; - } - - rotation = fmod (rotation, 360.0); +# elif defined HAVE_HAIKU + /* Store the transform in the struct image for later. */ + memcpy (&img->transform, &matrix, sizeof matrix); - if (rotation == 90 || rotation == 270) + /* Also add the extra translations. */ + if (rotate_flag) { - int w = width; - width = height; - height = w; + img->transform[0][2] = extra_tx; + img->transform[1][2] = extra_ty; } - - img->have_be_transforms_p = rotation != 0 || (img->width != width) || (img->height != height); - img->be_rotate = rotation; - img->be_scale_x = 1.0 / (img->width / (double) width); - img->be_scale_y = 1.0 / (img->height / (double) height); - img->width = width; - img->height = height; -#endif /* not HAVE_HAIKU */ +#endif } #endif /* HAVE_IMAGEMAGICK || HAVE_NATIVE_TRANSFORMS */ |