]> git.eshelyaron.com Git - emacs.git/commitdiff
Rationalize Haiku rectangle handling
authorPo Lu <luangruo@yahoo.com>
Tue, 4 Jan 2022 08:07:53 +0000 (08:07 +0000)
committerPo Lu <luangruo@yahoo.com>
Tue, 4 Jan 2022 08:07:53 +0000 (08:07 +0000)
* src/haiku_draw_support.cc (BView_DrawBitmapWithEraseOp):
(BView_DrawMask):
(rotate_bitmap_270):
(rotate_bitmap_90):
(BBitmap_transform_bitmap):
* src/haiku_support.cc (UnZoom):
(GetParentWidthHeight):
(MakeFullscreen):
(AttachCairoSurface):
(AfterResize):
(DrawContent):
(BView_cr_dump_clipping): Use new rectangle handling macros.

* src/haiku_support.h (BE_RECT_WIDTH, BE_RECT_HEIGHT): New
macros.

src/haiku_draw_support.cc
src/haiku_support.cc
src/haiku_support.h

index 76a5d2e59c7bde8c09f8c4cc2f01ffc9f494c7aa..3e17a08811c1195a5a1ea80188ea2fbca3bfd1eb 100644 (file)
@@ -310,9 +310,10 @@ BView_DrawBitmapWithEraseOp (void *view, void *bitmap, int x,
   if (bm->ColorSpace () == B_GRAY1)
     {
       rgb_color low_color = vw->LowColor ();
-      for (int y = 0; y <= bc.Bounds ().Height (); ++y)
+      BRect bounds = bc.Bounds ();
+      for (int y = 0; y < BE_RECT_HEIGHT (bounds); ++y)
        {
-         for (int x = 0; x <= bc.Bounds ().Width (); ++x)
+         for (int x = 0; x <= BE_RECT_WIDTH (bounds); ++x)
            {
              if (bits[y * (stride / 4) + x] == 0xFF000000)
                bits[y * (stride / 4) + x] = RGB_COLOR_UINT32 (low_color);
@@ -336,11 +337,13 @@ BView_DrawMask (void *src, void *view,
 {
   BBitmap *source = (BBitmap *) src;
   BBitmap bm (source->Bounds (), B_RGBA32);
+  BRect bounds = bm.Bounds ();
+
   if (bm.InitCheck () != B_OK)
     return;
-  for (int y = 0; y <= bm.Bounds ().IntegerHeight (); ++y)
+  for (int y = 0; y < BE_RECT_HEIGHT (bounds); ++y)
     {
-      for (int x = 0; x <= bm.Bounds ().IntegerWidth (); ++x)
+      for (int x = 0; x < BE_RECT_WIDTH (bounds); ++x)
        {
          int bit = haiku_get_pixel ((void *) source, x, y);
 
@@ -364,8 +367,8 @@ rotate_bitmap_270 (BBitmap *bmp)
                             bmp->ColorSpace (), true);
   if (bm->InitCheck () != B_OK)
     gui_abort ("Failed to init bitmap for rotate");
-  int w = bmp->Bounds ().Width () + 1;
-  int h = bmp->Bounds ().Height () + 1;
+  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)
@@ -383,8 +386,8 @@ rotate_bitmap_90 (BBitmap *bmp)
                             bmp->ColorSpace (), true);
   if (bm->InitCheck () != B_OK)
     gui_abort ("Failed to init bitmap for rotate");
-  int w = bmp->Bounds ().Width () + 1;
-  int h = bmp->Bounds ().Height () + 1;
+  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)
@@ -419,44 +422,42 @@ BBitmap_transform_bitmap (void *bitmap, void *mask, uint32_t m_color,
     }
 
   BRect r = bm->Bounds ();
-  if (r.Width () != desw || r.Height () != desh)
+  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);
+
+  if (!vw.LockLooper ())
+    gui_abort ("Failed to lock offscreen view for scale");
+
+  if (rot != 90 && rot != 270)
     {
-      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);
-
-      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)
-       BView_DrawMask ((void *) mk, (void *) &vw,
-                       0, 0, mk->Bounds ().Width () + 1,
-                       mk->Bounds ().Height () + 1,
-                       0, 0, desw, desh, m_color);
-      vw.Sync ();
-      vw.RemoveSelf ();
-
-      if (copied_p)
-       delete bm;
-      if (copied_p && mk)
-       delete mk;
-      return dst;
+      BAffineTransform tr;
+      tr.RotateBy (BPoint (desw / 2, desh / 2), rot * M_PI / 180.0);
+      vw.SetTransform (tr);
     }
 
-  return bm;
+  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;
 }
 
 void
index 84f5756f8ca2ec2c98a6082818bbd61caeb20a49..40f37d577e1d61408c27a4cd58acbeda800134a9 100644 (file)
@@ -821,8 +821,8 @@ public:
     zoomed_p = 0;
 
     EmacsMoveTo (pre_zoom_rect.left, pre_zoom_rect.top);
-    ResizeTo (pre_zoom_rect.Width (),
-             pre_zoom_rect.Height ());
+    ResizeTo (BE_RECT_WIDTH (pre_zoom_rect),
+             BE_RECT_HEIGHT (pre_zoom_rect));
   }
 
   void
