Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
  3.  *
  4.  * Framebuffer interface
  5.  *
  6.  * This file is part of NetSurf, http://www.netsurf-browser.org/
  7.  *
  8.  * NetSurf is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; version 2 of the License.
  11.  *
  12.  * NetSurf is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include <stdbool.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25.  
  26. #include <libnsfb.h>
  27. #include <libnsfb_plot.h>
  28. #include <libnsfb_event.h>
  29. #include <libnsfb_cursor.h>
  30.  
  31. #include "utils/log.h"
  32. #include "desktop/browser.h"
  33. #include "image/bitmap.h"
  34.  
  35. #include "framebuffer/gui.h"
  36. #include "framebuffer/fbtk.h"
  37. #include "framebuffer/framebuffer.h"
  38. #include "framebuffer/font.h"
  39.  
  40.  
  41. /* netsurf framebuffer library handle */
  42. static nsfb_t *nsfb;
  43.  
  44.  
  45. static bool
  46. framebuffer_plot_disc(int x, int y, int radius, const plot_style_t *style)
  47. {
  48.     nsfb_bbox_t ellipse;
  49.     ellipse.x0 = x - radius;
  50.     ellipse.y0 = y - radius;
  51.     ellipse.x1 = x + radius;
  52.     ellipse.y1 = y + radius;
  53.  
  54.     if (style->fill_type != PLOT_OP_TYPE_NONE) {
  55.         nsfb_plot_ellipse_fill(nsfb, &ellipse, style->fill_colour);
  56.     }
  57.  
  58.     if (style->stroke_type != PLOT_OP_TYPE_NONE) {
  59.         nsfb_plot_ellipse(nsfb, &ellipse, style->stroke_colour);
  60.     }
  61.     return true;
  62. }
  63.  
  64. static bool
  65. framebuffer_plot_arc(int x, int y, int radius, int angle1, int angle2, const plot_style_t *style)
  66. {
  67.     return nsfb_plot_arc(nsfb, x, y, radius, angle1, angle2, style->fill_colour);
  68. }
  69.  
  70. static bool
  71. framebuffer_plot_polygon(const int *p, unsigned int n, const plot_style_t *style)
  72. {
  73.     return nsfb_plot_polygon(nsfb, p, n, style->fill_colour);
  74. }
  75.  
  76.  
  77. #ifdef FB_USE_FREETYPE
  78. static bool
  79. framebuffer_plot_text(int x, int y, const char *text, size_t length,
  80.                 const plot_font_style_t *fstyle)
  81. {
  82.         uint32_t ucs4;
  83.         size_t nxtchr = 0;
  84.         FT_Glyph glyph;
  85.         FT_BitmapGlyph bglyph;
  86.         nsfb_bbox_t loc;
  87.  
  88.         while (nxtchr < length) {
  89.                 ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr);
  90.                 nxtchr = utf8_next(text, length, nxtchr);
  91.  
  92.                 glyph = fb_getglyph(fstyle, ucs4);
  93.                 if (glyph == NULL)
  94.                         continue;
  95.  
  96.                 if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
  97.                         bglyph = (FT_BitmapGlyph)glyph;
  98.  
  99.                         loc.x0 = x + bglyph->left;
  100.                         loc.y0 = y - bglyph->top;
  101.                         loc.x1 = loc.x0 + bglyph->bitmap.width;
  102.                         loc.y1 = loc.y0 + bglyph->bitmap.rows;
  103.  
  104.                         /* now, draw to our target surface */
  105.                         if (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
  106.                             nsfb_plot_glyph1(nsfb,
  107.                                              &loc,
  108.                                              bglyph->bitmap.buffer,
  109.                                              bglyph->bitmap.pitch,
  110.                                              fstyle->foreground);
  111.                         } else {
  112.                             nsfb_plot_glyph8(nsfb,
  113.                                              &loc,
  114.                                              bglyph->bitmap.buffer,
  115.                                              bglyph->bitmap.pitch,
  116.                                              fstyle->foreground);
  117.                         }
  118.                 }
  119.                 x += glyph->advance.x >> 16;
  120.  
  121.         }
  122.         return true;
  123.  
  124. }
  125. #else
  126. static bool framebuffer_plot_text(int x, int y, const char *text, size_t length,
  127.                 const plot_font_style_t *fstyle)
  128. {
  129.     const struct fb_font_desc* fb_font = fb_get_font(fstyle);
  130.     const uint32_t *chrp;
  131.     char *buffer = NULL;
  132.     int chr;
  133.     int blen;
  134.     nsfb_bbox_t loc;
  135.  
  136.     utf8_to_font_encoding(fb_font, text, length, &buffer);
  137.     if (buffer == NULL)
  138.         return true;
  139.  
  140.         /* y is given as the baseline, at 3/4 from top.
  141.          * we need it to the top */
  142.         y -= ((fb_font->height * 3) / 4);
  143.  
  144.         /* the coord is the bottom-left of the pixels offset by 1 to make
  145.          *   it work since fb coords are the top-left of pixels
  146.          */
  147.         y += 1;
  148.  
  149.     blen = strlen(buffer);
  150.  
  151.     for (chr = 0; chr < blen; chr++) {
  152.         loc.x0 = x;
  153.         loc.y0 = y;
  154.         loc.x1 = loc.x0 + fb_font->width;
  155.         loc.y1 = loc.y0 + fb_font->height;
  156.  
  157.         chrp = fb_font->data + ((unsigned char)buffer[chr] * fb_font->height);
  158.         nsfb_plot_glyph1(nsfb, &loc, (uint8_t *)chrp, 32, fstyle->foreground);
  159.  
  160.         x += fb_font->width;
  161.  
  162.     }
  163.  
  164.     free(buffer);
  165.     return true;
  166. }
  167. #endif
  168.  
  169.  
  170. static bool
  171. framebuffer_plot_bitmap(int x, int y,
  172.                         int width, int height,
  173.                         struct bitmap *bitmap, colour bg,
  174.                         bitmap_flags_t flags)
  175. {
  176.         int xf,yf;
  177.         nsfb_bbox_t loc;
  178.         nsfb_bbox_t clipbox;
  179.         bool repeat_x = (flags & BITMAPF_REPEAT_X);
  180.         bool repeat_y = (flags & BITMAPF_REPEAT_Y);
  181.         int bmwidth;
  182.         int bmheight;
  183.         unsigned char *bmptr;
  184.         nsfb_t *bm = (nsfb_t *)bitmap;
  185.  
  186.         /* x and y define coordinate of top left of of the initial explicitly
  187.          * placed tile. The width and height are the image scaling and the
  188.          * bounding box defines the extent of the repeat (which may go in all
  189.          * four directions from the initial tile).
  190.          */
  191.  
  192.         if (!(repeat_x || repeat_y)) {
  193.                 /* Not repeating at all, so just plot it */
  194.                 loc.x0 = x;
  195.                 loc.y0 = y;
  196.                 loc.x1 = loc.x0 + width;
  197.                 loc.y1 = loc.y0 + height;
  198.  
  199.                 return nsfb_plot_copy(bm, NULL, nsfb, &loc);           
  200.         }
  201.  
  202.         nsfb_plot_get_clip(nsfb, &clipbox);
  203.         nsfb_get_geometry(bm, &bmwidth, &bmheight, NULL);
  204.         nsfb_get_buffer(bm, &bmptr, NULL);
  205.  
  206.         /* Optimise tiled plots of 1x1 bitmaps by replacing with a flat fill
  207.          * of the area.  Can only be done when image is fully opaque. */
  208.         if ((bmwidth == 1) && (bmheight == 1)) {
  209.                 if ((*(nsfb_colour_t *)bmptr & 0xff000000) != 0) {
  210.                         return nsfb_plot_rectangle_fill(nsfb, &clipbox,
  211.                                         *(nsfb_colour_t *)bmptr);
  212.                 }
  213.         }
  214.  
  215.         /* Optimise tiled plots of bitmaps scaled to 1x1 by replacing with
  216.          * a flat fill of the area.  Can only be done when image is fully
  217.          * opaque. */
  218.         if ((width == 1) && (height == 1)) {
  219.                 if (bitmap_get_opaque(bm)) {
  220.                         /** TODO: Currently using top left pixel. Maybe centre
  221.                          *        pixel or average value would be better. */
  222.                         return nsfb_plot_rectangle_fill(nsfb, &clipbox,
  223.                                         *(nsfb_colour_t *)bmptr);
  224.                 }
  225.         }
  226.  
  227.         /* get left most tile position */
  228.         if (repeat_x)
  229.                 for (; x > clipbox.x0; x -= width);
  230.  
  231.         /* get top most tile position */
  232.         if (repeat_y)
  233.                 for (; y > clipbox.y0; y -= height);
  234.  
  235.         /* tile down and across to extents */
  236.         for (xf = x; xf < clipbox.x1; xf += width) {
  237.                 for (yf = y; yf < clipbox.y1; yf += height) {
  238.  
  239.                         loc.x0 = xf;
  240.                         loc.y0 = yf;
  241.                         loc.x1 = loc.x0 + width;
  242.                         loc.y1 = loc.y0 + height;
  243.  
  244.                         nsfb_plot_copy(bm, NULL, nsfb, &loc);          
  245.  
  246.                         if (!repeat_y)
  247.                                 break;
  248.                 }
  249.                 if (!repeat_x)
  250.                         break;
  251.         }
  252.         return true;
  253. }
  254.  
  255. static bool
  256. framebuffer_plot_rectangle(int x0, int y0, int x1, int y1, const plot_style_t *style)
  257. {
  258.         nsfb_bbox_t rect;
  259.         bool dotted = false;
  260.         bool dashed = false;
  261.  
  262.         rect.x0 = x0;
  263.         rect.y0 = y0;
  264.         rect.x1 = x1;
  265.         rect.y1 = y1;
  266.  
  267.         if (style->fill_type != PLOT_OP_TYPE_NONE) {  
  268.                 nsfb_plot_rectangle_fill(nsfb, &rect, style->fill_colour);
  269.         }
  270.    
  271.         if (style->stroke_type != PLOT_OP_TYPE_NONE) {
  272.                 if (style->stroke_type == PLOT_OP_TYPE_DOT)
  273.                         dotted = true;
  274.  
  275.                 if (style->stroke_type == PLOT_OP_TYPE_DASH)
  276.                         dashed = true;
  277.  
  278.                 nsfb_plot_rectangle(nsfb, &rect, style->stroke_width, style->stroke_colour, dotted, dashed);
  279.         }
  280.  
  281.         return true;
  282. }
  283.  
  284. static bool
  285. framebuffer_plot_line(int x0, int y0, int x1, int y1, const plot_style_t *style)
  286. {
  287.         nsfb_bbox_t rect;
  288.         nsfb_plot_pen_t pen;
  289.  
  290.         rect.x0 = x0;
  291.         rect.y0 = y0;
  292.         rect.x1 = x1;
  293.         rect.y1 = y1;
  294.    
  295.         if (style->stroke_type != PLOT_OP_TYPE_NONE) {
  296.  
  297.                 if (style->stroke_type == PLOT_OP_TYPE_DOT) {
  298.                         pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
  299.                         pen.stroke_pattern = 0xAAAAAAAA;
  300.                 } else if (style->stroke_type == PLOT_OP_TYPE_DASH) {
  301.                         pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
  302.                         pen.stroke_pattern = 0xF0F0F0F0;
  303.                 } else {
  304.                         pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
  305.                 }
  306.  
  307.                 pen.stroke_colour = style->stroke_colour;
  308.                 pen.stroke_width = style->stroke_width;
  309.                 nsfb_plot_line(nsfb, &rect, &pen);
  310.         }
  311.  
  312.         return true;
  313. }
  314.  
  315.  
  316. static bool
  317. framebuffer_plot_path(const float *p,
  318.                       unsigned int n,
  319.                       colour fill,
  320.                       float width,
  321.                       colour c,
  322.                       const float transform[6])
  323. {
  324.         LOG(("path unimplemented"));
  325.         return true;
  326. }
  327.  
  328. static bool
  329. framebuffer_plot_clip(const struct rect *clip)
  330. {
  331.         nsfb_bbox_t nsfb_clip;
  332.         nsfb_clip.x0 = clip->x0;
  333.         nsfb_clip.y0 = clip->y0;
  334.         nsfb_clip.x1 = clip->x1;
  335.         nsfb_clip.y1 = clip->y1;
  336.  
  337.         return nsfb_plot_set_clip(nsfb, &nsfb_clip);
  338. }
  339.  
  340. const struct plotter_table fb_plotters = {
  341.         .clip = framebuffer_plot_clip,
  342.         .arc = framebuffer_plot_arc,
  343.         .disc = framebuffer_plot_disc,
  344.         .line = framebuffer_plot_line,
  345.         .rectangle = framebuffer_plot_rectangle,
  346.         .polygon = framebuffer_plot_polygon,
  347.         .path = framebuffer_plot_path,
  348.         .bitmap = framebuffer_plot_bitmap,
  349.         .text = framebuffer_plot_text,
  350.         .option_knockout = true,
  351. };
  352.  
  353.  
  354.  
  355. nsfb_t *
  356. framebuffer_initialise(const char *fename, int width, int height, int bpp)
  357. {
  358.     enum nsfb_type_e fbtype;
  359.     enum nsfb_format_e fbfmt;
  360.  
  361.     /* bpp is a proxy for the framebuffer format */
  362.     switch (bpp) {
  363.     case 32:
  364.             fbfmt = NSFB_FMT_XRGB8888;
  365.             break;
  366.  
  367.     case 24:
  368.             fbfmt = NSFB_FMT_RGB888;
  369.             break;
  370.  
  371.     case 16:
  372.             fbfmt = NSFB_FMT_RGB565;
  373.             break;
  374.  
  375.     case 8:
  376.             fbfmt = NSFB_FMT_I8;
  377.             break;
  378.  
  379.     case 4:
  380.             fbfmt = NSFB_FMT_I4;
  381.             break;
  382.  
  383.     case 1:
  384.             fbfmt = NSFB_FMT_I1;
  385.             break;
  386.  
  387.     default:
  388.         LOG(("Bad bits per pixel (%d)\n", bpp));
  389.         return NULL;       
  390.     }
  391.  
  392.                
  393.        
  394.  
  395.     fbtype = nsfb_type_from_name(fename);
  396.     if (fbtype == NSFB_SURFACE_NONE) {
  397.         LOG(("The %s surface is not available from libnsfb\n", fename));
  398.         return NULL;
  399.     }
  400.  
  401.     nsfb = nsfb_new(fbtype);
  402.     if (nsfb == NULL) {
  403.         LOG(("Unable to create %s fb surface\n", fename));
  404.         return NULL;
  405.     }
  406.    
  407.     if (nsfb_set_geometry(nsfb, width, height, fbfmt) == -1) {
  408.         LOG(("Unable to set surface geometry\n"));
  409.         nsfb_free(nsfb);
  410.         return NULL;
  411.     }
  412.  
  413.     nsfb_cursor_init(nsfb);
  414.    
  415.     if (nsfb_init(nsfb) == -1) {
  416.         LOG(("Unable to initialise nsfb surface\n"));
  417.         nsfb_free(nsfb);
  418.         return NULL;
  419.     }
  420.  
  421.     return nsfb;
  422.  
  423. }
  424.  
  425. void
  426. framebuffer_finalise(void)
  427. {
  428.     nsfb_free(nsfb);    
  429. }
  430.  
  431. bool
  432. framebuffer_set_cursor(struct fbtk_bitmap *bm)
  433. {
  434.     return nsfb_cursor_set(nsfb, (nsfb_colour_t *)bm->pixdata, bm->width, bm->height, bm->width, bm->hot_x, bm->hot_y);
  435. }
  436.  
  437. nsfb_t *framebuffer_set_surface(nsfb_t *new_nsfb)
  438. {
  439.         nsfb_t *old_nsfb;
  440.         old_nsfb = nsfb;
  441.         nsfb = new_nsfb;
  442.         return old_nsfb;
  443. }
  444.