summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Wildemann <metalstrolch@metalstrolche.de>2015-11-21 17:21:04 +0100
committerStefan Wildemann <gta04@metalstrolche.de>2017-02-23 19:40:26 +0100
commit8efae9e743b97d520ffc80afdf20785ac07ea9b5 (patch)
treec8f0cb143c51e1932310f6092d015f851159e93e
parent0ba8f875914f91dae76d83feaa37afdaf72c49a7 (diff)
downloadnavit-8efae9e743b97d520ffc80afdf20785ac07ea9b5.tar.gz
Add QT5 graphics. Works on Sailfish OS.
-rwxr-xr-xCMakeLists.txt22
-rw-r--r--navit/graphics/qt5/CMakeLists.txt9
-rw-r--r--navit/graphics/qt5/Makefile.am9
-rw-r--r--navit/graphics/qt5/QNavitWidget.cpp148
-rw-r--r--navit/graphics/qt5/QNavitWidget.h32
-rw-r--r--navit/graphics/qt5/event_qt5.cpp185
-rw-r--r--navit/graphics/qt5/event_qt5.h18
-rw-r--r--navit/graphics/qt5/graphics_qt5.cpp659
-rw-r--r--navit/graphics/qt5/graphics_qt5.h50
9 files changed, 1127 insertions, 5 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 926fcb8b2..a240b6630 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -87,6 +87,7 @@ add_module(graphics/opengl "FreeType library not found" FALSE)
add_module(graphics/sdl "Required library not found" FALSE)
add_module(graphics/egl "Required library not found" FALSE)
add_module(graphics/qt_qpainter "Qt libraries not found" FALSE)
+add_module(graphics/qt5 "Qt5 libraries not found" FALSE)
add_module(gui/qml "Qt Declarative not found" FALSE)
add_module(gui/gtk "GTK libs not found" FALSE)
add_module(vehicle/gpsd "gpsd lib not found" FALSE)
@@ -155,11 +156,18 @@ find_package(Threads)
libfind_pkg_check_modules(FONTCONFIG fontconfig)
#Qt detection
if (NOT DISABLE_QT)
- # Unfortunately, CMake seems to ignore the "OPTIONAL_COMPONENTS" flag,
- # and actually requires all components to be installed. Maybe this can
- # be fixed later...
- find_package(Qt4 4.7 COMPONENTS QtCore OPTIONAL_COMPONENTS QtGui QtXml QtDeclarative QtSvg)
+ find_package(Qt5Widgets)
+ find_package(Qt5Svg)
+ #find_package(Qt5Declarative)
+ if (Qt5Widgets_FOUND)
+ else (Qt5Widgets_FOUND)
+ # Unfortunately, CMake seems to ignore the "OPTIONAL_COMPONENTS" flag,
+ # and actually requires all components to be installed. Maybe this can
+ # be fixed later...
+ find_package(Qt4 4.7 COMPONENTS QtCore OPTIONAL_COMPONENTS QtGui QtXml QtDeclarative QtSvg)
+ endif (Qt5Widgets_FOUND)
endif (NOT DISABLE_QT)
+
#pkg-config based detection
find_package(PkgConfig)
if(PKG_CONFIG_FOUND)
@@ -301,7 +309,11 @@ if (QT_FOUND)
endif()
endif()
endif(QT_FOUND)
-
+if (Qt5Widgets_FOUND)
+ set_with_reason(graphics/qt5 "Qt5 found" TRUE ${Qt5Widgets_LIBRARIES}
+ ${Qt5Declarative_LIBRARIES}
+ ${Qt5Svg_LIBRARIES})
+endif ()
if(GTK2_FOUND)
# Include gtk.h with "SYSTEM" to avoid GCC compiler warning for gtkitemfactory.h.
include_directories(SYSTEM ${GTK2_GTK_INCLUDE_DIR})
diff --git a/navit/graphics/qt5/CMakeLists.txt b/navit/graphics/qt5/CMakeLists.txt
new file mode 100644
index 000000000..9c2574e8b
--- /dev/null
+++ b/navit/graphics/qt5/CMakeLists.txt
@@ -0,0 +1,9 @@
+# Find includes in corresponding build directories
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+# Instruct CMake to run moc automatically when needed.
+set(CMAKE_AUTOMOC ON)
+
+# Find the QtWidgets library
+find_package(Qt5Widgets)
+
+module_add_library(graphics_qt5 graphics_qt5.cpp event_qt5.cpp QNavitWidget.cpp)
diff --git a/navit/graphics/qt5/Makefile.am b/navit/graphics/qt5/Makefile.am
new file mode 100644
index 000000000..a4631ff4a
--- /dev/null
+++ b/navit/graphics/qt5/Makefile.am
@@ -0,0 +1,9 @@
+include $(top_srcdir)/Makefile.inc
+AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(top_srcdir)/navit -DMODULE=graphics_null
+if PLUGINS
+modulegraphics_LTLIBRARIES = libgraphics_null.la
+else
+noinst_LTLIBRARIES = libgraphics_null.la
+endif
+libgraphics_null_la_SOURCES = graphics_null.c
+libgraphics_null_la_LDFLAGS = -module -avoid-version @NAVIT_MODULE_LDFLAGS@
diff --git a/navit/graphics/qt5/QNavitWidget.cpp b/navit/graphics/qt5/QNavitWidget.cpp
new file mode 100644
index 000000000..df9038055
--- /dev/null
+++ b/navit/graphics/qt5/QNavitWidget.cpp
@@ -0,0 +1,148 @@
+/**
+ * Navit, a modular navigation system.
+ * Copyright (C) 2005-2008 Navit Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program 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 this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <glib.h>
+#include "config.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "item.h"
+#include "point.h"
+#include "graphics.h"
+#include "color.h"
+#include "plugin.h"
+#include "event.h"
+#include "debug.h"
+#include "window.h"
+#include "callback.h"
+#if defined(WINDOWS) || defined(WIN32) || defined (HAVE_API_WIN32_CE)
+#include <windows.h>
+#endif
+#include "graphics_qt5.h"
+#include "QNavitWidget.h"
+#include "QNavitWidget.moc"
+
+QNavitWidget :: QNavitWidget(struct graphics_priv *my_graphics_priv,
+ QWidget * parent,
+ Qt::WindowFlags flags): QWidget(parent, flags)
+{
+ graphics_priv = my_graphics_priv;
+}
+
+bool QNavitWidget::event(QEvent *event)
+{
+ if (event->type() == QEvent::Gesture)
+ dbg(lvl_debug, "Gesture event caught");
+ //return gestureEvent(static_cast<QGestureEvent*>(event));
+ return QWidget::event(event);
+}
+
+void QNavitWidget :: paintEvent(QPaintEvent * event)
+{
+// dbg(lvl_debug,"enter\n");
+ QPainter painter(this);
+ /* color background if any */
+ if (graphics_priv->background_graphics_gc_priv != NULL)
+ {
+ painter.setPen(*graphics_priv->background_graphics_gc_priv->pen);
+ painter.fillRect(0, 0, graphics_priv->pixmap->width(),
+ graphics_priv->pixmap->height(),
+ *graphics_priv->background_graphics_gc_priv->brush);
+ }
+ painter.drawPixmap(0,0,*graphics_priv->pixmap);
+
+}
+
+void QNavitWidget :: do_resize(QSize size)
+{
+ delete graphics_priv->pixmap;
+ graphics_priv->pixmap=new QPixmap(size);
+ graphics_priv->pixmap->fill();
+ QPainter painter(graphics_priv->pixmap);
+ QBrush brush;
+ painter.fillRect(0, 0, size.width(), size.height(), brush);
+ dbg(lvl_debug,"size %dx%d\n", size.width(), size.height());
+ dbg(lvl_debug,"pixmap %p %dx%d\n", graphics_priv->pixmap, graphics_priv->pixmap->width(), graphics_priv->pixmap->height());
+ resize_callback(size.width(),size.height());
+}
+
+void QNavitWidget::mouseEvent(int pressed, QMouseEvent *event)
+{
+ struct point p;
+// dbg(lvl_debug,"enter\n");
+ p.x=event->x();
+ p.y=event->y();
+ switch (event->button()) {
+ case Qt::LeftButton:
+ callback_list_call_attr_3(callbacks, attr_button, GINT_TO_POINTER(pressed), GINT_TO_POINTER(1), GINT_TO_POINTER(&p));
+ break;
+ case Qt::MidButton:
+ callback_list_call_attr_3(callbacks, attr_button, GINT_TO_POINTER(pressed), GINT_TO_POINTER(2), GINT_TO_POINTER(&p));
+ break;
+ case Qt::RightButton:
+ callback_list_call_attr_3(callbacks, attr_button, GINT_TO_POINTER(pressed), GINT_TO_POINTER(3), GINT_TO_POINTER(&p));
+ break;
+ default:
+ break;
+ }
+}
+
+void QNavitWidget::mousePressEvent(QMouseEvent *event)
+{
+// dbg(lvl_debug,"enter\n");
+ mouseEvent(1, event);
+}
+
+void QNavitWidget::mouseReleaseEvent(QMouseEvent *event)
+{
+// dbg(lvl_debug,"enter\n");
+ mouseEvent(0, event);
+}
+
+void QNavitWidget::mouseMoveEvent(QMouseEvent *event)
+{
+ struct point p;
+// dbg(lvl_debug,"enter\n");
+ p.x=event->x();
+ p.y=event->y();
+ callback_list_call_attr_1(callbacks, attr_motion, (void *)&p);
+}
+
+void QNavitWidget::wheelEvent(QWheelEvent *event)
+{
+ struct point p;
+ int button;
+ dbg(lvl_debug,"enter");
+ p.x=event->x(); // xy-coordinates of the mouse pointer
+ p.y=event->y();
+
+ if (event->delta() > 0) // wheel movement away from the person
+ button=4;
+ else if (event->delta() < 0) // wheel movement towards the person
+ button=5;
+ else
+ button=-1;
+
+ if (button != -1) {
+ callback_list_call_attr_3(callbacks, attr_button, GINT_TO_POINTER(1), GINT_TO_POINTER(button), GINT_TO_POINTER(&p));
+ callback_list_call_attr_3(callbacks, attr_button, GINT_TO_POINTER(0), GINT_TO_POINTER(button), GINT_TO_POINTER(&p));
+ }
+
+ event->accept();
+}
diff --git a/navit/graphics/qt5/QNavitWidget.h b/navit/graphics/qt5/QNavitWidget.h
new file mode 100644
index 000000000..7fd3223cc
--- /dev/null
+++ b/navit/graphics/qt5/QNavitWidget.h
@@ -0,0 +1,32 @@
+#ifndef __QNavitWidget_h
+#define __QNavitWidget_h
+class QNavitWidget;
+#include "graphics_qt5.h"
+#include <QPixmap>
+#include <QWidget>
+#include <QMouseEvent>
+#include <QWheelEvent>
+#include <QEvent>
+
+class QNavitWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ QNavitWidget(struct graphics_priv *my_graphics_priv,
+ QWidget * parent,
+ Qt::WindowFlags flags);
+protected:
+ virtual bool event(QEvent *event);
+ virtual void paintEvent(QPaintEvent * event);
+ virtual void do_resize(QSize size);
+ virtual void mouseEvent(int pressed, QMouseEvent *event);
+ virtual void mousePressEvent(QMouseEvent *event);
+ virtual void mouseReleaseEvent(QMouseEvent *event);
+ virtual void mouseMoveEvent(QMouseEvent *event);
+ virtual void wheelEvent(QWheelEvent * event);
+
+
+private:
+ struct graphics_priv *graphics_priv;
+};
+#endif \ No newline at end of file
diff --git a/navit/graphics/qt5/event_qt5.cpp b/navit/graphics/qt5/event_qt5.cpp
new file mode 100644
index 000000000..12f23d954
--- /dev/null
+++ b/navit/graphics/qt5/event_qt5.cpp
@@ -0,0 +1,185 @@
+/**
+ * Navit, a modular navigation system.
+ * Copyright (C) 2005-2008 Navit Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program 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 this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "config.h"
+#include "navit/point.h"
+#include "navit/item.h"
+#include "navit/graphics.h"
+#include "navit/color.h"
+#include "navit/debug.h"
+#include "navit/plugin.h"
+#include "navit/callback.h"
+#include "navit/event.h"
+#include "navit/window.h"
+#include "navit/keys.h"
+#include "navit/navit.h"
+#if defined(WINDOWS) || defined(WIN32) || defined (HAVE_API_WIN32_CE)
+#include <windows.h>
+#endif
+#include <QSocketNotifier>
+#include "graphics_qt5.h"
+#include "event_qt5.h"
+#include "event_qt5.moc"
+
+struct event_watch {
+ QSocketNotifier *sn;
+ struct callback *cb;
+ int fd;
+};
+
+static void event_qt5_remove_timeout(struct event_timeout *to);
+
+qt5_navit_timer :: qt5_navit_timer (QObject * parent) : QObject(parent)
+{
+ timer_type=g_hash_table_new(NULL, NULL);
+ timer_callback=g_hash_table_new(NULL, NULL);
+ watches=g_hash_table_new(NULL,NULL);
+ dbg(lvl_debug, "qt5_navit_timer object created\n");
+}
+
+void qt5_navit_timer :: timerEvent (QTimerEvent * event)
+{
+ int id=event->timerId();
+ void* multi = NULL;
+// dbg(lvl_debug, "TimerEvent (%d)\n", id);
+ struct callback *cb=(struct callback *)g_hash_table_lookup(timer_callback, (void *)id);
+ if (cb)
+ callback_call_0(cb);
+ /* remove timer if it was oneshot timer */
+ if (g_hash_table_lookup_extended(timer_type, (void *)id, NULL, &multi))
+ {
+ /* it's still in the list */
+ if(((int)multi) == 0)
+ event_qt5_remove_timeout((struct event_timeout *)id);
+ }
+// dbg(lvl_debug, "TimerEvent (%d) leave\n", id);
+}
+
+qt5_navit_timer * qt5_timer = NULL;
+
+static void
+event_qt5_main_loop_run(void)
+{
+
+ dbg(lvl_debug,"enter\n");
+ if(navit_app != NULL)
+ navit_app->exec();
+
+}
+
+static void event_qt5_main_loop_quit(void)
+{
+ dbg(lvl_debug,"enter\n");
+ exit(0);
+}
+
+static struct event_watch *
+event_qt5_add_watch(int fd, enum event_watch_cond cond, struct callback *cb)
+{
+ dbg(lvl_debug,"enter fd=%d\n",(int)(long)fd);
+ struct event_watch *ret=g_new0(struct event_watch, 1);
+ ret->fd=fd;
+ ret->cb=cb;
+ g_hash_table_insert(qt5_timer->watches, GINT_TO_POINTER(fd), ret);
+ ret->sn=new QSocketNotifier(fd, QSocketNotifier::Read, qt5_timer);
+ QObject::connect(ret->sn, SIGNAL(activated(int)), qt5_timer, SLOT(watchEvent(int)));
+ return ret;
+}
+
+static void
+event_qt5_remove_watch(struct event_watch *ev)
+{
+ dbg(lvl_debug,"enter\n");
+ g_hash_table_remove(qt5_timer->watches, GINT_TO_POINTER(ev->fd));
+ delete(ev->sn);
+ g_free(ev);
+}
+
+
+static struct event_timeout *
+event_qt5_add_timeout(int timeout, int multi, struct callback *cb)
+{
+ int id;
+ dbg(lvl_debug,"add timeout %d, mul %d, %p ==",timeout, multi, cb);
+ id=qt5_timer->startTimer(timeout);
+ dbg(lvl_debug,"%d\n", id);
+ g_hash_table_insert(qt5_timer->timer_callback, (void *)id, cb);
+ g_hash_table_insert(qt5_timer->timer_type, (void *)id, (void *)!!multi);
+ return (struct event_timeout *)id;
+}
+
+static void
+event_qt5_remove_timeout(struct event_timeout *to)
+{
+ dbg(lvl_debug,"remove timeout (%d)\n",(int)(long)to);
+ qt5_timer->killTimer((int)(long)to);
+ g_hash_table_remove(qt5_timer->timer_callback, to);
+ g_hash_table_remove(qt5_timer->timer_type, to);
+}
+
+
+static struct event_idle *
+event_qt5_add_idle(int priority, struct callback *cb)
+{
+ dbg(lvl_debug,"add idle event\n");
+ return (struct event_idle *)event_qt5_add_timeout(0, 1, cb);
+}
+
+static void
+event_qt5_remove_idle(struct event_idle *ev)
+{
+ dbg(lvl_debug,"Remove idle timeout\n");
+ event_qt5_remove_timeout((struct event_timeout *) ev);
+}
+
+static void
+event_qt5_call_callback(struct callback_list *cb)
+{
+ dbg(lvl_debug,"enter\n");
+}
+
+static struct event_methods event_qt5_methods = {
+ event_qt5_main_loop_run,
+ event_qt5_main_loop_quit,
+ event_qt5_add_watch,
+ event_qt5_remove_watch,
+ event_qt5_add_timeout,
+ event_qt5_remove_timeout,
+ event_qt5_add_idle,
+ event_qt5_remove_idle,
+ event_qt5_call_callback,
+};
+
+static struct event_priv *
+event_qt5_new(struct event_methods *meth)
+{
+ *meth=event_qt5_methods;
+ qt5_timer = new qt5_navit_timer(NULL);
+ return NULL;
+}
+
+
+void
+qt5_event_init(void)
+{
+ plugin_register_event_type("qt5", event_qt5_new);
+}
diff --git a/navit/graphics/qt5/event_qt5.h b/navit/graphics/qt5/event_qt5.h
new file mode 100644
index 000000000..f999d3a46
--- /dev/null
+++ b/navit/graphics/qt5/event_qt5.h
@@ -0,0 +1,18 @@
+#include <glib.h>
+#include <QObject>
+
+class qt5_navit_timer : public QObject
+{
+ Q_OBJECT
+public:
+ qt5_navit_timer(QObject * parent = 0);
+ GHashTable *timer_type;
+ GHashTable *timer_callback;
+ GHashTable *watches;
+protected:
+ void timerEvent(QTimerEvent * event);
+};
+
+
+void
+qt5_event_init(void);
diff --git a/navit/graphics/qt5/graphics_qt5.cpp b/navit/graphics/qt5/graphics_qt5.cpp
new file mode 100644
index 000000000..1e7154869
--- /dev/null
+++ b/navit/graphics/qt5/graphics_qt5.cpp
@@ -0,0 +1,659 @@
+/**
+ * Navit, a modular navigation system.
+ * Copyright (C) 2005-2008 Navit Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program 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 this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <glib.h>
+#include "config.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "item.h"
+#include "point.h"
+#include "graphics.h"
+#include "color.h"
+#include "plugin.h"
+#include "event.h"
+#include "debug.h"
+#include "window.h"
+#include "callback.h"
+#if defined(WINDOWS) || defined(WIN32) || defined (HAVE_API_WIN32_CE)
+#include <windows.h>
+#endif
+#include "graphics_qt5.h"
+#include "event_qt5.h"
+#include "QNavitWidget.h"
+#include <QApplication>
+#include <QDesktopWidget>
+#include <QPixmap>
+#include <QPainter>
+#include <QFont>
+#include <QSvgRenderer>
+#include <QPixmapCache>
+
+
+
+struct callback_list* callbacks;
+QApplication * navit_app = NULL;
+
+struct graphics_font_priv {
+ QFont * font;
+};
+
+struct graphics_image_priv {
+ QPixmap * pixmap;
+};
+
+static void
+graphics_destroy(struct graphics_priv *gr)
+{
+// dbg(lvl_debug,"enter\n");
+#ifdef QT_QPAINTER_USE_FREETYPE
+ gr->freetype_methods.destroy();
+#endif
+ /* destroy painter */
+ if(gr->painter != NULL)
+ delete(gr->painter);
+ /* destroy pixmap */
+ if(gr->pixmap != NULL)
+ delete(gr->pixmap);
+ /* destroy widget */
+ delete(gr->widget);
+ /* unregister from parent, if any */
+ if(gr->parent != NULL)
+ {
+ g_hash_table_remove(gr->parent->overlays, gr);
+ }
+ /* destroy overlays hash */
+ g_hash_table_destroy(gr->overlays);
+ /* destroy self */
+ g_free(gr);
+}
+
+static void font_destroy(struct graphics_font_priv *font)
+{
+// dbg(lvl_debug,"enter\n");
+ if(font->font != NULL)
+ delete(font->font);
+ g_free(font);
+
+}
+
+static struct graphics_font_methods font_methods = {
+ font_destroy
+};
+
+static struct graphics_font_priv *font_new(struct graphics_priv *gr, struct graphics_font_methods *meth, char *font, int size, int flags)
+{
+ struct graphics_font_priv *font_priv;
+// dbg(lvl_debug,"enter (font %s, %d)\n", font, size);
+ font_priv = g_new0(struct graphics_font_priv, 1);
+ font_priv->font=new QFont(font,size/16);
+ font_priv->font->setStyleStrategy(QFont::NoAntialias);
+ *meth=font_methods;
+ return font_priv;
+}
+
+static void
+gc_destroy(struct graphics_gc_priv *gc)
+{
+// dbg(lvl_debug,"enter gc=%p\n", gc);
+ delete(gc->pen);
+ delete(gc->brush);
+ g_free(gc);
+}
+
+static void
+gc_set_linewidth(struct graphics_gc_priv *gc, int w)
+{
+ //dbg(lvl_debug,"enter gc=%p, %d\n", gc, w);
+ gc->pen->setWidth(w);
+}
+
+static void
+gc_set_dashes(struct graphics_gc_priv *gc, int w, int offset, unsigned char *dash_list, int n)
+{
+ /* use Qt dash feature */
+ QVector<qreal> dashes;
+ gc->pen->setWidth(w);
+ for(int a = 0; a < n; a ++)
+ dashes << dash_list[n];
+ gc->pen->setDashPattern(dashes);
+}
+
+static void
+gc_set_foreground(struct graphics_gc_priv *gc, struct color *c)
+{
+ QColor col(c->r >> 8, c->g >> 8, c->b >> 8, c->a >> 8 );
+ //dbg(lvl_debug,"context %p: color %02x%02x%02x\n",gc, c->r >> 8, c->g >> 8, c->b >> 8);
+ gc->pen->setColor(col);
+ gc->brush->setColor(col);
+ //gc->c=*c;
+}
+
+static void
+gc_set_background(struct graphics_gc_priv *gc, struct color *c)
+{
+ QColor col(c->r >> 8, c->g >> 8, c->b >> 8, c->a >> 8 );
+ //dbg(lvl_debug,"context %p: color %02x%02x%02x\n",gc, c->r >> 8, c->g >> 8, c->b >> 8);
+ //gc->pen->setColor(col);
+ //gc->brush->setColor(col);
+}
+
+static struct graphics_gc_methods gc_methods = {
+ gc_destroy,
+ gc_set_linewidth,
+ gc_set_dashes,
+ gc_set_foreground,
+ gc_set_background
+};
+
+static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth)
+{
+ struct graphics_gc_priv * graphics_gc_priv = NULL;
+// dbg(lvl_debug,"enter gr==%p\n", gr);
+ graphics_gc_priv = g_new0(struct graphics_gc_priv, 1);
+ graphics_gc_priv->graphics_priv = gr;
+ graphics_gc_priv->pen=new QPen();
+ graphics_gc_priv->brush=new QBrush(Qt::SolidPattern);
+
+ *meth=gc_methods;
+ return graphics_gc_priv;
+}
+
+static void image_destroy(struct graphics_image_priv *img)
+{
+// dbg(lvl_debug, "enter\n");
+ if(img->pixmap != NULL)
+ delete(img->pixmap);
+ g_free(img);
+}
+
+struct graphics_image_methods image_methods ={
+ image_destroy
+};
+
+
+static struct graphics_image_priv *
+image_new(struct graphics_priv *gr, struct graphics_image_methods *meth, char *path, int *w, int *h, struct point *hot, int rotation)
+{
+ struct graphics_image_priv * image_priv;
+ dbg(lvl_debug,"enter %s, %d %d\n", path, *w, *h);
+ if(*w == -1) *w = 16;
+ if(*h == -1) *h = 16;
+// QPixmap *cachedPixmap;
+ QString key(path);
+ image_priv = g_new0(struct graphics_image_priv, 1);
+ *meth = image_methods;
+// cachedPixmap=QPixmapCache::find(key);
+// if (!cachedPixmap) {
+ if(1/*key.endsWith(".svg", Qt::CaseInsensitive)*/) {
+ QSvgRenderer renderer(key);
+ if (!renderer.isValid()) {
+ g_free(image_priv);
+ return NULL;
+ }
+ image_priv->pixmap=new QPixmap(/*renderer.defaultSize()*/*w, *h);
+ image_priv->pixmap->fill(Qt::transparent);
+ QPainter painter(image_priv->pixmap);
+ renderer.render(&painter);
+
+ } else {
+ image_priv->pixmap=new QPixmap(path);
+ }
+ if (image_priv->pixmap->isNull()) {
+ g_free(image_priv);
+ return NULL;
+ }
+
+// QPixmapCache::insert(key,QPixmap(*image_priv->pixmap));
+// } else {
+// image_priv->pixmap=new QPixmap(*cachedPixmap);
+// }
+
+ *w=image_priv->pixmap->width();
+ *h=image_priv->pixmap->height();
+// dbg(lvl_debug, "Got (%d,%d)\n", *w,*h);
+ if (hot) {
+ hot->x=*w/2;
+ hot->y=*h/2;
+ }
+
+ return image_priv;
+}
+
+static void
+draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
+{
+ int i;
+ QPolygon polygon;
+// dbg(lvl_debug,"enter gr=%p, gc=%p, (%d, %d)\n", gr, gc, p->x, p->y);
+
+ for (i = 0 ; i < count ; i++)
+ polygon.putPoints(i, 1, p[i].x, p[i].y);
+ gr->painter->setPen(*gc->pen);
+ gr->painter->drawPolyline(polygon);
+
+}
+
+static void
+draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
+{
+ int i;
+ QPolygon polygon;
+// dbg(lvl_debug,"enter gr=%p, gc=%p, (%d, %d)\n", gr, gc, p->x, p->y);
+
+ for (i = 0 ; i < count ; i++)
+ polygon.putPoints(i, 1, p[i].x, p[i].y);
+ gr->painter->setPen(*gc->pen);
+ gr->painter->setBrush(*gc->brush);
+ gr->painter->drawPolygon(polygon);
+}
+
+static void
+draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h)
+{
+// dbg(lvl_debug,"gr=%p gc=%p %d,%d,%d,%d\n", gr, gc, p->x, p->y, w, h);
+ gr->painter->fillRect(p->x,p->y, w, h, *gc->brush);
+}
+
+static void
+draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r)
+{
+// dbg(lvl_debug,"enter gr=%p, gc=%p, (%d,%d) r=%d\n", gr, gc, p->x, p->y, r);
+ gr->painter->setPen(*gc->pen);
+ gr->painter->drawArc(p->x-r/2, p->y-r/2, r, r, 0, 360*16);
+}
+
+
+static void
+draw_text(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy)
+{
+// dbg(lvl_debug,"enter gc=%p, fg=%p, bg=%p pos(%d,%d) %s\n", gr, fg, bg, p->x, p->y, text);
+ QPainter *painter=gr->painter;
+#ifdef QT_QPAINTER_USE_FREETYPE
+ struct font_freetype_text *t;
+ struct font_freetype_glyph *g, **gp;
+ struct color transparent = {0x0000, 0x0000, 0x0000, 0x0000};
+ struct color fgc;
+ struct color bgc;
+ QColor temp;
+
+ int i,x,y;
+
+ if (! font)
+ return;
+ /* extract colors */
+ fgc.r = fg->pen->color().red() << 8;
+ fgc.g = fg->pen->color().green() << 8;
+ fgc.b = fg->pen->color().blue() << 8;
+ fgc.a = fg->pen->color().alpha() << 8;
+ if(bg != NULL)
+ {
+ bgc.r = bg->pen->color().red() << 8;
+ bgc.g = bg->pen->color().green() << 8;
+ bgc.b = bg->pen->color().blue() << 8;
+ bgc.a = bg->pen->color().alpha() << 8;
+ }
+ else
+ bgc = transparent;
+
+ t=gr->freetype_methods.text_new(text, (struct font_freetype_font *)font, dx, dy);
+ x=p->x << 6;
+ y=p->y << 6;
+ gp=t->glyph;
+ i=t->glyph_count;
+ if (bg) {
+ while (i-- > 0) {
+ g=*gp++;
+ if (g->w && g->h) {
+ unsigned char *data;
+ QImage img(g->w+2, g->h+2, QImage::Format_ARGB32_Premultiplied);
+ data=img.bits();
+ gr->freetype_methods.get_shadow(g,(unsigned char *)data,img.bytesPerLine(),&bgc,&transparent);
+
+ painter->drawImage(((x+g->x)>>6)-1, ((y+g->y)>>6)-1, img);
+ }
+ x+=g->dx;
+ y+=g->dy;
+ }
+ }
+ x=p->x << 6;
+ y=p->y << 6;
+ gp=t->glyph;
+ i=t->glyph_count;
+ while (i-- > 0) {
+ g=*gp++;
+ if (g->w && g->h) {
+ unsigned char *data;
+ QImage img(g->w, g->h, QImage::Format_ARGB32_Premultiplied);
+ data=img.bits();
+ gr->freetype_methods.get_glyph(g,(unsigned char *)data,img.bytesPerLine(),&fgc,&bgc,&transparent);
+ painter->drawImage((x+g->x)>>6, (y+g->y)>>6, img);
+ }
+ x+=g->dx;
+ y+=g->dy;
+ }
+ gr->freetype_methods.text_destroy(t);
+#else
+ QString tmp=QString::fromUtf8(text);
+ QMatrix sav=gr->painter->worldMatrix();
+ QMatrix m(dx/65535.0,dy/65535.0,-dy/65535.0,dx/65535.0,p->x,p->y);
+ painter->setWorldMatrix(m,TRUE);
+ painter->setPen(*fg->pen);
+ painter->setFont(*font->font);
+ painter->drawText(0, 0, tmp);
+ painter->setWorldMatrix(sav);
+#endif
+}
+
+static void
+draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img)
+{
+// dbg(lvl_debug,"enter\n");
+ if(gr->painter != NULL)
+ gr->painter->drawPixmap(p->x, p->y, *img->pixmap);
+ else
+ dbg(lvl_debug, "Try to draw image, but no painter\n");
+}
+
+static void draw_drag(struct graphics_priv *gr, struct point *p)
+{
+ if(p != NULL)
+ {
+ dbg(lvl_debug,"enter %p (%d,%d)\n", gr, p->x, p->y);
+ gr->widget->move(p->x, p->y);
+ }
+ else
+ {
+ dbg(lvl_debug,"enter %p (NULL)\n", gr);
+ gr->widget->move(0,0);
+ }
+}
+
+static void
+background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc)
+{
+// dbg(lvl_debug,"register context %p on %p\n", gc, gr);
+ gr->background_graphics_gc_priv = gc;
+}
+
+static void
+draw_mode(struct graphics_priv *gr, enum draw_mode_num mode)
+{
+ switch (mode)
+ {
+ case draw_mode_begin:
+ gr->use_count ++;
+ dbg(lvl_debug,"Begin drawing on context %p\n", gr);
+ if(gr->painter == NULL)
+ gr->painter = new QPainter(gr->pixmap);
+ else
+ dbg(lvl_debug, "drawing on %p already active\n", gr);
+ break;
+ case draw_mode_end:
+ dbg(lvl_debug,"End drawing on context %p\n", gr);
+ gr->use_count --;
+ if(gr->painter != NULL && gr->use_count == 0)
+ {
+ gr->painter->end();
+ delete(gr->painter);
+ gr->painter = NULL;
+ /* call repaint on widget */
+ gr->widget->repaint();
+ }
+ else
+ dbg(lvl_debug, "Context %p not active!", gr)
+
+ break;
+ default:
+ dbg(lvl_debug,"Unknown drawing %d on context %p\n", mode, gr);
+ break;
+ }
+}
+
+static struct graphics_priv * overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h, int wraparound);
+
+void
+resize_callback(int w, int h)
+{
+ dbg(lvl_debug,"enter (%d, %d)\n", w, h);
+ callback_list_call_attr_2(callbacks, attr_resize,
+ GINT_TO_POINTER(w), GINT_TO_POINTER(h));
+}
+
+static int
+graphics_qt5_fullscreen(struct window *w, int on)
+{
+ struct graphics_priv * gr;
+ dbg(lvl_debug,"enter\n");
+ gr = (struct graphics_priv *) w->priv;
+ if(on)
+ gr->widget->setWindowState(Qt::WindowFullScreen);
+ else
+ gr->widget->setWindowState(Qt::WindowMaximized);
+ return 1;
+}
+
+static void
+graphics_qt5_disable_suspend(struct window *w)
+{
+ dbg(lvl_debug,"enter\n");
+}
+
+static void *
+get_data(struct graphics_priv *this_priv, char const *type)
+{
+ dbg(lvl_debug,"enter: %s\n", type);
+ if (strcmp(type, "window") == 0) {
+ struct window *win;
+// dbg(lvl_debug,"window detected\n");
+ win = g_new0(struct window, 1);
+ win->priv = this_priv;
+ win->fullscreen = graphics_qt5_fullscreen;
+ win->disable_suspend = graphics_qt5_disable_suspend;
+ resize_callback(this_priv->widget->width(),this_priv->widget->height());
+ return win;
+ }
+ return NULL;
+}
+
+static void image_free(struct graphics_priv *gr, struct graphics_image_priv *priv)
+{
+ //dbg(lvl_debug,"enter\n");
+ delete(priv->pixmap);
+ g_free(priv);
+}
+
+static void get_text_bbox(struct graphics_priv *gr, struct graphics_font_priv *font, char *text, int dx, int dy, struct point *ret, int estimate)
+{
+// dbg(lvl_debug,"enter %s %d %d\n", text, dx, dy);
+ QPainter *painter=gr->painter;
+ QString tmp=QString::fromUtf8(text);
+ if(gr->painter != NULL)
+ {
+ gr->painter->setFont(*font->font);
+ QRect r=painter->boundingRect(0,0,gr->pixmap->width(),gr->pixmap->height(),0,tmp);
+// dbg (lvl_debug, "Text bbox: %d %d (%d,%d),(%d,%d)\n",dx, dy, r.left(), r.top(), r.right(), r.bottom());
+ /* low left */
+ ret[0].x = r.left();
+ ret[0].y = r.bottom();
+ /* top left */
+ ret[1].x = r.left();
+ ret[1].y = r.top();
+ /* top right */
+ ret[2].x = r.right();
+ ret[2].y = r.top();
+ /* low right */
+ ret[3].x = r.right();
+ ret[3].y = r.bottom();
+ }
+}
+
+static void overlay_disable(struct graphics_priv *gr, int disable)
+{
+ GHashTableIter iter;
+ struct graphics_priv * key, * value;
+// dbg(lvl_debug,"enter gr=%p, %d\n", gr, disable);
+
+ g_hash_table_iter_init (&iter, gr->overlays);
+ while (g_hash_table_iter_next (&iter, (void **)&key, (void **)&value))
+ {
+ /* disable or enable all overlays of this pane */
+ value->widget->setVisible(!disable);
+ }
+}
+
+static void overlay_resize(struct graphics_priv *gr, struct point *p, int w, int h, int wraparound)
+{
+ dbg(lvl_debug,"enter\n");
+
+ gr->widget->move(p->x, p->y);
+ gr->widget->setFixedSize(w, h);
+ if(gr->painter != NULL)
+ {
+ delete(gr->painter);
+ }
+ delete(gr->pixmap);
+ gr->pixmap = new QPixmap(gr->widget->size());
+ if(gr->painter != NULL)
+ gr->painter = new QPainter (gr->pixmap);
+}
+
+static struct graphics_methods graphics_methods = {
+ graphics_destroy,
+ draw_mode,
+ draw_lines,
+ draw_polygon,
+ draw_rectangle,
+ draw_circle,
+ draw_text,
+ draw_image,
+ NULL,
+ draw_drag,
+ font_new,
+ gc_new,
+ background_gc,
+ overlay_new,
+ image_new,
+ get_data,
+ image_free,
+ get_text_bbox,
+ overlay_disable,
+ overlay_resize,
+};
+
+/* create new graphics context on given context */
+static struct graphics_priv *
+overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h, int wraparound)
+{
+ struct graphics_priv * graphics_priv = NULL;
+ graphics_priv = g_new0(struct graphics_priv, 1);
+#ifdef QT_QPAINTER_USE_FREETYPE
+ if (gr->font_freetype_new) {
+ graphics_priv->font_freetype_new=gr->font_freetype_new;
+ gr->font_freetype_new(&graphics_priv->freetype_methods);
+ meth->font_new=(struct graphics_font_priv *(*)(struct graphics_priv *, struct graphics_font_methods *, char *, int, int))graphics_priv->freetype_methods.font_new;
+ meth->get_text_bbox=(void (*)(struct graphics_priv*, struct graphics_font_priv*, char*, int, int, struct point*, int))graphics_priv->freetype_methods.get_text_bbox;
+ }
+#endif
+ graphics_priv->widget = new QNavitWidget(graphics_priv, gr->widget, Qt::Widget);
+ graphics_priv->widget->move(p->x, p->y);
+ graphics_priv->widget->setFixedSize(w, h);
+ graphics_priv->widget->setVisible(true);
+ graphics_priv->pixmap = new QPixmap(graphics_priv->widget->size());
+ graphics_priv->painter = NULL;
+ graphics_priv->use_count = 0;
+ graphics_priv->parent = gr;
+ graphics_priv->overlays=g_hash_table_new(NULL, NULL);
+ /* register on parent */
+ g_hash_table_insert(gr->overlays, graphics_priv, graphics_priv);
+ dbg(lvl_debug,"New overlay: %p\n", graphics_priv);
+
+ *meth=graphics_methods;
+ return graphics_priv;
+}
+
+static int argc=3;
+static char *argv[]={"navit","-platform","wayland", NULL};
+
+/* create application and initial graphics context */
+static struct graphics_priv *
+graphics_qt5_new(struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl)
+{
+ struct graphics_priv * graphics_priv = NULL;
+ struct attr *event_loop_system = NULL;
+ *meth=graphics_methods;
+ dbg(lvl_debug,"enter\n");
+
+ event_loop_system = attr_search(attrs, NULL, attr_event_loop_system);
+
+ if (event_loop_system && event_loop_system->u.str) {
+ dbg(lvl_debug, "event_system is %s\n", event_loop_system->u.str);
+ if (!event_request_system(event_loop_system->u.str, "graphics_qt5"))
+ return NULL;
+ } else {
+ if (!event_request_system("qt5", "graphics_qt5"))
+ return NULL;
+ }
+#ifdef QT_QPAINTER_USE_FREETYPE
+ struct font_priv * (*font_freetype_new)(void *meth);
+ /* get font plugin if present */
+ font_freetype_new=(struct font_priv *(*)(void *))plugin_get_font_type("freetype");
+ if (!font_freetype_new) {
+ dbg(lvl_error,"no freetype\n");
+ return NULL;
+ }
+#endif
+
+
+ /* create surrounding application */
+ navit_app = new QApplication(argc, argv);
+ /* create root graphics layer */
+ graphics_priv = g_new0(struct graphics_priv, 1);
+
+#ifdef QT_QPAINTER_USE_FREETYPE
+ graphics_priv->font_freetype_new=font_freetype_new;
+ font_freetype_new(&graphics_priv->freetype_methods);
+ meth->font_new=(struct graphics_font_priv *(*)(struct graphics_priv *, struct graphics_font_methods *, char *, int, int))graphics_priv->freetype_methods.font_new;
+ meth->get_text_bbox=(void (*)(struct graphics_priv*, struct graphics_font_priv*, char*, int, int, struct point*, int))graphics_priv->freetype_methods.get_text_bbox;
+#endif
+
+ graphics_priv->widget = new QNavitWidget(graphics_priv,NULL,Qt::Window);
+ QRect geomet = navit_app->desktop()->screenGeometry(graphics_priv->widget);
+ graphics_priv->widget->setFixedSize(geomet.width(), geomet.height());
+ /* on most platforms we may want to show this maximized at least */
+ //graphics_priv->widget->setWindowState(Qt::WindowFullScreen);
+ /* generate initial pixmap same size as window */
+ graphics_priv->pixmap = new QPixmap(graphics_priv->widget->size());
+ graphics_priv->use_count = 0;
+ graphics_priv->painter = NULL;
+ graphics_priv->widget->show();
+ graphics_priv->parent = NULL;
+ graphics_priv->overlays=g_hash_table_new(NULL, NULL);
+ callbacks = cbl;
+ resize_callback(graphics_priv->widget->width(),graphics_priv->widget->height());
+ return graphics_priv;
+}
+
+void
+plugin_init(void)
+{
+ dbg(lvl_debug,"enter\n");
+ plugin_register_graphics_type("qt5", graphics_qt5_new);
+ qt5_event_init();
+}
diff --git a/navit/graphics/qt5/graphics_qt5.h b/navit/graphics/qt5/graphics_qt5.h
new file mode 100644
index 000000000..fb3c29f8d
--- /dev/null
+++ b/navit/graphics/qt5/graphics_qt5.h
@@ -0,0 +1,50 @@
+#ifndef __graphics_qt_h
+#define __graphics_qt_h
+#include <glib.h>
+#include <QApplication>
+#include <QPixmap>
+#include <QPainter>
+#include <QPen>
+#include <QBrush>
+#include "QNavitWidget.h"
+
+#ifndef QT_QPAINTER_USE_FREETYPE
+#define QT_QPAINTER_USE_FREETYPE 1
+#endif
+
+#ifdef QT_QPAINTER_USE_FREETYPE
+#include "navit/font/freetype/font_freetype.h"
+#endif
+
+struct graphics_gc_priv;
+struct graphics_priv;
+
+struct graphics_priv {
+ QNavitWidget * widget;
+ QPixmap * pixmap;
+ QPainter * painter;
+ int use_count;
+ struct graphics_gc_priv * background_graphics_gc_priv;
+#ifdef QT_QPAINTER_USE_FREETYPE
+ struct font_priv * (*font_freetype_new)(void *meth);
+ struct font_freetype_methods freetype_methods;
+#endif
+ GHashTable *overlays;
+ struct graphics_priv * parent;
+};
+
+struct graphics_gc_priv {
+ struct graphics_priv * graphics_priv;
+ QPen * pen;
+ QBrush * brush;
+};
+/* central exported application info */
+extern QApplication * navit_app;
+
+/* navit callback list */
+extern struct callback_list* callbacks;
+
+void
+resize_callback(int w, int h);
+
+#endif \ No newline at end of file