@@ -833,14 +833,17 @@ public:
 
     if (parent)
       {
-       *width = parent->Frame ().Width ();
-       *height = parent->Frame ().Height ();
+       BRect frame = parent->Frame ();
+       *width = BE_RECT_WIDTH (frame);
+       *height = BE_RECT_HEIGHT (frame);
       }
     else
       {
        BScreen s (this);
-       *width = s.Frame ().Width ();
-       *height = s.Frame ().Height ();
+       BRect frame = s.Frame ();
+
+       *width = BE_RECT_WIDTH (frame);
+       *height = BE_RECT_HEIGHT (frame);
       }
 
     child_frame_lock.Unlock ();
@@ -906,8 +909,8 @@ public:
        flags &= ~(B_NOT_MOVABLE | B_NOT_ZOOMABLE);
        EmacsMoveTo (pre_fullscreen_rect.left,
                     pre_fullscreen_rect.top);
-       ResizeTo (pre_fullscreen_rect.Width (),
-                 pre_fullscreen_rect.Height ());
+       ResizeTo (BE_RECT_WIDTH (pre_fullscreen_rect),
+                 BE_RECT_HEIGHT (pre_fullscreen_rect));
       }
     SetFlags (flags);
   }
@@ -998,11 +1001,12 @@ public:
       gui_abort ("Could not lock cr surface during attachment");
     if (cr_surface)
       gui_abort ("Trying to attach cr surface when one already exists");
+    BRect bounds = offscreen_draw_bitmap_1->Bounds ();
+
     cr_surface = cairo_image_surface_create_for_data
       ((unsigned char *) offscreen_draw_bitmap_1->Bits (),
-       CAIRO_FORMAT_ARGB32,
-       offscreen_draw_bitmap_1->Bounds ().IntegerWidth () + 1,
-       offscreen_draw_bitmap_1->Bounds ().IntegerHeight () + 1,
+       CAIRO_FORMAT_ARGB32, BE_RECT_WIDTH (bounds),
+       BE_RECT_HEIGHT (bounds),
        offscreen_draw_bitmap_1->BytesPerRow ());
     if (!cr_surface)
       gui_abort ("Cr surface allocation failed for double-buffered view");
@@ -1056,8 +1060,11 @@ public:
        if (offscreen_draw_bitmap_1->InitCheck () != B_OK)
          gui_abort ("Offscreen draw bitmap initialization failed");
 
-       offscreen_draw_view->MoveTo (Frame ().left, Frame ().top);
-       offscreen_draw_view->ResizeTo (Frame ().Width (), Frame ().Height ());
+       BRect frame = Frame ();
+
+       offscreen_draw_view->MoveTo (frame.left, frame.top);
+       offscreen_draw_view->ResizeTo (BE_RECT_WIDTH (frame),
+                                      BE_RECT_HEIGHT (frame));
        offscreen_draw_bitmap_1->AddChild (offscreen_draw_view);
 #ifdef USE_BE_CAIRO
        AttachCairoSurface ();
@@ -1446,7 +1453,7 @@ public:
       {
        BRect r = menu->Frame ();
        int w = menu->StringWidth (key);
-       menu->MovePenTo (BPoint (r.Width () - w - 4,
+       menu->MovePenTo (BPoint (BE_RECT_WIDTH (r) - w - 4,
                                 menu->PenLocation ().y));
        menu->DrawString (key);
       }
@@ -2914,8 +2921,9 @@ BView_cr_dump_clipping (void *view, cairo_t *ctx)
   for (int i = 0; i < cr.CountRects (); ++i)
     {
       BRect r = cr.RectAt (i);
-      cairo_rectangle (ctx, r.left, r.top, r.Width () + 1,
-                      r.Height () + 1);
+      cairo_rectangle (ctx, r.left, r.top,
+                      BE_RECT_WIDTH (r),
+                      BE_RECT_HEIGHT (r));
     }
 
   cairo_clip (ctx);
index ef90374f69db5cb84e9904c88dec90e8968e7eb8..550ebd0050585bad0f1435f52d4541486acfc10c 100644 (file)
@@ -32,6 +32,8 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include <cairo.h>
 #endif
 
+#include <math.h>
+
 enum haiku_cursor
   {
     CURSOR_ID_NO_CURSOR = 12,
@@ -310,6 +312,28 @@ struct haiku_menu_bar_state_event
 #define HAIKU_BLACK 1000
 #define HAIKU_MEDIUM 2000
 
+#ifdef __cplusplus
+/* Haiku's built in Height and Width functions for calculating
+   rectangle sizes are broken, probably for compatibility with BeOS:
+   they do not round up in a reasonable fashion, and they return the
+   numerical difference between the end and start sides in both
+   directions, instead of the actual size.
+
+   For example:
+
+     BRect (1, 1, 5, 5).IntegerWidth ()
+
+   Will return 4, when in reality the rectangle is 5 pixels wide,
+   since the left corner is also a pixel!
+
+   All code in Emacs should use the macros below to calculate the
+   dimensions of a BRect, instead of relying on the broken Width and
+   Height functions.  */
+
+#define BE_RECT_HEIGHT(rect) (ceil (((rect).bottom - (rect).top) + 1))
+#define BE_RECT_WIDTH(rect) (ceil (((rect).right - (rect).left) + 1))
+#endif /* __cplusplus */
+
 #ifdef __cplusplus
 extern "C"
 {