[gnome-characters] characterList: Show invisible character names



commit f62d9dda0be75ccb3f3eae42e6d92780d7803317
Author: Daiki Ueno <dueno src gnome org>
Date:   Fri Dec 4 17:11:12 2015 +0900

    characterList: Show invisible character names
    
    https://bugzilla.gnome.org/show_bug.cgi?id=757815

 lib/gc.c             |   15 +++++++++++
 lib/gc.h             |    3 ++
 src/characterList.js |   64 +++++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 76 insertions(+), 6 deletions(-)
---
diff --git a/lib/gc.c b/lib/gc.c
index 85138ec..c433e3f 100644
--- a/lib/gc.c
+++ b/lib/gc.c
@@ -494,6 +494,21 @@ gc_character_name (gunichar uc)
   return unicode_character_name (uc, g_new0 (gchar, UNINAME_MAX));
 }
 
+/**
+ * gc_character_is_invisible:
+ * @uc: a UCS-4 character
+ *
+ * Returns: %TRUE if @uc is an invisible character, %FALSE otherwise.
+ */
+gboolean
+gc_character_is_invisible (gunichar uc)
+{
+  return uc_is_property_space (uc)
+    || uc_is_property_iso_control (uc)
+    || uc_is_property_format_control (uc)
+    || uc_is_property_zero_width (uc);
+}
+
 GQuark
 gc_search_error_quark (void)
 {
diff --git a/lib/gc.h b/lib/gc.h
index 5a074af..8164304 100644
--- a/lib/gc.h
+++ b/lib/gc.h
@@ -86,6 +86,9 @@ gboolean              gc_search_context_is_finished
                                             (GcSearchContext      *context);
 
 gchar                *gc_character_name     (gunichar              uc);
+gboolean              gc_character_is_invisible
+                                            (gunichar              uc);
+
 
 /* GTK+ support.  gtk_clipboard_get() takes an GdkAtom as the first
    argument, but GdkAtom is not accessible through GI.  */
diff --git a/src/characterList.js b/src/characterList.js
index d39f9db..e43ef2c 100644
--- a/src/characterList.js
+++ b/src/characterList.js
@@ -23,6 +23,7 @@ const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 const Gdk = imports.gi.Gdk;
+const Cairo = imports.cairo;
 const Pango = imports.gi.Pango;
 const PangoCairo = imports.gi.PangoCairo;
 const Gc = imports.gi.Gc;
@@ -53,6 +54,9 @@ const CharacterListRow = new Lang.Class({
         this.parent(params);
         this._characters = filtered.characters;
         this._fontDescription = filtered.fontDescription;
+        var fontDescription = filtered.fontDescription.copy();
+        fontDescription.set_size(fontDescription.get_size() * 0.18);
+        this._overlayFontDescription = fontDescription;
     },
 
     draw: function(cr, x, y, width, height) {
@@ -72,14 +76,62 @@ const CharacterListRow = new Lang.Class({
         let cellSize = getCellSize(this._fontDescription);
         for (let i in this._characters) {
             layout.set_text(this._characters[i], -1);
-            let layoutBaseline = layout.get_baseline() / Pango.SCALE;
-            let [logicalRect, inkRect] = layout.get_extents();
-            cr.moveTo(x + cellSize * i - logicalRect.x / Pango.SCALE +
-                      (cellSize - logicalRect.width / Pango.SCALE) / 2,
-                      y + BASELINE_OFFSET * height - layoutBaseline);
-            PangoCairo.show_layout(cr, layout);
+            if (Gc.character_is_invisible (this._characters[i])) {
+                this._drawOverlay(cr, x + cellSize * i, y, cellSize, cellSize,
+                                  this._characters[i]);
+            } else {
+                let layoutBaseline = layout.get_baseline();
+                let [logicalRect, inkRect] = layout.get_extents();
+                cr.moveTo(x + cellSize * i - logicalRect.x / Pango.SCALE +
+                          (cellSize - logicalRect.width / Pango.SCALE) / 2,
+                          y + BASELINE_OFFSET * height -
+                          layoutBaseline / Pango.SCALE);
+                PangoCairo.show_layout(cr, layout);
+            }
         }
     },
+
+    _drawOverlay: function(cr, x, y, width, height, uc) {
+        cr.save();
+        cr.rectangle(x, y, width, height);
+        cr.clip();
+
+        // Draw character shape as a gray rectangle.
+        let layout = PangoCairo.create_layout(cr);
+        layout.set_text(uc, -1);
+        layout.set_font_description(this._fontDescription);
+        let layoutBaseline = layout.get_baseline();
+        let [logicalRect, inkRect] = layout.get_extents();
+        let x0 = x - inkRect.x / Pango.SCALE +
+            (width - inkRect.width / Pango.SCALE) / 2;
+        let y0 = y + BASELINE_OFFSET * height - layoutBaseline / Pango.SCALE;
+        let borderWidth = 1;
+        cr.rectangle(x0 - borderWidth * 2,
+                     y0 - borderWidth * 2,
+                     inkRect.width / Pango.SCALE + borderWidth * 2,
+                     inkRect.height / Pango.SCALE + borderWidth * 2);
+        cr.setSourceRGBA(239.0 / 255.0, 239.0 / 255.0, 239.0 / 255.0, 1.0);
+        cr.fill();
+
+        // Draw character name.
+        layout.set_width(width * Pango.SCALE * 0.8);
+        layout.set_height(height * Pango.SCALE * 0.8);
+        layout.set_wrap(Pango.WrapMode.WORD);
+        layout.set_ellipsize(Pango.EllipsizeMode.END);
+        layout.set_alignment(Pango.Alignment.CENTER);
+        layout.set_font_description(this._overlayFontDescription);
+        var name = Gc.character_name(uc);
+        layout.set_text(Util.capitalize(name), -1);
+        let [logicalRect, inkRect] = layout.get_extents();
+        cr.moveTo(x - logicalRect.x / Pango.SCALE +
+                  (width - logicalRect.width / Pango.SCALE) / 2,
+                  y - logicalRect.y / Pango.SCALE +
+                  (height - logicalRect.height / Pango.SCALE) / 2);
+        cr.setSourceRGBA(0.0, 0.0, 0.0, 1.0);
+        PangoCairo.show_layout(cr, layout);
+
+        cr.restore();
+    }
 });
 
 const CharacterListWidget = new Lang.Class({


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]