From 79ddf2f2b854aac373123620b8c722f81f4fbdaa Mon Sep 17 00:00:00 2001 From: Albrecht Schlosser Date: Thu, 9 May 2024 19:46:07 +0200 Subject: [PATCH] Optimize "arrow" drawing and centering - center (sub)menu arrow as good as possible - adjust arrow sizes in Fl_Counter widget - refactor "oxy" arrow drawing and centering in widgets --- src/Fl_Counter.cxx | 2 +- src/Fl_Menu.cxx | 8 ++-- src/fl_oxy.cxx | 94 ++++++++++++++++++++++++---------------------- 3 files changed, 55 insertions(+), 49 deletions(-) diff --git a/src/Fl_Counter.cxx b/src/Fl_Counter.cxx index 852658a1d..17a1efa19 100644 --- a/src/Fl_Counter.cxx +++ b/src/Fl_Counter.cxx @@ -62,7 +62,7 @@ void Fl_Counter::arrow_widths(int &w1, int &w2) { w2 = w() * 17/100; } // limit arrow box sizes to reserve more space for the text box - if (w1 > 18) w1 = 18; + if (w1 > 13) w1 = 13; if (w2 > 24) w2 = 24; } diff --git a/src/Fl_Menu.cxx b/src/Fl_Menu.cxx index f7a763327..b2f6abb50 100644 --- a/src/Fl_Menu.cxx +++ b/src/Fl_Menu.cxx @@ -526,10 +526,10 @@ void menuwindow::drawentry(const Fl_Menu_Item* m, int n, int eraseit) { if (m->submenu()) { // calculate the bounding box of the submenu pointer (arrow) - int sz = (hh-2) & -2; - if (sz > 12) sz = 12; // limit arrow size => max(d) = (sz-2)/2 = 5 - int x1 = xx + ww - sz - 2; - int y1 = yy + (hh-sz)/2 + 1; + int sz = ((hh-2) & (-2)) + 1 ; // must be odd for better centering + if (sz > 13) sz = 13; // limit arrow size + int x1 = xx + ww - sz - 2; // left border + int y1 = yy + (hh-sz)/2 + 1; // top border // draw an arrow whose style depends on the active scheme fl_draw_arrow(Fl_Rect(x1, y1, sz, sz), FL_ARROW_SINGLE, FL_ORIENT_RIGHT, fl_color()); diff --git a/src/fl_oxy.cxx b/src/fl_oxy.cxx index 5c3870d2b..0c6ae69e3 100644 --- a/src/fl_oxy.cxx +++ b/src/fl_oxy.cxx @@ -2,7 +2,7 @@ // "Oxy" Scheme drawing routines for the Fast Light Tool Kit (FLTK). // // Copyright 2011 by Dmitrij K. aka "kdiman" -// Copyright 2012-2022 by Bill Spitzak and others. +// Copyright 2012-2024 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -20,66 +20,74 @@ #include #include "fl_oxy.h" -// Status of this scheme (to-do list): +// Note: // -// This scheme works but is not yet perfect: -// -// (1) Drawing on the X11 platform (w/o Cairo) can be asymmetric for some "arrows" -// (2) Arrows are not always centered perfectly +// Drawing on the X11 platform w/o Cairo can be asymmetric for some "arrows" #define GROFF 0.45f // gradients offset -// Draw a single arrow -static void single_arrow(Fl_Rect bb, Fl_Orientation o, Fl_Color col) { +#ifndef DEBUG_OXY_ARROW +#define DEBUG_OXY_ARROW 0 // 0 = off, 1 = cross at center position of arrows +#endif - fl_color(col); - fl_line_style(FL_SOLID, 1); - fl_push_matrix(); +// Draw a single arrow + +static void single_arrow(Fl_Rect bb, Fl_Orientation o, Fl_Color col) { int x1 = bb.x(); int y1 = bb.y(); int w1 = bb.w(); int h1 = bb.h(); - int dx = w1 / 3; - if (h1 < w1) dx = h1 / 3; - if (dx > 4) dx = 4; - else if (dx < 2) dx = 2; - float angle = int(o) * 45.0f; - int tx = x1 + (w1 + 1)/2; - int ty = y1 + (h1 + 1)/2; + // calculate arrow size + int dx = (w1 - 3) / 2; + if (h1 < w1) dx = (h1 - 3) / 2; + if (dx > 4) dx = 4; + else if (dx < 2) dx = 2; + // dx = (dx + 1) & (-2); // should be even ? not required - const int lw = 2; // arrow line width: n means n+1 pixels + int tx = x1 + w1/2; + int ty = y1 + h1/2; - // define translation adjustments for easier maintenance + const int lw = 2; // arrow line width: n+1 pixels (must be even) + const int dw = 1; // half the line width - static int tr_x = 0; - static int tr_y = -1; + fl_color(col); + fl_line_style(FL_SOLID, 1); + fl_push_matrix(); - if (o == FL_ORIENT_LEFT) - tr_x = 2; + fl_translate(tx, ty); // move to center + fl_rotate(angle); // rotate by given angle - if (o & 2) // up or down arrow - fl_translate(tx, ty - (lw+1)/2 + tr_y); - else // left or right arrow - fl_translate(tx - lw/2 + tr_x, ty); + // DEBUG: Draw a two-colored cross at the center of the arrow box + // This can be used to debug or adjust array alignment (centering) - fl_rotate(angle); +#if (DEBUG_OXY_ARROW) // draw a cross at the center + int ll; // line length + fl_color(FL_BLUE); // "horizontal" line + ll = (o&2) ? h1/2 - 1 : w1/2 - 1; // line length + fl_begin_line(); + fl_vertex(-ll, 0); fl_vertex(ll, 0); + fl_end_line(); + fl_color(0x22882200); // "vertical" line + ll = (o&2) ? w1/2 - 1 : h1/2 - 1; // line length + fl_begin_line(); + fl_vertex(0, -ll); fl_vertex(0, ll); + fl_end_line(); + fl_color(col); // back to original color +#endif - int x0 = (-dx)/2; + // Draw the "arrow", similar to '>' at the center of the box fl_begin_complex_polygon(); - - fl_vertex(x0, -dx); - fl_vertex(x0 + dx, 0); - fl_vertex(x0, dx); - - fl_vertex(x0 + lw, dx); - fl_vertex(x0 + lw + dx, 0); - fl_vertex(x0 + lw, -dx); - + fl_vertex(-dx + dw, -dx); + fl_vertex( 0 + dw, 0); + fl_vertex(-dx + dw, dx); + fl_vertex(-dx + dw + lw, dx); + fl_vertex( 0 + dw + lw, 0); + fl_vertex(-dx + dw + lw, -dx); fl_end_complex_polygon(); fl_pop_matrix(); @@ -105,14 +113,12 @@ void oxy_arrow(Fl_Rect bb, Fl_Arrow_Type t, Fl_Orientation o, Fl_Color col) { switch (int(o)) { case FL_ORIENT_DOWN: case FL_ORIENT_UP: - bb.y(bb.y() - 2); // shift upwards bb.h(bb.h() - 4); // reduce size single_arrow(bb, o, col); bb.y(bb.y() + 4); // shift down single_arrow(bb, o, col); break; default: - bb.x(bb.x() - 1); // shift left bb.w(bb.w() - 4); // reduce size single_arrow(bb, o, col); bb.x(bb.x() + 4); // shift right @@ -123,10 +129,10 @@ void oxy_arrow(Fl_Rect bb, Fl_Arrow_Type t, Fl_Orientation o, Fl_Color col) { case FL_ARROW_CHOICE: - // bb.y(bb.y() - 0); // don't shift upwards (was: -2) - bb.h(bb.h() - 4); // reduce size + bb.y(bb.y() - 1); // shift upwards + bb.h(bb.h() - 4); // reduce height single_arrow(bb, FL_ORIENT_UP, col); - bb.y(bb.y() + 4); // shift down + bb.y(bb.y() + 6); // shift down single_arrow(bb, FL_ORIENT_DOWN, col); break;