summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dispextern.h11
-rw-r--r--src/haiku_draw_support.cc132
-rw-r--r--src/haiku_support.h11
-rw-r--r--src/haikuterm.c74
-rw-r--r--src/image.c104
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 */