[gnome-maps/wip/mlundblad/dont-use-offscreen-window: 4/16] printLayout: Stop using GtkOffscreenWindow



commit ead4817877d4a4c512b66758e1fd9da72f5698aa
Author: Marcus Lundblad <ml update uu se>
Date:   Thu Mar 14 23:21:10 2019 +0100

    printLayout: Stop using GtkOffscreenWindow
    
    Render the instruction list with Cairo and Pango.
    
    Fixes #78

 src/printLayout.js | 122 ++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 97 insertions(+), 25 deletions(-)
---
diff --git a/src/printLayout.js b/src/printLayout.js
index 6cc075e..d91d289 100644
--- a/src/printLayout.js
+++ b/src/printLayout.js
@@ -20,16 +20,18 @@
 const Cairo = imports.cairo;
 const Champlain = imports.gi.Champlain;
 const Clutter = imports.gi.Clutter;
+const Gdk = imports.gi.Gdk;
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 const Pango = imports.gi.Pango;
 const PangoCairo = imports.gi.PangoCairo;
 
 const Application = imports.application;
-const InstructionRow = imports.instructionRow;
+const Color = imports.color;
 const MapView = imports.mapView;
 const MapSource = imports.mapSource;
 const TurnPointMarker = imports.turnPointMarker;
+const Utils = imports.utils;
 
 /* Following constant has unit as meters */
 const _SHORT_LAYOUT_MAX_DISTANCE = 3000;
@@ -97,6 +99,11 @@ var PrintLayout = GObject.registerClass({
         this._surfacesRendered = 0;
         this.renderFinished = false;
         this._initSignals();
+
+        this._rtl = Gtk.get_locale_direction() === Gtk.TextDirection.RTL;
+        // directional override character to force alignment of labels
+        this._dirChar = this._rtl ? '\u200F' : '\u200E';
+        this._fontDescription = Pango.FontDescription.from_string("sans");
     }
 
     render() {
@@ -195,37 +202,102 @@ var PrintLayout = GObject.registerClass({
         this._route.path.forEach((node) => routeLayer.add_node(node));
     }
 
+    _drawIcon(cr, iconName, width, height) {
+        let theme = Gtk.IconTheme.get_default();
+        let pixbuf = theme.load_icon(iconName, height, 0);
+        let iconWidth = pixbuf.width;
+        let iconHeight = pixbuf.height;
+
+        Gdk.cairo_set_source_pixbuf(cr, pixbuf,
+                                    this._rtl ?
+                                    width - height + (height - iconWidth) / 2 :
+                                    (height - iconWidth) / 2,
+                                    (height - iconWidth) / 2);
+        cr.paint();
+    }
+
+    _createTextLayout(cr, text, width, height, alignment) {
+        let layout = PangoCairo.create_layout(cr);
+
+        layout.set_text(this._dirChar + text, -1);
+        layout.set_height(Pango.units_from_double(height));
+        layout.set_width(Pango.units_from_double(width));
+        layout.set_font_description(this._fontDescription);
+        layout.set_alignment(alignment);
+        layout.set_ellipsize(Pango.EllipsizeMode.END);
+
+        return layout;
+    }
+
+    _drawText(cr, text, x, y, width, height, alignment) {
+        this._drawTextWithColor(cr, text, x, y, width, height, '000000', alignment);
+    }
+
+    _drawTextWithColor(cr, text, x, y, width, height, color, alignment) {
+        let layout = this._createTextLayout(cr, text, width, height, alignment);
+
+        this._drawTextLayoutWithColor(cr, layout, x, y, width, height, color,
+                                      alignment);
+    }
+
+    _drawTextLayoutWithColor(cr, layout, x, y, width, height, color, alignment) {
+        let red = Color.parseColor(color, 0);
+        let green = Color.parseColor(color, 1);
+        let blue = Color.parseColor(color, 2);
+
+        cr.moveTo(x, y);
+        cr.setSourceRGB(red, green, blue);
+        PangoCairo.show_layout(cr, layout);
+    }
+
+    _drawTextVerticallyCentered(cr, text, width, height, x, alignment) {
+        this._drawTextVerticallyCenteredWithColor(cr, text, width, height, x,
+                                                  '000000', alignment);
+    }
+
+    _drawTextVerticallyCenteredWithColor(cr, text, width, height, x, color,
+                                         alignment) {
+        let layout = this._createTextLayout(cr, text, width, height, alignment);
+        let [pWidth, pHeight] = layout.get_pixel_size();
+        let red = Color.parseColor(color, 0);
+        let green = Color.parseColor(color, 1);
+        let blue = Color.parseColor(color, 2);
+
+        // place text centered
+        cr.moveTo(x, (height - pHeight) / 2);
+        cr.setSourceRGB(red, green, blue);
+        PangoCairo.show_layout(cr, layout);
+    }
+
     _drawInstruction(width, height, turnPoint) {
         let pageNum = this.numPages - 1;
         let x = this._cursorX;
         let y = this._cursorY;
-        let instructionWidget = new Gtk.OffscreenWindow({ visible: true });
-        let instructionEntry =  new InstructionRow.InstructionRow({
-            visible: true,
-            turnPoint: turnPoint,
-            hasColor: turnPoint.isStop(),
-            lines: 2
-        });
+        let surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, width, height);
+        let cr = new Cairo.Context(surface);
+        let iconName = turnPoint.iconName;
 
-        instructionWidget.get_style_context().add_class('printing-text');
-        instructionWidget.width_request = width;
-        instructionWidget.height_request = height;
+        if (iconName) {
+            this._drawIcon(cr, iconName, width, height);
+        }
 
-        /* Paint the background of the entry to be transparent */
-        instructionEntry.connect('draw', (widget, cr) => {
-            cr.setSourceRGBA(0.0, 0.0, 0.0, 0.0);
-            cr.setOperator(Cairo.Operator.SOURCE);
-            cr.paint();
-            cr.setOperator(Cairo.Operator.OVER);
-        });
+        // draw the instruction text
+        this._drawTextVerticallyCentered(cr, turnPoint.instruction,
+                                         width - height * 3, height,
+                                         this._rtl ? height * 2 : height,
+                                         Pango.Alignment.LEFT);
+
+        // draw the distance text
+        if (turnPoint.distance > 0) {
+            this._drawTextVerticallyCentered(cr,
+                                             Utils.prettyDistance(turnPoint.distance),
+                                             height * 2,
+                                             height,
+                                             this._rtl ? 0 : width - height * 2,
+                                             Pango.Alignment.RIGHT);
+        }
 
-        instructionEntry.queue_draw();
-        instructionWidget.add(instructionEntry);
-        instructionWidget.set_valign(Gtk.Align.START);
-        instructionWidget.connect('damage-event', (widget) => {
-            let surface = widget.get_surface();
-            this._addSurface(surface, x, y, pageNum);
-        });
+        this._addSurface(surface, x, y, pageNum);
     }
 
     _drawHeader(width, height) {


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