drawing: replace ? avatar by a fallback image and supports special characters

Change-Id: I85f2112ca8321f5242b78bdc72b3a11165e381a1
Reviewed-by: Philippe Gorley <philippe.gorley@savoirfairelinux.com>
diff --git a/pixmaps/fallbackavatar.svg b/pixmaps/fallbackavatar.svg
new file mode 100644
index 0000000..f8b6a6e
--- /dev/null
+++ b/pixmaps/fallbackavatar.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" ?>
+<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg">
+  <path d="M8.013766 23.107838l0.00465 -0.810382 0.033095 -0.133474c0.1495327 -0.603099 0.50107 -1.099452 1.1411917 -1.611311 0.1690725 -0.135195 0.5493165 -0.388522 0.7866284 -0.524069 1.4449359 -0.825313 3.6497829 -1.439907 5.5693029 -1.552424 0.268992 -0.01577 0.866138 -0.0085 1.131356 0.01373 1.873734 0.157215 3.884055 0.729268 5.262712 1.497544 1.031356 0.574739 1.70347 1.254543 1.937152 1.959316 0.101301 0.305518 0.100213 0.293393 0.105924 1.180132l0.0051 0.791314 -7.990878 0 -7.990878 0 0.00465 -0.810381z" fill="#ffffff"/>
+  <path d="M15.641818 15.906151c-0.512638 -0.04757 -0.970838 -0.177847 -1.424519 -0.40503 -0.534623 -0.267715 -0.972855 -0.622072 -1.344489 -1.087162 -0.500329 -0.626146 -0.797007 -1.385268 -0.858271 -2.196087 -0.01377 -0.182277 -0.0068 -0.568261 0.01341 -0.738308 0.137062 -1.155519 0.73576 -2.1602655 1.685808 -2.8291565 1.010233 -0.711264 2.333521 -0.90809 3.519055 -0.523424 0.511977 0.166119 0.9845 0.434474 1.39324 0.791249 0.103105 0.09 0.316993 0.304905 0.402137 0.404056 0.848222 0.9877635 1.16007 2.3144245 0.843044 3.5864705 -0.116312 0.466694 -0.339476 0.947863 -0.621858 1.340798 -0.695617 0.967955 -1.761735 1.568261 -2.95044 1.661324 -0.155481 0.01217 -0.501821 0.0097 -0.657113 -0.0047z" fill="#ffffff"/>
+</svg>
diff --git a/pixmaps/pixmaps.gresource.xml b/pixmaps/pixmaps.gresource.xml
index da6f6d8..6f66dc5 100644
--- a/pixmaps/pixmaps.gresource.xml
+++ b/pixmaps/pixmaps.gresource.xml
@@ -32,5 +32,6 @@
     <file alias="invite">ic_person_add_black_24px.svg</file>
     <file alias="temporary-item">ic_search_black_48px.svg</file>
     <file alias="audio_only_call_start">ic_call_black_24px.svg</file>
+    <file alias="fallbackavatar">fallbackavatar.svg</file>
   </gresource>
 </gresources>
diff --git a/src/native/pixbufmanipulator.cpp b/src/native/pixbufmanipulator.cpp
index 5b1df61..2b5b6f3 100644
--- a/src/native/pixbufmanipulator.cpp
+++ b/src/native/pixbufmanipulator.cpp
@@ -37,7 +37,6 @@
 #include <api/account.h>
 #include <api/contact.h>
 
