cairo_debug_reset_static_data() issue using pango library - cairo

I've a problem with cairo_debug_reset_static_data() function when I combine both pango lib and cairo as I am getting the following assertion when its get called.
draw: cairo-hash.c:217: _cairo_hash_table_destroy: Assertion `hash_table->live_entries == 0' failed.
Here's the code I took from the following post: where some one had similar problem but they have not shared any working solution there(I already tried solution from the post, but it did not work). If we remove the commented lines then there is assertion.
#include <cairo.h>
#include <pango/pangocairo.h>
int
main (int argc, char *argv[])
{
cairo_surface_t *surface;
cairo_t *context;
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 120, 120);
context = cairo_create(surface);
PangoRectangle extents;
PangoLayout *layout;
PangoFontDescription *desc;
layout = pango_cairo_create_layout (context);
desc = pango_font_description_from_string("Inconsolata 12");
pango_layout_set_font_description(layout, desc);
pango_font_description_free(desc);
pango_layout_set_markup(layout, "hello", -1);
//pango_layout_get_pixel_extents(layout, &extents, NULL);
//pango_cairo_show_layout(context, layout);
g_object_unref(layout);
cairo_destroy(context);
cairo_surface_destroy(surface);
cairo_debug_reset_static_data();
return(0);
}
I have tried to play around it to fix this problem, and also searched their documentation but could not find anything useful. Some one with expertise on pangocairo, please shed some light and point me to right direction.
Thanks

Here's the code I took from the following post: where some one had similar problem but they have not shared any working solution there.
Well, did you see the reply to that post? It contains everything you need to know to fix this assertion failure:
Add a call to pango_cairo_font_map_set_default(NULL); before calling
cairo_debug_reset_static_data();. That makes PangoCairo unreference the fonts
that it still has alive.

Related

Draw to GdkWindow root window with Gtk3 and Cairo

I want to be able to draw directly to the root window with Gtk3 using Cairo. I have and old Gtk2 code drawing on a fullscreened window like this:
GdkWindow* drawable;
GdkGC* gc;
drawable = gdk_screen_get_root_window (gdk_screen_get_default());
gc = gdk_gc_new (drawable);
gdk_gc_set_subwindow (gc, GDK_INCLUDE_INFERIORS);
...
do_draw(drawable, gc);
With Gtk3 I tried this,
GdkWindow* drawable;
drawable = gdk_screen_get_root_window (gdk_screen_get_default());
cairo_surface_t *source_surface = gdk_window_create_similar_surface (drawable, CAIRO_CONTENT_COLOR_ALPHA, gdk_window_get_width(drawable), gdk_window_get_height(drawable) );
cairo_t *cairo = cairo_create(source_surface);
cairo_set_source_surface(cairo, source_surface, 0, 0);
....
do_draw(cairo);
The code seems to runs fine, but nothing is ever drawn to the screen. Is there a way to do something similar with Gtk3 and Cairo?
gdk_window_create_similar_surface creates a new surface that is "similar" to an already given one. But it is still a new surface.
You are looking for gdk_cairo_create() instead, I think (which is deprecated).
Unrelated to your question, but what is the following code supposed to do? Why are you preparing to copy a surface to itself? I think that is not really an allowed operation in cairo.
cairo_t *cairo = cairo_create(source_surface);
cairo_set_source_surface(cairo, source_surface, 0, 0);

class "APlayerController" has no member "GetPlayerViewPoint" in UE4.21.2

I'm in UE4 4.21.2
I'm a total noob for UE4. I'm following along with a tutorial where I need to use the GetPlayerViewPoint method on the PlayerController class, however when I try and call that method, I get a compile time error that says: class "APlayerController" has no member "GetPlayerViewPoint"
Which is weird because I get autocomplete in Visual Studio for other methods on that class, but not that particular method, BUT I can see that method in the docs here:
http://api.unrealengine.com/INT/API/Runtime/Engine/GameFramework/APlayerController/index.html
Could it be that my compiler and autocomplete are using a different UE4 version than the docs and tutorial?
Anyways, here is my class.
// Copyright, 2018
#include "BryceEscapeRoomUe4.h"
#include "Grabber.h"
#include "Runtime/Engine/Classes/GameFramework/Actor.h"
#include "Engine/World.h";
#include "GameFramework/PlayerController.h"
#define OUT
// Sets default values for this component's properties
UGrabber::UGrabber()
{
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = true;
// ...
}
// Called when the game starts
void UGrabber::BeginPlay()
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("Grabber repoting for duty!"));
}
// Called every frame
void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
// get player view point this tick
FVector PlayerVeiwPointLocation;
FRotator PlayerVeiwPointRotaion;
GetWorld()->GetFirstPlayerController()->GetPlayerVeiwPoint(
OUT PlayerVeiwPointLocation,
OUT PlayerVeiwPointRotaion
);
//log out to test
//ray cast out to reach distance
// see what we hit
}
I think this may have been caused by the fact that you have spelled GetPlayerViewPoint as GetPlayerVeiwPoint, which isn't a method that exists in UE4. Hopefully that should fix the problem, although as this is a relatively old question I'm sure you figured that out a while ago!

GLib signal connect works with webkitgtk but not webkitgtk2

I am working on a web browser for fun and ran into this problem.
This works:
#include <webkit/webkit.h>
void init() {
GtkWidget *web_view = webkit_web_view_new();
g_signal_connect(
G_OBJECT(GTK_WIDGET(this->web_view)),
"notify::progress",
G_CALLBACK(LoadChangedProxy),
NULL);
webkit_web_view_load_uri(WEBKIT_WEB_VIEW(this->web_view), "http://google.com");
}
void LoadChangedProxy(GtkWidget *view, GParamSpec *pspec, gpointer p) {
puts("LOADING");
}
In this case the callback is never called:
#include <webkit2/webkit2.h>
void init() {
GtkWidget *web_view = webkit_web_view_new();
g_signal_connect(
G_OBJECT(GTK_WIDGET(this->web_view)),
"notify::estimated-load-progress",
G_CALLBACK(LoadChangedProxy),
NULL);
webkit_web_view_load_uri(WEBKIT_WEB_VIEW(this->web_view), "http://google.com");
}
void LoadChangedProxy(GtkWidget *view, GParamSpec *pspec, gpointer p) {
puts("LOADING");
}
I was attempting to use webkitgtk2 initially and was really hitting my head against the wall. I switched to the older webkitgtk1 header and api and it magically started working. I have not idea what would cause this, additionally no errors are printed to stderr or stdout (eg. attempting to connect to a signal that an object does not have).
Any suggestions out there? There is surprisingly little documentation on g_signal_connect, from glib. All I know has come from looking at some gnome app source code.
Edit:
I have found that using "notify::progress" signal identifier in the webkitgtk2 case, the callback works. However I then cannot use either webkit_web_view_get_progress() or webkit_web_view_get_estimated_load_progress() to read the progress value to display it.
The symptoms are strange enough that I can only think of one explanation: you are still linking with webkit-gtk. With trivial code like this you didn't happen to hit linking problems but of course the new signals wouldn't be there either.

Why is the signal callback data pointer pointing to a junk value when the callback is fired?

Ok, I'm writing a method that creates an entire panel and it's containing contents and adds it to the form. The panels are stored in an array.
Here's the basic idea.
void vscale1Event(GtkWidget *widget, int *vscale_id)
{
int value = gtk_range_get_value(GTK_RANGE(vscale_struct[*vscale_id]->vscale1));
do stuff with this value;
}
void add_vscale_panel(int vscale_id)
{
vscale_struct[vscale_id]->vscale1 = ..... ;
vscale_struct[vscale_id]->vscale2 = ..... ;
add buttons to form;
gtk_signal_connect(GTK_OBJECT(vscale_struct[button_id]), "value_changed", (GtkSignalFunc)vscale1Event, &vscale_id);
gtk_signal_connect(GTK_OBJECT(vscale_struct[button_id]), "value_changed", (GtkSignalFunc)vscale2Event, &vscale_id);
}
int main()
{
for (i = 0; i<n; i++)
{
add_vscale_panel(i);
}
}
The problem I'm having, is that &vscale_id that I'm passing in, later becomes junk (it's value is a junk number around 32000) when I move the scale.
But - the gtk_signal_connect is only being called that once.
Ok, I get that it's probably something to do with the call stack, that bit of memory no longer being reserved.
But I did this same thing earlier for another panel, and it's working fine.
what I've changed - is trying to make things a bit tidier.
The previous version I had all the panels and widgets each in seperate arrays.
eg
GtkWidget **outerPanel;
GtkWidget **innerPanel1;
GtkWidget **vscale1;
whereas this one I'm doing it:
typedef struct
{
GtkWidget **vscale1;
Gtkwidget **vscale2;
} V_Panel;
V_Panel **vscale_struct;
Not bothering putting the panels into arrays or structs - because I figure I don't need to access them later? ( I found that you can 'recycle' labels so I figure panels (h and vboxes), are the same.
Also - an interesting clue - when I run valgrind - it works fine. Some how valgrind changes the way the program uses it's memory.
Any help here?
If you can perhaps explain what's happening when you call gtk_signal_connect. -
Here's my actual code: http://pastebin.com/MGfUihjM
relevant lines are
45, 145, 274, 308, 391
The problem is that your taking the address of a variable on the stack - in this case the parameter to the function. That address in memory is definitely not guaranteed to continue to hold the value you expect it to since it is just part of the stack frame
The correct way to pack your integer value_id into the callback userdata pointer is to use GINT_TO_POINTER and to reverse it using GPOINTER_TO_INT.
So your signal connection would be:
gtk_signal_connect(GTK_OBJECT(vscale_struct[button_id]),
"value_changed",
(GtkSignalFunc)vscale1Event,
GINT_TO_POINTER(value_id));
And in your signal handler would look like:
void vscale1Event(GtkWidget *widget, gpointer userdata)
{
int vscale_id = GPOINTER_TO_INT (userdata);
int value = gtk_range_get_value(GTK_RANGE(vscale_struct[vscale_id]->vscale1));
do stuff with this value;
}

Draw background image in gtk - none of my attempts work

I've been trying to set a background image on a gtk widget without success, even after trying 4 different approaches.
The following program contains 3 approaches (the 4th approach involves no code). I compiled it using MinGW (g++ 4.5.0) and gtkmm 2.4. The APPROACH macro can be set to 1, 2 or 3 in order to choose which approach to compile. I've also added references in the comments, so you can find out where I got the ideas from.
#include <iostream>
#include <gtkmm/main.h>
#include <gtkmm/alignment.h>
#include <gtkmm/box.h>
#include <gtkmm/entry.h>
#include <gtkmm/eventbox.h>
#include <gtkmm/frame.h>
#include <gtkmm/image.h>
#include <gtkmm/label.h>
#include <gtkmm/table.h>
#include <gtkmm/window.h>
// Set this to 1, 2 or 3 to try different ways of drawing the background
// Set to 0 to load no background at all
#define APPROACH (0)
// Making this alignment global in order to modify it from drawBackground
Gtk::Alignment* alignment;
bool drawBackground(GdkEventExpose* event) {
std::cout << "Draw background" << std::endl;
// Load background image
Glib::RefPtr<Gdk::Pixbuf> pixbuf = Gdk::Pixbuf::create_from_file("background.jpg");
Glib::RefPtr<Gdk::Pixmap> pixmap;
Glib::RefPtr<Gdk::Bitmap> mask;
pixbuf->render_pixmap_and_mask(pixmap, mask,0);
{
// Test that pixbuf was created correctly
Glib::RefPtr<Gdk::Pixbuf> back_to_pixbuf = Gdk::Pixbuf::create((Glib::RefPtr<Gdk::Drawable>)pixmap, 0, 0, pixbuf->get_width(), pixbuf->get_height());
back_to_pixbuf->save("back_to_pixbuf.png", "png");
}
#if APPROACH == 1
// Approach 1: draw_pixbuf
// Ref: http://islascruz.org/html/index.php/blog/show/Image-as-background-in-a-Gtk-Application..html
Glib::RefPtr<Gtk::Style> style = alignment->get_style();
alignment->get_window()->draw_pixbuf(style->get_bg_gc(Gtk::STATE_NORMAL), pixbuf, 0, 0, 0, 200, pixbuf->get_width(), pixbuf->get_height(), Gdk::RGB_DITHER_NONE, 0, 0);
#endif
#if APPROACH == 2
// Approach 2: set_back_pixmap
// Ref: http://www.gtkforums.com/viewtopic.php?t=446
// http://stackoverflow.com/questions/3150706/gtk-drawing-set-background-image
alignment->get_window()->set_back_pixmap(pixmap);
#endif
}
int main (int argc, char *argv[])
{
Gtk::Main kit(argc, argv);
Gtk::Window w;
Gtk::VBox mainBox;
// Top image
Gtk::Image topImage("header.jpg");
mainBox.pack_start(topImage,false,false,0);
// Middle alignment
alignment = Gtk::manage(new Gtk::Alignment);
mainBox.pack_start(*alignment,true,true,0);
// Create widget
Gtk::Alignment mywidget(0.5, 0.5, 0.1, 0.9);
Gtk::Table table;
Gtk::Label label1("Username"); table.attach(label1,0,1,0,1);
Gtk::Label label2("Password"); table.attach(label2,0,1,1,2);
Gtk::Entry entry1; table.attach(entry1,1,2,0,1);
Gtk::Entry entry2; table.attach(entry2,1,2,1,2);
Gtk::Button button("Login"); table.attach(button,1,2,2,3);
mywidget.add(table);
// Put widget in middle alignment
alignment->add(mywidget);
// Try to change the background
#if APPROACH == 1 || APPROACH == 2
alignment->signal_expose_event().connect(sigc::ptr_fun(&drawBackground), true);
#endif
#if APPROACH == 3
// Approach 3: modify the style using code
// Ref: http://www.gtkforums.com/viewtopic.php?t=446
// Load background image
Glib::RefPtr<Gdk::Pixbuf> pixbuf = Gdk::Pixbuf::create_from_file("background.jpg");
Glib::RefPtr<Gdk::Pixmap> pixmap;
Glib::RefPtr<Gdk::Bitmap> mask;
pixbuf->render_pixmap_and_mask(pixmap, mask,0);
Glib::RefPtr<Gtk::Style> style = alignment->get_style()->copy();
style->set_bg_pixmap(Gtk::STATE_NORMAL,pixmap);
style->set_bg_pixmap(Gtk::STATE_ACTIVE,pixmap);
style->set_bg_pixmap(Gtk::STATE_PRELIGHT,pixmap);
style->set_bg_pixmap(Gtk::STATE_SELECTED,pixmap);
style->set_bg_pixmap(Gtk::STATE_INSENSITIVE,pixmap);
alignment->set_style(style);
#endif
// Approach 4: modify share\themes\MS-Windows\gtk-2.0
// adding the following line
// bg_pixmap[NORMAL] = "D:\\path\\to\\file\\background.jpg"
// in the style "msw-default" section
// Ref: http://lists.ximian.com/pipermail/gtk-sharp-list/2005-August/006324.html
// Show the window
w.add(mainBox);
w.show_all();
kit.run(w);
return 0;
}
Links to images I used: header.jpg background.jpg
The layout mimics that of my actual program. The main window contains a Gtk::VBox with a header image on top and an Gtk::Alignment at the bottom. The contents of this alignment will change over time but I want it to have a background image always visible.
When loading no background at all, the header image loads correctly and the window looks like this:
Approach 1 is the one that is closer to work, though it hides the labels and the buttons:
Approaches 2 and 3 look the same as loading no background. Besides, approach 2 gives me the following error message:
(test-img-fondo.exe:1752): Gdk-CRITICAL **: gdk_window_set_back_pixmap: assertion `pixmap == NULL || !parent_relative' failed
Finally, in approach 4, I attempt to modify share\themes\MS-Windows\gtk-2.0 by adding the following line
bg_pixmap[NORMAL] = "D:\\path\\to\\file\\background.jpg"
in the style "msw-default" section. It doesn't work either.
So, has anyone succesfully drawn a background image on a Gtk widget? Is this possible at all? Any changes in my code that would make this work? Any workarounds?
All help is greatly appreciated.
I think I've solved it myself. Use approach 1 but change this line
alignment->signal_expose_event().connect(sigc::ptr_fun(&drawBackground), true);
for this:
alignment->signal_expose_event().connect(sigc::ptr_fun(&drawBackground), false);
This way, the call to drawBackground occurs before gtk calls its own handlers.
I should also point out that, in a real program, the images should be loaded once outside of drawBackground.