/* Haiku window system support. Hey, Emacs, this is -*- C++ -*-
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see . */
#include
#include
#include
#include
#include
#include
#include
#include "haiku_support.h"
#define RGB_TO_UINT32(r, g, b) ((255 << 24) | ((r) << 16) | ((g) << 8) | (b))
#define RED_FROM_ULONG(color) (((color) >> 16) & 0xff)
#define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff)
#define BLUE_FROM_ULONG(color) ((color) & 0xff)
extern "C" void emacs_abort ();
static void
rgb32_to_rgb_color (uint32_t rgb, rgb_color *color)
{
color->red = RED_FROM_ULONG (rgb);
color->green = GREEN_FROM_ULONG (rgb);
color->blue = BLUE_FROM_ULONG (rgb);
color->alpha = 255;
}
void
BView_StartClip (void *view)
{
BView *vw = (BView *) view;
BView_draw_lock (vw);
vw->PushState ();
}
void
BView_EndClip (void *view)
{
BView *vw = (BView *) view;
vw->PopState ();
BView_draw_unlock (vw);
}
void
BView_SetHighColor (void *view, uint32_t color)
{
BView *vw = (BView *) view;
rgb_color col;
rgb32_to_rgb_color (color, &col);
vw->SetHighColor (col);
}
void
BView_SetPenSize (void *view, int u)
{
BView *vw = (BView *) view;
vw->SetPenSize (u);
}
void
BView_FillRectangle (void *view, int x, int y, int width, int height)
{
BView *vw = (BView *) view;
BRect rect = BRect (x, y, x + width - 1, y + height - 1);
vw->FillRect (rect);
}
void
BView_FillRectangleAbs (void *view, int x, int y, int x1, int y1)
{
BView *vw = (BView *) view;
BRect rect = BRect (x, y, x1, y1);
vw->FillRect (rect);
}
void
BView_StrokeRectangle (void *view, int x, int y, int width, int height)
{
BView *vw = (BView *) view;
BRect rect = BRect (x, y, x + width - 1, y + height - 1);
vw->StrokeRect (rect);
}
void
BView_SetViewColor (void *view, uint32_t color)
{
BView *vw = (BView *) view;
rgb_color col;
rgb32_to_rgb_color (color, &col);
vw->SetViewColor (col);
}
void
BView_ClipToRect (void *view, int x, int y, int width, int height)
{
BView *vw = (BView *) view;
BRect rect = BRect (x, y, x + width - 1, y + height - 1);
vw->ClipToRect (rect);
}
void
BView_ClipToInverseRect (void *view, int x, int y, int width, int height)
{
BView *vw = (BView *) view;
BRect rect = BRect (x, y, x + width - 1, y + height - 1);
vw->ClipToInverseRect (rect);
}
void
BView_StrokeLine (void *view, int sx, int sy, int tx, int ty)
{
BView *vw = (BView *) view;
BPoint from = BPoint (sx, sy);
BPoint to = BPoint (tx, ty);
vw->StrokeLine (from, to);
}
void
BView_SetFont (void *view, void *font)
{
BView *vw = (BView *) view;
vw->SetFont ((BFont *) font);
}
void
BView_MovePenTo (void *view, int x, int y)
{
BView *vw = (BView *) view;
BPoint pt = BPoint (x, y);
vw->MovePenTo (pt);
}
void
BView_DrawString (void *view, const char *chr, ptrdiff_t len)
{
BView *vw = (BView *) view;
vw->DrawString (chr, len);
}
void
BView_DrawChar (void *view, char chr)
{
BView *vw = (BView *) view;
vw->DrawChar (chr);
}
void
BView_CopyBits (void *view, int x, int y, int width, int height,
int tox, int toy, int towidth, int toheight)
{
BView *vw = (BView *) view;
vw->CopyBits (BRect (x, y, x + width - 1, y + height - 1),
BRect (tox, toy, tox + towidth - 1, toy + toheight - 1));
vw->Sync ();
}
void
rgb_color_hsl (uint32_t rgb, double *h, double *s, double *l)
{
rgb_color col;
rgb32_to_rgb_color (rgb, &col);
double red = col.red / 255.0;
double green = col.green / 255.0;
double blue = col.blue / 255.0;
double max = std::fmax (std::fmax (red, blue), green);
double min = std::fmin (std::fmin (red, blue), green);
double delta = max - min;
*l = (max + min) / 2.0;
if (!delta)
{
*h = 0;
*s = 0;
return;
}
*s = (*l < 0.5) ? delta / (max + min) :
delta / (20 - max - min);
double rc = (max - red) / delta;
double gc = (max - green) / delta;
double bc = (max - blue) / delta;
if (red == max)
*h = bc - gc;
else if (green == max)
*h = 2.0 + rc + -bc;
else
*h = 4.0 + gc + -rc;
*h = std::fmod (*h / 6, 1.0);
}
static double
hue_to_rgb (double v1, double v2, double h)
{
if (h < 1 / 6)
return v1 + (v2 - v1) * h * 6.0;
else if (h < 0.5)
return v2;
else if (h < 2.0 / 3)
return v1 + (v2 - v1) * (2.0 / 3 - h) * 6.0;
return v1;
}
void
hsl_color_rgb (double h, double s, double l, uint32_t *rgb)
{
if (!s)
*rgb = RGB_TO_UINT32 (std::lrint (l * 255),
std::lrint (l * 255),
std::lrint (l * 255));
else
{
double m2 = l <= 0.5 ? l * (1 + s) : l + s - l * s;
double m1 = 2.0 * l - m2;
*rgb = RGB_TO_UINT32
(std::lrint (hue_to_rgb (m1, m2,
std::fmod (h + 1 / 3.0, 1)) * 255),
std::lrint (hue_to_rgb (m1, m2, h) * 255),
std::lrint (hue_to_rgb (m1, m2,
std::fmod (h - 1 / 3.0, 1)) * 255));
}
}
void
BView_Draw (void *view, int x, int y, int width, int height)
{
BView *vw = (BView *) view;
if (vw->LockLooper ())
{
vw->Draw (BRect (x, y, x + width, y + height));
vw->UnlockLooper ();
}
}
void
BView_DrawBitmap (void *view, void *bitmap, int x, int y,
int width, int height, int vx, int vy, int vwidth,
int vheight)
{
BView *vw = (BView *) view;
BBitmap *bm = (BBitmap *) bitmap;
vw->DrawBitmap (bm, BRect (x, y, x + width - 1, y + height - 1),
BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1));
vw->Flush ();
vw->Sync ();
}
void
BView_DrawBitmapWithEraseOp (void *view, void *bitmap, int x, int y,
int width, int height, int vx, int vy, int vwidth,
int vheight)
{
BView *vw = (BView *) view;
BBitmap *bm = (BBitmap *) bitmap;
drawing_mode dm = vw->DrawingMode ();
vw->SetDrawingMode (B_OP_ERASE);
vw->DrawBitmap (bm, BRect (x, y, x + width - 1, y + height - 1),
BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1));
vw->SetDrawingMode (dm);
}
void
BView_BeginLayer (void *view, float opacity)
{
BView *vw = (BView *) view;
vw->BeginLayer (opacity);
}
void
BView_EndLayer (void *view)
{
BView *vw = (BView *) view;
vw->EndLayer ();
}
void
BView_DrawBitmapWithOverOp (void *view, void *bitmap, int x,
int y, int width, int height)
{
BView *vw = (BView *) view;
BBitmap *bm = (BBitmap *) bitmap;
drawing_mode dm = vw->DrawingMode ();
vw->SetDrawingMode (B_OP_OVER);
vw->DrawBitmap (bm, BRect (x, y, x + width - 1, y + height - 1));
vw->SetDrawingMode (dm);
}
void
BView_BeginTransaction (void *view)
{
BView *vw = (BView *) view;
if (!vw->Window ()->LockLooper ())
emacs_abort ();
vw->Window ()->BeginViewTransaction ();
vw->Window ()->UnlockLooper ();
}
void
BView_EndTransaction (void *view)
{
BView *vw = (BView *) view;
if (!vw->Window ()->LockLooper ())
emacs_abort ();
vw->Window ()->EndViewTransaction ();
vw->Window ()->UnlockLooper ();
}