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); }
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 }
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 ()); }
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); } }
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;
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); }
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); }
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; }
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; } }
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; }
static void on_popup_copy_activate (GtkWidget *widget, LifereaHtmlView *htmlview) { (RENDERER (htmlview)->copySelection) (htmlview->priv->renderWidget); }
gboolean liferea_htmlview_scroll (LifereaHtmlView *htmlview) { return (RENDERER (htmlview)->scrollPagedown) (htmlview->priv->renderWidget); }
gfloat liferea_htmlview_get_zoom (LifereaHtmlView *htmlview) { return (RENDERER (htmlview)->zoomLevelGet) (htmlview->priv->renderWidget); }
void liferea_htmlview_set_zoom (LifereaHtmlView *htmlview, gfloat diff) { (RENDERER (htmlview)->zoomLevelSet) (htmlview->priv->renderWidget, diff); }
static void liferea_htmlview_set_online (LifereaHtmlView *htmlview, gboolean online) { if (RENDERER (htmlview)->setOffLine) (RENDERER (htmlview)->setOffLine) (!online); }
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); }