-
 namespace Interfaces {
 
 PixbufManipulator::PixbufManipulator()
@@ -66,21 +65,19 @@
 PixbufManipulator::generateAvatar(const ContactMethod* cm) const
 {
     auto cm_number = QString("0");
-    auto letter = QChar('?'); // R for ring
+    QString bestName;
     if (cm) {
         auto hashName = cm->uri().userinfo();
         if (hashName.size() > 0) {
             cm_number = hashName.at(0);
         }
-        // Get the letter to draw
+        // Get the bestName to draw
         if (!cm->bestName().isEmpty()) {
             // Prioritize the name
-            letter = cm->bestName().toUpper().at(0);
+            bestName = cm->bestName().toUpper();
         } else if (!cm->bestId().isEmpty()) {
             // If the contact has no name, use the id
-            letter = cm->bestId().toUpper().at(0);
-        } else {
-            // R for ring is used
+            bestName = cm->bestId().toUpper();
         }
     }
 
@@ -88,22 +85,27 @@
     auto color = cm_number.toUInt(&ok, 16);
     if (!ok) color = 0;
 
+    // Retrieve first character
+    auto letter = bestName.isEmpty() ? "" : QString(bestName.at(0)).toStdString();
+
     return std::shared_ptr<GdkPixbuf> {
         ring_draw_fallback_avatar(
             FALLBACK_AVATAR_SIZE,
-            letter.toLatin1(),
+            letter,
             color
         ),
         g_object_unref
     };
+
 }
 
 std::shared_ptr<GdkPixbuf>
 PixbufManipulator::generateAvatar(const std::string& alias, const std::string& uri) const
 {
     auto name = alias;
-    std::transform(name.begin(), name.end(), name.begin(), ::toupper);
-    auto letter = name.length() > 0 ? name[0] : '?';
+    std::string letter = {};
+    if (!name.empty())
+        letter = QString(QString(name.c_str()).toUpper().at(0)).toStdString();
     auto color = 0;
     try {
         color = uri.length() > 0 ? std::stoi(std::string(1, uri[0]), 0, 16) : 0;
diff --git a/src/utils/drawing.cpp b/src/utils/drawing.cpp
index b2932ff..b5756e0 100644
--- a/src/utils/drawing.cpp
+++ b/src/utils/drawing.cpp
@@ -49,7 +49,7 @@
                                                 {0.376470, 0.490196, 0.545098, 1.0}};// red 95, green 124, blue 138, 1 (blue grey)
 
 GdkPixbuf *
-ring_draw_fallback_avatar(int size, const char letter, const char color) {
+ring_draw_fallback_avatar(int size, const std::string& letter, const char color) {
     cairo_surface_t *surface;
     cairo_t *cr;
 
@@ -60,18 +60,27 @@
     cairo_set_source_rgb (cr, bg_color.red, bg_color.green, bg_color.blue);
     cairo_paint(cr);
 
-    // Draw a letter at the center of the avatar
-    cairo_text_extents_t extents;
-    cairo_select_font_face (cr, "monospace", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
-    cairo_set_font_size(cr, size / 2);
-    cairo_set_source_rgb (cr, 1, 1, 1);
-    char first_letter[2] = {0};
-    first_letter[0] = letter;
-    cairo_text_extents (cr, first_letter, &extents);
-    auto x = size/2-(extents.width/2 + extents.x_bearing);
-    auto y = size/2-(extents.height/2 + extents.y_bearing);
-    cairo_move_to (cr, x, y);
-    cairo_show_text(cr, first_letter);
+    if (!letter.empty()) {
+        // Draw a letter at the center of the avatar
+        cairo_text_extents_t extents;
+        cairo_select_font_face(cr, "monospace", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
+        cairo_set_font_size(cr, size / 2);
+        cairo_set_source_rgb(cr, 1, 1, 1);
+        cairo_text_extents(cr, letter.c_str(), &extents);
+        auto x = size/2-(extents.width/2 + extents.x_bearing);
+        auto y = size/2-(extents.height/2 + extents.y_bearing);
+        cairo_move_to(cr, x, y);
+        cairo_show_text(cr, letter.c_str());
+    } else {
+        // Compose from fallback svg if no letter found
+        GError *error = nullptr;
+        auto* finalAvatar = gdk_pixbuf_get_from_surface(cairo_get_target(cr), 0, 0, size, size);
+        auto* fallbackavatar = gdk_pixbuf_new_from_resource_at_scale("/cx/ring/RingGnome/fallbackavatar", size, size, true, &error);
+        gdk_pixbuf_composite (fallbackavatar, finalAvatar, 0, 0, size, size, 0, 0, 1, 1, GDK_INTERP_BILINEAR, 0xff);
+
+        return finalAvatar;
+    }
+
 
     GdkPixbuf *pixbuf = gdk_pixbuf_get_from_surface(cairo_get_target(cr), 0, 0, size, size);
 
@@ -119,8 +128,6 @@
     return pixbuf;
 }
 
-#include <iostream>
-
 GdkPixbuf *
 ring_frame_avatar(GdkPixbuf *avatar) {
 
diff --git a/src/utils/drawing.h b/src/utils/drawing.h
index 7c9ef6d..e5d8d48 100644
--- a/src/utils/drawing.h
+++ b/src/utils/drawing.h
@@ -21,8 +21,9 @@
 #define _DRAWING_H
 
 #include <gtk/gtk.h>
+#include <string>
 
-GdkPixbuf *ring_draw_fallback_avatar(int size, const char letter, const char color = 0);
+GdkPixbuf *ring_draw_fallback_avatar(int size, const std::string& letter, const char color = 0);
 
 GdkPixbuf *ring_draw_conference_avatar(int size);