correct version of: port cairo ARGB/BGRA -> pixbuf RGBA patch from recent 2.X commit (restores text on canvas), in which i move some functions around, rename stuff and add comments

git-svn-id: svn://localhost/ardour2/branches/3.0@7846 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2010-09-26 13:33:39 +00:00
parent 0d2ddbe52a
commit aad157337c
8 changed files with 161 additions and 140 deletions

View file

@ -17,11 +17,14 @@
*/
#define __STDC_LIMIT_MACROS 1
#include <stdint.h>
#include "pbd/memento_command.h"
#include "pbd/basename.h"
#include "pbd/stateful_diff_command.h"
#include "gtkmm2ext/utils.h"
#include "ardour/session.h"
#include "ardour/dB.h"
#include "ardour/region_factory.h"
@ -48,6 +51,7 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
using namespace Gtk;
using namespace Gtkmm2ext;
using namespace Editing;
using namespace ArdourCanvas;

View file

@ -39,6 +39,7 @@
using namespace std;
using namespace ARDOUR;
using namespace Gtkmm2ext;
PBD::Signal1<void,Marker*> Marker::CatchDeletion;

View file

@ -21,6 +21,7 @@
#include <gtkmm.h>
#include <gtkmm2ext/gtk_ui.h>
#include <gtkmm2ext/utils.h>
#include "ardour/playlist.h"
#include "ardour/region.h"
@ -67,7 +68,7 @@ StreamView::StreamView (RouteTimeAxisView& tv, ArdourCanvas::Group* background_g
canvas_rect = new ArdourCanvas::SimpleRect (*_background_group);
canvas_rect->property_x1() = 0.0;
canvas_rect->property_y1() = 0.0;
canvas_rect->property_x2() = physical_screen_width (_trackview.editor().get_window());
canvas_rect->property_x2() = Gtkmm2ext::physical_screen_width (_trackview.editor().get_window());
canvas_rect->property_y2() = (double) tv.current_height();
canvas_rect->raise(1); // raise above tempo lines

View file

@ -47,6 +47,7 @@ using namespace Editing;
using namespace Glib;
using namespace PBD;
using namespace ARDOUR;
using namespace Gtkmm2ext;
Pango::FontDescription* TimeAxisViewItem::NAME_FONT = 0;
const double TimeAxisViewItem::NAME_X_OFFSET = 15.0;

View file

@ -916,61 +916,6 @@ reset_dpi ()
DPIReset();//Emit Signal
}
inline guint8
convert_color_channel (guint8 src,
guint8 alpha)
{
return alpha ? ((guint (src) << 8) - src) / alpha : 0;
}
void
convert_bgra_to_rgba (guint8 const* src,
guint8* dst,
int width,
int height)
{
guint8 const* src_pixel = src;
guint8* dst_pixel = dst;
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
{
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
/* [ B G R A ] is actually [ B G R A ] in memory SOURCE
0 1 2 3
[ R G B A ] is actually [ R G B A ] in memory DEST
*/
dst_pixel[0] = convert_color_channel (src_pixel[2],
src_pixel[3]); // R [0] <= [ 2 ]
dst_pixel[1] = convert_color_channel (src_pixel[1],
src_pixel[3]); // G [1] <= [ 1 ]
dst_pixel[2] = convert_color_channel (src_pixel[0],
src_pixel[3]); // B [2] <= [ 0 ]
dst_pixel[3] = src_pixel[3]; // alpha
#elif G_BYTE_ORDER == G_BIG_ENDIAN
/* [ B G R A ] is actually [ A R G B ] in memory SOURCE
0 1 2 3
[ R G B A ] is actually [ A B G R ] in memory DEST
*/
dst_pixel[3] = convert_color_channel (src_pixel[1],
src_pixel[0]); // R [3] <= [ 1 ]
dst_pixel[2] = convert_color_channel (src_pixel[2],
src_pixel[0]); // G [2] <= [ 2 ]
dst_pixel[1] = convert_color_channel (src_pixel[3],
src_pixel[0]); // B [1] <= [ 3 ]
dst_pixel[0] = src_pixel[0]; // alpha
#else
#error ardour does not currently support PDP-endianess
#endif
dst_pixel += 4;
src_pixel += 4;
}
}
void
resize_window_to_proportion_of_monitor (Gtk::Window* window, int max_width, int max_height)
{
@ -984,41 +929,6 @@ resize_window_to_proportion_of_monitor (Gtk::Window* window, int max_width, int
window->resize (w, h);
}
Glib::RefPtr<Gdk::Pixbuf>
pixbuf_from_string(const string& name, Pango::FontDescription* font, int clip_width, int clip_height, Gdk::Color fg)
{
static Glib::RefPtr<Gdk::Pixbuf>* empty_pixbuf = 0;
if (name.empty()) {
if (empty_pixbuf == 0) {
empty_pixbuf = new Glib::RefPtr<Gdk::Pixbuf>;
*empty_pixbuf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, clip_width, clip_height);
}
return *empty_pixbuf;
}
Glib::RefPtr<Gdk::Pixbuf> buf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, clip_width, clip_height);
cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, clip_width, clip_height);
cairo_t* cr = cairo_create (surface);
cairo_text_extents_t te;
cairo_set_source_rgba (cr, fg.get_red_p(), fg.get_green_p(), fg.get_blue_p(), 1.0);
cairo_select_font_face (cr, font->get_family().c_str(),
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size (cr, font->get_size() / Pango::SCALE);
cairo_text_extents (cr, name.c_str(), &te);
cairo_move_to (cr, 0.5, 0.5 - te.height / 2 - te.y_bearing + clip_height / 2);
cairo_show_text (cr, name.c_str());
convert_bgra_to_rgba(cairo_image_surface_get_data (surface), buf->get_pixels(), clip_width, clip_height);
cairo_destroy(cr);
cairo_surface_destroy(surface);
return buf;
}
/** Replace _ with __ in a string; for use with menu item text to make underscores displayed correctly */
string
@ -1075,32 +985,3 @@ control_link (ScopedConnectionList& scl, boost::shared_ptr<Controllable> c, Gtk:
gui_context());
}
int
physical_screen_height (Glib::RefPtr<Gdk::Window> win)
{
GdkScreen* scr = gdk_screen_get_default();
if (win) {
GdkRectangle r;
gint monitor = gdk_screen_get_monitor_at_window (scr, win->gobj());
gdk_screen_get_monitor_geometry (scr, monitor, &r);
return r.height;
} else {
return gdk_screen_get_height (scr);
}
}
int
physical_screen_width (Glib::RefPtr<Gdk::Window> win)
{
GdkScreen* scr = gdk_screen_get_default();
if (win) {
GdkRectangle r;
gint monitor = gdk_screen_get_monitor_at_window (scr, win->gobj());
gdk_screen_get_monitor_geometry (scr, monitor, &r);
return r.width;
} else {
return gdk_screen_get_width (scr);
}
}

