Exemplo n.º 1
0
void
liferea_htmlview_write (LifereaHtmlView *htmlview, const gchar *string, const gchar *base)
{ 
	const gchar	*baseURL = base;
	const gchar	*errMsg = "ERROR: Invalid encoded UTF8 buffer passed to HTML widget! This shouldn't happen.";

	if (!htmlview)
		return;
	
	htmlview->priv->internal = TRUE;	/* enables special links */
	
	if (baseURL == NULL)
		baseURL = "file:///";

	if (debug_level & DEBUG_HTML) {
		gchar *filename = common_create_cache_filename (NULL, "output", "xhtml");
		g_file_set_contents (filename, string, -1, NULL);
		g_free (filename);
	}
	
	if (!g_utf8_validate (string, -1, NULL)) {
		/* It is really a bug if we get invalid encoded UTF-8 here!!! */
		(RENDERER (htmlview)->write) (htmlview->priv->renderWidget, errMsg, strlen (errMsg), baseURL, "text/plain");
	} else {
		(RENDERER (htmlview)->write) (htmlview->priv->renderWidget, string, strlen (string), baseURL, "application/xhtml+xml");
	}

	/* We hide the toolbar as it should only be shown when loading external content */
	gtk_widget_hide (htmlview->priv->toolbar);
}
Exemplo n.º 2
0
static void traverselights( P_Transform *thistrans, P_Attrib_List *thisattr )
{
  P_Gob *self= (P_Gob *)po_this;
  P_Ren_Data *thisrendata;
  METHOD_IN

  ger_debug("gob_mthd: traverselights");
  
  thisrendata= RENLIST(self);
  while (thisrendata) {
    METHOD_RDY(RENDERER(thisrendata));
    (*(RENDERER(thisrendata)->light_traverse_gob))
      (RENDATA(thisrendata), thistrans, thisattr);
    thisrendata= thisrendata->next;
  }

  METHOD_OUT
}
Exemplo n.º 3
0
static void
liferea_htmlview_proxy_changed (NetworkMonitor *nm, gpointer userdata)
{
	LifereaHtmlView *htmlview = LIFEREA_HTMLVIEW (userdata);

	(RENDERER (htmlview)->setProxy) (network_get_proxy_host (),
	                                 network_get_proxy_port (),
	                                 network_get_proxy_username (),
	                                 network_get_proxy_password ());
}
Exemplo n.º 4
0
void
liferea_htmlview_prepare_context_menu (LifereaHtmlView *htmlview, GtkMenu *menu, const gchar *linkUri, const gchar *imageUri)
{
	GList *item, *items;
	gboolean link = (linkUri != NULL);
	gboolean image = (imageUri != NULL);

	/* first drop all menu items that are provided by the browser widget (necessary for WebKit) */
	item = items = gtk_container_get_children (GTK_CONTAINER (menu));
	while (item) {
		gtk_widget_destroy (GTK_WIDGET (item->data));
		item = g_list_next (item);
	}
	g_list_free (items);

	/* do not expose internal links */
	if (linkUri && liferea_htmlview_is_special_url (linkUri) && !g_str_has_prefix (linkUri, "javascript:") && !g_str_has_prefix (linkUri, "data:"))
		link = FALSE;

	/* and now add all we want to see */
	if (link) {
		gchar *path;
		menu_add_option (menu, _("Open Link In _Tab"), NULL, G_CALLBACK (on_popup_open_link_in_tab_activate), (gpointer)linkUri);
		menu_add_option (menu, _("_Open Link In Browser"), NULL, G_CALLBACK (on_popup_launch_link_activate), (gpointer)linkUri);
		menu_add_option (menu, _("_Open Link In External Browser"), NULL, G_CALLBACK (on_popup_launch_link_external_activate), (gpointer)linkUri);
		menu_add_separator (menu);
		
		path = g_strdup_printf (_("_Bookmark Link at %s"), social_get_bookmark_site ());
		menu_add_option (menu, path, NULL, on_popup_social_bm_link_activate, (gpointer)linkUri);
		g_free (path);

		menu_add_option (menu, _("_Copy Link Location"), "gtk-copy", G_CALLBACK (on_popup_copy_url_activate), (gpointer)linkUri);
	}
	if (image)
		menu_add_option (menu, _("_Copy Image Location"), "gtk-copy", G_CALLBACK (on_popup_copy_url_activate), (gpointer)imageUri);
	if (link)
		menu_add_option (menu, _("S_ave Link As"), "gtk-save", G_CALLBACK (on_popup_save_url_activate), (gpointer)linkUri);
	if (image)
		menu_add_option (menu, _("S_ave Image As"), "gtk-save", G_CALLBACK (on_popup_save_url_activate), (gpointer)imageUri);
	if (link) {	
		menu_add_separator (menu);
		menu_add_option (menu, _("_Subscribe..."), "gtk-add", G_CALLBACK (on_popup_subscribe_url_activate), (gpointer)linkUri);
	}
	
	if(!link && !image) {
		GtkWidget *item;
		item = menu_add_option (menu, NULL, GTK_STOCK_COPY, G_CALLBACK (on_popup_copy_activate), htmlview);
		if (!(RENDERER (htmlview)->hasSelection) (htmlview->priv->renderWidget)) 
			gtk_widget_set_sensitive (item, FALSE);

		menu_add_separator (menu);
		menu_add_option (menu, _("_Increase Text Size"), "gtk-zoom-in", G_CALLBACK (on_popup_zoomin_activate), htmlview);
		menu_add_option (menu, _("_Decrease Text Size"), "gtk-zoom-out", G_CALLBACK (on_popup_zoomout_activate), htmlview);
	}
}
Exemplo n.º 5
0
static void traverselights_to_ren( P_Renderer *ren, P_Transform *thistrans, 
				  P_Attrib_List *thisattr)
{
  P_Gob *self= (P_Gob *)po_this;
  P_Ren_Data *thisrendata;
  METHOD_IN

  ger_debug("gob_mthd: traverselights_to_ren");
  
  /* I hate to do a walk of the renderer list, but I don't
   * see an alternative.
   */
  thisrendata= RENLIST(self);
  while (thisrendata) { 
    if ( RENDERER(thisrendata) == ren ) {
      METHOD_RDY(RENDERER(thisrendata)); 
      (*(RENDERER(thisrendata)->light_traverse_gob))
	(RENDATA(thisrendata), thistrans, thisattr);
      METHOD_OUT
      return;
    }
    else thisrendata= thisrendata->next;
Exemplo n.º 6
0
void
liferea_htmlview_launch_URL_internal (LifereaHtmlView *htmlview, const gchar *url)
{
	/* before loading untrusted URLs suppress internal link schema */
	htmlview->priv->internal = FALSE;

	browser_history_add_location (htmlview->priv->history, (gchar *)url);

	gtk_widget_set_sensitive (htmlview->priv->forward, browser_history_can_go_forward (htmlview->priv->history));
	gtk_widget_set_sensitive (htmlview->priv->back,    browser_history_can_go_back (htmlview->priv->history));

	gtk_entry_set_text (GTK_ENTRY (htmlview->priv->urlentry), url);
	
	(RENDERER (htmlview)->launch) (htmlview->priv->renderWidget, url);
}
Exemplo n.º 7
0
static void
liferea_htmlview_init (LifereaHtmlView *htmlview)
{
	GtkWidget *widget, *image;

	htmlview->priv = LIFEREA_HTMLVIEW_GET_PRIVATE (htmlview);
	htmlview->priv->internal = FALSE;
	htmlview->priv->impl = htmlview_get_impl ();
	htmlview->priv->renderWidget = RENDERER (htmlview)->create (htmlview);
	htmlview->priv->container = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
	htmlview->priv->history = browser_history_new ();
	htmlview->priv->toolbar = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
	
	widget = gtk_button_new ();	
	gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
	image = gtk_image_new_from_stock ("gtk-go-back", GTK_ICON_SIZE_BUTTON);
	gtk_widget_show (image);
	gtk_container_add (GTK_CONTAINER (widget), image);
	gtk_box_pack_start (GTK_BOX (htmlview->priv->toolbar), widget, FALSE, FALSE, 0);
	g_signal_connect ((gpointer)widget, "clicked", G_CALLBACK (on_htmlview_history_back), (gpointer)htmlview);
	gtk_widget_set_sensitive (widget, FALSE);
	htmlview->priv->back = widget;

	widget = gtk_button_new ();
	gtk_button_set_relief (GTK_BUTTON(widget), GTK_RELIEF_NONE);
	image = gtk_image_new_from_stock ("gtk-go-forward", GTK_ICON_SIZE_BUTTON);
	gtk_widget_show (image);
	gtk_container_add (GTK_CONTAINER (widget), image);
	gtk_box_pack_start (GTK_BOX (htmlview->priv->toolbar), widget, FALSE, FALSE, 0);
	g_signal_connect ((gpointer)widget, "clicked", G_CALLBACK (on_htmlview_history_forward), (gpointer)htmlview);
	gtk_widget_set_sensitive (widget, FALSE);
	htmlview->priv->forward = widget;

	widget = gtk_entry_new ();
	gtk_box_pack_start (GTK_BOX (htmlview->priv->toolbar), widget, TRUE, TRUE, 0);
	g_signal_connect ((gpointer)widget, "activate", G_CALLBACK (on_htmlview_url_entry_activate), (gpointer)htmlview);
	htmlview->priv->urlentry = widget;

	gtk_box_pack_start (GTK_BOX (htmlview->priv->container), htmlview->priv->toolbar, FALSE, FALSE, 0);
	gtk_box_pack_end (GTK_BOX (htmlview->priv->container), htmlview->priv->renderWidget, TRUE, TRUE, 0);

	gtk_widget_show_all (htmlview->priv->container);
}
Exemplo n.º 8
0
static inline FAR struct nxtext_glyph_s *
nxtext_renderglyph(FAR struct nxtext_state_s *st,
                   FAR const struct nx_fontbitmap_s *fbm, uint8_t ch)
{
  FAR struct nxtext_glyph_s *glyph = NULL;
  FAR nxgl_mxpixel_t *ptr;
#if CONFIG_EXAMPLES_NXTEXT_BPP < 8
  nxgl_mxpixel_t pixel;
#endif
  int bmsize;
  int row;
  int col;
  int ret;

  /* Make sure that there is room for another glyph */

  ginfo("ch=%c [%02x]\n", isprint(ch) ? ch : '.', ch);

  /* Allocate the glyph (always succeeds) */

  glyph         = nxtext_allocglyph(st);
  glyph->code   = ch;

  /* Get the dimensions of the glyph */

  glyph->width  = fbm->metric.width + fbm->metric.xoffset;
  glyph->height = fbm->metric.height + fbm->metric.yoffset;

  /* Allocate memory to hold the glyph with its offsets */

  glyph->stride = (glyph->width * CONFIG_EXAMPLES_NXTEXT_BPP + 7) / 8;
  bmsize        =  glyph->stride * glyph->height;
  glyph->bitmap = (FAR uint8_t *)malloc(bmsize);

  if (glyph->bitmap)
    {
      /* Initialize the glyph memory to the background color */

#if CONFIG_EXAMPLES_NXTEXT_BPP < 8
      pixel  = st->wcolor[0];
#  if CONFIG_EXAMPLES_NXTEXT_BPP == 1
      /* Pack 1-bit pixels into a 2-bits */

      pixel &= 0x01;
      pixel  = (pixel) << 1 |pixel;
#  endif
#  if CONFIG_EXAMPLES_NXTEXT_BPP < 4
      /* Pack 2-bit pixels into a nibble */

      pixel &= 0x03;
      pixel  = (pixel) << 2 |pixel;
#  endif

      /* Pack 4-bit nibbles into a byte */

      pixel &= 0x0f;
      pixel  = (pixel) << 4 | pixel;

      ptr    = (FAR nxgl_mxpixel_t *)glyph->bitmap;
      for (row = 0; row < glyph->height; row++)
        {
          for (col = 0; col < glyph->stride; col++)
            {
              /* Transfer the packed bytes into the buffer */

              *ptr++ = pixel;
            }
        }

#elif CONFIG_EXAMPLES_NXTEXT_BPP == 24
# error "Additional logic is needed here for 24bpp support"

#else /* CONFIG_EXAMPLES_NXTEXT_BPP = {8,16,32} */

      ptr = (FAR nxgl_mxpixel_t *)glyph->bitmap;
      for (row = 0; row < glyph->height; row++)
        {
          /* Just copy the color value into the glyph memory */

          for (col = 0; col < glyph->width; col++)
            {
              *ptr++ = st->wcolor[0];
            }
        }
#endif

      /* Then render the glyph into the allocated memory */

      ret = RENDERER((FAR nxgl_mxpixel_t*)glyph->bitmap,
                      glyph->height, glyph->width, glyph->stride,
                      fbm, st->fcolor[0]);
      if (ret < 0)
        {
          /* Actually, the RENDERER never returns a failure */

          printf("nxtext_renderglyph: RENDERER failed\n");
          nxtext_freeglyph(glyph);
          glyph = NULL;
        }
    }

  return glyph;
}
Exemplo n.º 9
0
void nxhello_hello(NXWINDOW hwnd)
{
  FAR const struct nx_font_s *fontset;
  FAR const struct nx_fontbitmap_s *fbm;
  FAR uint8_t *glyph;
  FAR const char *ptr;
  FAR struct nxgl_point_s pos;
  FAR struct nxgl_rect_s dest;
  FAR const void *src[CONFIG_NX_NPLANES];
  unsigned int glyphsize;
  unsigned int mxstride;
  int ret;

  /* Get information about the font we are going to use */

  fontset = nxf_getfontset(g_nxhello.hfont);

  /* Allocate a bit of memory to hold the largest rendered font */

  mxstride  = (fontset->mxwidth * CONFIG_EXAMPLES_NXHELLO_BPP + 7) >> 3;
  glyphsize = (unsigned int)fontset->mxheight * mxstride;
  glyph     = (FAR uint8_t*)malloc(glyphsize);

  /* NOTE: no check for failure to allocate the memory.  In a real application
   * you would need to handle that event.
   */

  /* Get a position so the the "Hello, World!" string will be centered on the
   * display.
   */

  nxhello_center(&pos, fontset);
  message("nxhello_hello: Position (%d,%d)\n", pos.x, pos.y);

  /* Now we can say "hello" in the center of the display. */

  for (ptr = g_hello; *ptr; ptr++)
    {
      /* Get the bitmap font for this ASCII code */

      fbm = nxf_getbitmap(g_nxhello.hfont, *ptr);
      if (fbm)
        {
          uint8_t fheight;      /* Height of this glyph (in rows) */
          uint8_t fwidth;       /* Width of this glyph (in pixels) */
          uint8_t fstride;      /* Width of the glyph row (in bytes) */

          /* Get information about the font bitmap */

          fwidth  = fbm->metric.width + fbm->metric.xoffset;
          fheight = fbm->metric.height + fbm->metric.yoffset;
          fstride = (fwidth * CONFIG_EXAMPLES_NXHELLO_BPP + 7) >> 3;

          /* Initialize the glyph memory to the background color */

          nxhello_initglyph(glyph, fheight, fwidth, fstride);

          /* Then render the glyph into the allocated memory */

#if CONFIG_NX_NPLANES > 1
# warning "More logic is needed for the case where CONFIG_NX_PLANES > 1"
#endif
          (void)RENDERER((FAR nxgl_mxpixel_t*)glyph, fheight, fwidth,
                         fstride, fbm, CONFIG_EXAMPLES_NXHELLO_FONTCOLOR);

          /* Describe the destination of the font with a rectangle */

          dest.pt1.x = pos.x;
          dest.pt1.y = pos.y;
          dest.pt2.x = pos.x + fwidth - 1;
          dest.pt2.y = pos.y + fheight - 1;
   
          /* Then put the font on the display */

          src[0] = (FAR const void *)glyph;
#if CONFIG_NX_NPLANES > 1
# warning "More logic is needed for the case where CONFIG_NX_PLANES > 1"
#endif
          ret = nx_bitmap((NXWINDOW)hwnd, &dest, src, &pos, fstride);
          if (ret < 0)
            {
              message("nxhello_write: nx_bitmapwindow failed: %d\n", errno);
            }

           /* Skip to the right the width of the font */

          pos.x += fwidth;
        }
      else
        {
           /* No bitmap (probably because the font is a space).  Skip to the
            * right the width of a space.
            */

          pos.x += fontset->spwidth;
        }
    }
Exemplo n.º 10
0
static inline FAR struct nxcon_glyph_s *
nxcon_renderglyph(FAR struct nxcon_state_s *priv,
                   FAR const struct nx_fontbitmap_s *fbm, uint8_t ch)
{
  FAR struct nxcon_glyph_s *glyph = NULL;
  FAR nxgl_mxpixel_t *ptr;
#if CONFIG_NXCONSOLE_BPP < 8
  nxgl_mxpixel_t pixel;
#endif
  int bmsize;
  int row;
  int col;
  int ret;

  /* Allocate the glyph (always succeeds) */

  glyph         = nxcon_allocglyph(priv);
  glyph->code   = ch;

  /* Get the dimensions of the glyph */

  glyph->width  = fbm->metric.width + fbm->metric.xoffset;
  glyph->height = fbm->metric.height + fbm->metric.yoffset;

  /* Get the physical width of the glyph in bytes */

  glyph->stride = (glyph->width * CONFIG_NXCONSOLE_BPP + 7) / 8;

  /* Allocate memory to hold the glyph with its offsets */

  bmsize        =  glyph->stride * glyph->height;
  glyph->bitmap = (FAR uint8_t *)kmalloc(bmsize);

  if (glyph->bitmap)
    {
      /* Initialize the glyph memory to the background color using the
       * hard-coded bits-per-pixel (BPP).
       *
       * TODO:  The rest of NX is configured to support multiple devices
       * with differing BPP.  They logic should be extended to support
       * differing BPP's as well.
       */

#if CONFIG_NXCONSOLE_BPP < 8
      pixel  = priv->wndo.wcolor[0];

#  if CONFIG_NXCONSOLE_BPP == 1

      /* Pack 1-bit pixels into a 2-bits */

      pixel &= 0x01;
      pixel  = (pixel) << 1 | pixel;

#  endif
#  if CONFIG_NXCONSOLE_BPP < 4

      /* Pack 2-bit pixels into a nibble */

      pixel &= 0x03;
      pixel  = (pixel) << 2 | pixel;

#  endif

      /* Pack 4-bit nibbles into a byte */

      pixel &= 0x0f;
      pixel  = (pixel) << 4 | pixel;

      ptr    = (FAR nxgl_mxpixel_t *)glyph->bitmap;
      for (row = 0; row < glyph->height; row++)
        {
          for (col = 0; col < glyph->stride; col++)
            {
              /* Transfer the packed bytes into the buffer */

              *ptr++ = pixel;
            }
        }

#elif CONFIG_NXCONSOLE_BPP == 24
# error "Additional logic is needed here for 24bpp support"

#else /* CONFIG_NXCONSOLE_BPP = {8,16,32} */

      ptr = (FAR nxgl_mxpixel_t *)glyph->bitmap;
      for (row = 0; row < glyph->height; row++)
        {
          /* Just copy the color value into the glyph memory */

          for (col = 0; col < glyph->width; col++)
            {
              *ptr++ = priv->wndo.wcolor[0];
            }
        }
#endif

      /* Then render the glyph into the allocated memory */

      ret = RENDERER((FAR nxgl_mxpixel_t*)glyph->bitmap,
                      glyph->height, glyph->width, glyph->stride,
                      fbm, priv->wndo.fcolor[0]);
      if (ret < 0)
        {
          /* Actually, the RENDERER never returns a failure */

          gdbg("nxcon_renderglyph: RENDERER failed\n");
          nxcon_freeglyph(glyph);
          glyph = NULL;
        }
    }

  return glyph;
}
Exemplo n.º 11
0
static void
on_popup_copy_activate (GtkWidget *widget, LifereaHtmlView *htmlview)
{
	(RENDERER (htmlview)->copySelection) (htmlview->priv->renderWidget); 
}
Exemplo n.º 12
0
gboolean
liferea_htmlview_scroll (LifereaHtmlView *htmlview)
{
	return (RENDERER (htmlview)->scrollPagedown) (htmlview->priv->renderWidget);
}
Exemplo n.º 13
0
gfloat
liferea_htmlview_get_zoom (LifereaHtmlView *htmlview)
{
	return (RENDERER (htmlview)->zoomLevelGet) (htmlview->priv->renderWidget);
}
Exemplo n.º 14
0
void
liferea_htmlview_set_zoom (LifereaHtmlView *htmlview, gfloat diff)
{
	(RENDERER (htmlview)->zoomLevelSet) (htmlview->priv->renderWidget, diff); 
}
Exemplo n.º 15
0
static void
liferea_htmlview_set_online (LifereaHtmlView *htmlview, gboolean online)
{
	if (RENDERER (htmlview)->setOffLine)
		(RENDERER (htmlview)->setOffLine) (!online);
}
Exemplo n.º 16
0
void doDrawGlyphs(PangoRenderer* renderer, PangoFont* font, PangoGlyphString* glyphs, int px, int py) {
    Renderer* ren = RENDERER(renderer);
    if (!ren->m_runs) return;
    std::vector<ViewdoTextRun>& runs = *(ren->m_runs);
    const float s = ren->m_scale;

    PangoColor* fg = pango_renderer_get_color(renderer, PANGO_RENDER_PART_FOREGROUND);
    //PangoColor* bg = pango_renderer_get_color(renderer, PANGO_RENDER_PART_BACKGROUND);

    float red = !fg ? 0.0f : fg->red / 65536.0f;
    float green = !fg ? 0.0f : fg->green / 65536.0f;
    float blue = !fg ? 0.0f : fg->blue / 65536.0f;

    PangoFontDescription* desc = pango_font_describe(font);
    unsigned int fontHash = pango_font_description_hash(desc);
    pango_font_description_free(desc);

    FT_Face face = pango_fc_font_lock_face((PangoFcFont*) font);

    PangoGlyphUnit layoutX = px;
    PangoGlyphUnit layoutY = py;
    ViewdoGlyphCache& cache = ViewdoGlyphCache::instance();

    for (int i = 0; i < glyphs->num_glyphs; i++) {
        PangoGlyphInfo* gi = glyphs->glyphs + i;

        if (gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG) {
            // XXX: Draw the fallback square.
            continue;
        }

        unsigned int glyph = gi->glyph;
        PangoRectangle r;
        
        pango_font_get_glyph_extents(font, glyph, &r, 0);
        pango_extents_to_pixels(&r, 0);

        float w = r.width;
        float h = r.height;

        if (w <= 0.f && h <= 0.f) {
            // Space.
            layoutX += gi->geometry.width;
            continue;
        }

        // Load and render the glyph. We probably need to just tell the font to cache it
        // and then grab the coordinates of it.
        const ViewdoGlyph& cachedGlyph = cache.findOrCreate(gi->glyph, fontHash, face);
        
        // Walk our existing runs and try to find one with the same color and page.
        // XXX: Fastpath try and use the run from the last glyph.
        ViewdoTextRun* run = nullptr;
        for (auto i = runs.begin(); i != runs.end(); i++) {
            if (i->m_page == cachedGlyph.m_page && i->m_red == red && i->m_green == green && i->m_blue == blue) {
                run = &(*i);
                break;
            }
        }
        if (!run) {
            runs.push_back(ViewdoTextRun(cachedGlyph.m_page, red, green, blue));
            run = &(runs[runs.size() - 1]);
        }

        float x = PANGO_PIXELS(layoutX + gi->geometry.x_offset) + cachedGlyph.m_offsetLeft;
        float y = PANGO_PIXELS(layoutY + gi->geometry.y_offset) - cachedGlyph.m_offsetTop;

        // Append ourselves onto this run.
        addPoint(run->m_geometry,
            x, y,
            cachedGlyph.m_x0, cachedGlyph.m_y0,
            s);

        addPoint(run->m_geometry,
            x + cachedGlyph.m_width, y,
            cachedGlyph.m_x1, cachedGlyph.m_y0,
            s);

        addPoint(run->m_geometry,
            x, y + cachedGlyph.m_height,
            cachedGlyph.m_x0, cachedGlyph.m_y1,
            s);

        // Triangle 2.
        addPoint(run->m_geometry,
            x + cachedGlyph.m_width, y,
            cachedGlyph.m_x1, cachedGlyph.m_y0,
            s);

        addPoint(run->m_geometry,
            x, y + cachedGlyph.m_height,
            cachedGlyph.m_x0, cachedGlyph.m_y1,
            s);

        addPoint(run->m_geometry,
            x + cachedGlyph.m_width, y + cachedGlyph.m_height,
            cachedGlyph.m_x1, cachedGlyph.m_y1,
            s);

        layoutX += gi->geometry.width;
    }

    pango_fc_font_unlock_face((PangoFcFont*) font);
}