View file

@ -85,25 +85,10 @@ bool key_is_legal_for_numeric_entry (guint keyval);
void reset_dpi ();
void set_pango_fontsize ();
inline guint8 convert_color_channel (guint8 src, guint8 alpha);
void convert_bgra_to_rgba (guint8 const* src,
guint8* dst,
int width,
int height);
Glib::RefPtr<Gdk::Pixbuf> pixbuf_from_string (const std::string& name,
Pango::FontDescription* font,
int clip_width,
int clip_height,
Gdk::Color);
void resize_window_to_proportion_of_monitor (Gtk::Window*, int, int);
std::string escape_underscores (std::string const &);
void control_link (PBD::ScopedConnectionList& scl, boost::shared_ptr<PBD::Controllable> c, Gtk::Adjustment& a);
int physical_screen_height (Glib::RefPtr<Gdk::Window>);
int physical_screen_width (Glib::RefPtr<Gdk::Window>);
#endif /* __ardour_gtk_utils_h__ */

View file

@ -26,6 +26,8 @@
#include <gtkmm/treeview.h>
#include <gdkmm/window.h> /* for WMDecoration */
#include <gdkmm/pixbuf.h>
#include <pangomm/fontdescription.h>
namespace Gtk {
class ComboBoxText;
@ -51,6 +53,12 @@ namespace Gtkmm2ext {
gint hpadding,
gint vpadding);
Glib::RefPtr<Gdk::Pixbuf> pixbuf_from_string (const std::string& name,
Pango::FontDescription* font,
int clip_width,
int clip_height,
Gdk::Color fg);
void set_popdown_strings (Gtk::ComboBoxText&,
const std::vector<std::string>&,
bool set_size = false,
@ -75,6 +83,9 @@ namespace Gtkmm2ext {
bool possibly_translate_keyval_to_make_legal_accelerator (uint32_t& keyval);
uint32_t possibly_translate_legal_accelerator_to_real_key (uint32_t keyval);
int physical_screen_height (Glib::RefPtr<Gdk::Window>);
int physical_screen_width (Glib::RefPtr<Gdk::Window>);
};
#endif /* __gtkmm2ext_utils_h__ */

View file

@ -34,6 +34,13 @@
using namespace std;
void
Gtkmm2ext::init ()
{
// Necessary for gettext
(void) bindtextdomain(PACKAGE, LOCALEDIR);
}
void
Gtkmm2ext::get_ink_pixel_size (Glib::RefPtr<Pango::Layout> layout,
int& width,
@ -84,11 +91,112 @@ Gtkmm2ext::set_size_request_to_display_given_text (Gtk::Widget &w,
w.set_size_request(width_max + hpadding, height_max + vpadding);
}
void
Gtkmm2ext::init ()
static inline guint8
demultiply_alpha (guint8 src,
guint8 alpha)
{
// Necessary for gettext
(void) bindtextdomain(PACKAGE, LOCALEDIR);
/* cairo pixel buffer data contains RGB values with the alpha
values premultiplied.
GdkPixbuf pixel buffer data contains RGB values without the
alpha value applied.
this removes the alpha component from the cairo version and
returns the GdkPixbuf version.
*/
return alpha ? ((guint (src) << 8) - src) / alpha : 0;
}
static void
convert_bgra_to_rgba (guint8 const* src,
guint8* dst,
int width,
int height)
{
guint8 const* src_pixel = src;
guint8* dst_pixel = dst;
/* cairo pixel data is endian-dependent ARGB with A in the most significant 8 bits,
with premultipled alpha values (see preceding function)
GdkPixbuf pixel data is non-endian-dependent RGBA with R in the lowest addressable
8 bits, and non-premultiplied alpha values.
convert from the cairo values to the GdkPixbuf ones.
*/
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
/* Cairo [ B G R A ] is actually [ B G R A ] in memory SOURCE
0 1 2 3
Pixbuf [ R G B A ] is actually [ R G B A ] in memory DEST
*/
dst_pixel[0] = demultiply_alpha (src_pixel[2],
src_pixel[3]); // R [0] <= [ 2 ]
dst_pixel[1] = demultiply_alpha (src_pixel[1],
src_pixel[3]); // G [1] <= [ 1 ]
dst_pixel[2] = demultiply_alpha (src_pixel[0],
src_pixel[3]); // B [2] <= [ 0 ]
dst_pixel[3] = src_pixel[3]; // alpha
#elif G_BYTE_ORDER == G_BIG_ENDIAN
/* Cairo [ B G R A ] is actually [ A R G B ] in memory SOURCE
0 1 2 3
Pixbuf [ R G B A ] is actually [ R G B A ] in memory DEST
*/
dst_pixel[0] = demultiply_alpha (src_pixel[1],
src_pixel[0]); // R [0] <= [ 1 ]
dst_pixel[1] = demultiply_alpha (src_pixel[2],
src_pixel[0]); // G [1] <= [ 2 ]
dst_pixel[2] = demultiply_alpha (src_pixel[3],
src_pixel[0]); // B [2] <= [ 3 ]
dst_pixel[3] = src_pixel[0]; // alpha
#else
#error ardour does not currently support PDP-endianess
#endif
dst_pixel += 4;
src_pixel += 4;
}
}
}
Glib::RefPtr<Gdk::Pixbuf>
Gtkmm2ext::pixbuf_from_string(const string& name, Pango::FontDescription* font, int clip_width, int clip_height, Gdk::Color fg)
{
static Glib::RefPtr<Gdk::Pixbuf>* empty_pixbuf = 0;
if (name.empty()) {
if (empty_pixbuf == 0) {
empty_pixbuf = new Glib::RefPtr<Gdk::Pixbuf>;
*empty_pixbuf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, clip_width, clip_height);
}
return *empty_pixbuf;
}
Glib::RefPtr<Gdk::Pixbuf> buf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, clip_width, clip_height);
cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, clip_width, clip_height);
cairo_t* cr = cairo_create (surface);
cairo_text_extents_t te;
cairo_set_source_rgba (cr, fg.get_red_p(), fg.get_green_p(), fg.get_blue_p(), 1.0);
cairo_select_font_face (cr, font->get_family().c_str(),
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size (cr, font->get_size() / Pango::SCALE);
cairo_text_extents (cr, name.c_str(), &te);
cairo_move_to (cr, 0.5, 0.5 - te.height / 2 - te.y_bearing + clip_height / 2);
cairo_show_text (cr, name.c_str());
convert_bgra_to_rgba(cairo_image_surface_get_data (surface), buf->get_pixels(), clip_width, clip_height);
cairo_destroy(cr);
cairo_surface_destroy(surface);
return buf;
}
void
@ -239,3 +347,32 @@ Gtkmm2ext::possibly_translate_legal_accelerator_to_real_key (uint32_t keyval)
return keyval;
}
int
Gtkmm2ext::physical_screen_height (Glib::RefPtr<Gdk::Window> win)
{
GdkScreen* scr = gdk_screen_get_default();
if (win) {
GdkRectangle r;
gint monitor = gdk_screen_get_monitor_at_window (scr, win->gobj());
gdk_screen_get_monitor_geometry (scr, monitor, &r);
return r.height;
} else {
return gdk_screen_get_height (scr);
}
}
int
Gtkmm2ext::physical_screen_width (Glib::RefPtr<Gdk::Window> win)
{
GdkScreen* scr = gdk_screen_get_default();
if (win) {
GdkRectangle r;
gint monitor = gdk_screen_get_monitor_at_window (scr, win->gobj());
gdk_screen_get_monitor_geometry (scr, monitor, &r);
return r.width;
} else {
return gdk_screen_get_width (scr);
}
}