Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* Cairo - a vector graphics library with display and print output
  2.  *
  3.  * Copyright © 2005 Red Hat, Inc.
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it either under the terms of the GNU Lesser General Public
  7.  * License version 2.1 as published by the Free Software Foundation
  8.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  9.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  10.  * notice, a recipient may use your version of this file under either
  11.  * the MPL or the LGPL.
  12.  *
  13.  * You should have received a copy of the LGPL along with this library
  14.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  15.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  16.  * You should have received a copy of the MPL along with this library
  17.  * in the file COPYING-MPL-1.1
  18.  *
  19.  * The contents of this file are subject to the Mozilla Public License
  20.  * Version 1.1 (the "License"); you may not use this file except in
  21.  * compliance with the License. You may obtain a copy of the License at
  22.  * http://www.mozilla.org/MPL/
  23.  *
  24.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  25.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  26.  * the specific language governing rights and limitations.
  27.  *
  28.  * The Original Code is the cairo graphics library.
  29.  *
  30.  * The Initial Developer of the Original Code is Red Hat, Inc.
  31.  *
  32.  * Partially on code from xftdpy.c
  33.  *
  34.  * Copyright © 2000 Keith Packard
  35.  *
  36.  * Permission to use, copy, modify, distribute, and sell this software and its
  37.  * documentation for any purpose is hereby granted without fee, provided that
  38.  * the above copyright notice appear in all copies and that both that
  39.  * copyright notice and this permission notice appear in supporting
  40.  * documentation, and that the name of Keith Packard not be used in
  41.  * advertising or publicity pertaining to distribution of the software without
  42.  * specific, written prior permission.  Keith Packard makes no
  43.  * representations about the suitability of this software for any purpose.  It
  44.  * is provided "as is" without express or implied warranty.
  45.  *
  46.  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  47.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  48.  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  49.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  50.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  51.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  52.  * PERFORMANCE OF THIS SOFTWARE.
  53.  */
  54.  
  55. #include "cairoint.h"
  56.  
  57. #if !CAIRO_HAS_XLIB_XCB_FUNCTIONS
  58.  
  59. #include "cairo-xlib-private.h"
  60. #include "cairo-xlib-xrender-private.h"
  61.  
  62. #include "cairo-xlib-surface-private.h"
  63. #include "cairo-error-private.h"
  64. #include "cairo-list-inline.h"
  65.  
  66. #include "cairo-fontconfig-private.h"
  67.  
  68. static int
  69. parse_boolean (const char *v)
  70. {
  71.     char c0, c1;
  72.  
  73.     c0 = *v;
  74.     if (c0 == 't' || c0 == 'T' || c0 == 'y' || c0 == 'Y' || c0 == '1')
  75.         return 1;
  76.     if (c0 == 'f' || c0 == 'F' || c0 == 'n' || c0 == 'N' || c0 == '0')
  77.         return 0;
  78.     if (c0 == 'o')
  79.     {
  80.         c1 = v[1];
  81.         if (c1 == 'n' || c1 == 'N')
  82.             return 1;
  83.         if (c1 == 'f' || c1 == 'F')
  84.             return 0;
  85.     }
  86.  
  87.     return -1;
  88. }
  89.  
  90. static cairo_bool_t
  91. get_boolean_default (Display       *dpy,
  92.                      const char    *option,
  93.                      cairo_bool_t  *value)
  94. {
  95.     char *v;
  96.     int i;
  97.  
  98.     v = XGetDefault (dpy, "Xft", option);
  99.     if (v) {
  100.         i = parse_boolean (v);
  101.         if (i >= 0) {
  102.             *value = i;
  103.             return TRUE;
  104.         }
  105.     }
  106.  
  107.     return FALSE;
  108. }
  109.  
  110. static cairo_bool_t
  111. get_integer_default (Display    *dpy,
  112.                      const char *option,
  113.                      int        *value)
  114. {
  115.     char *v, *e;
  116.  
  117.     v = XGetDefault (dpy, "Xft", option);
  118.     if (v) {
  119. #if CAIRO_HAS_FC_FONT
  120.         if (FcNameConstant ((FcChar8 *) v, value))
  121.             return TRUE;
  122. #endif
  123.  
  124.         *value = strtol (v, &e, 0);
  125.         if (e != v)
  126.             return TRUE;
  127.     }
  128.  
  129.     return FALSE;
  130. }
  131.  
  132. static void
  133. _cairo_xlib_init_screen_font_options (Display *dpy,
  134.                                       cairo_xlib_screen_t *info)
  135. {
  136.     cairo_bool_t xft_hinting;
  137.     cairo_bool_t xft_antialias;
  138.     int xft_hintstyle;
  139.     int xft_rgba;
  140.     int xft_lcdfilter;
  141.     cairo_antialias_t antialias;
  142.     cairo_subpixel_order_t subpixel_order;
  143.     cairo_lcd_filter_t lcd_filter;
  144.     cairo_hint_style_t hint_style;
  145.  
  146.     if (!get_boolean_default (dpy, "antialias", &xft_antialias))
  147.         xft_antialias = TRUE;
  148.  
  149.     if (!get_integer_default (dpy, "lcdfilter", &xft_lcdfilter)) {
  150.         /* -1 is an non-existant Fontconfig constant used to differentiate
  151.          * the case when no lcdfilter property is available.
  152.          */
  153.         xft_lcdfilter = -1;
  154.     }
  155.  
  156.     if (!get_boolean_default (dpy, "hinting", &xft_hinting))
  157.         xft_hinting = TRUE;
  158.  
  159.     if (!get_integer_default (dpy, "hintstyle", &xft_hintstyle))
  160.         xft_hintstyle = FC_HINT_FULL;
  161.  
  162.     if (!get_integer_default (dpy, "rgba", &xft_rgba))
  163.     {
  164.         cairo_xlib_display_t *display = (cairo_xlib_display_t *) info->device;
  165.  
  166.         xft_rgba = FC_RGBA_UNKNOWN;
  167.  
  168. #if RENDER_MAJOR > 0 || RENDER_MINOR >= 6
  169.         if (display->render_major > 0 || display->render_minor >= 6) {
  170.             int render_order = XRenderQuerySubpixelOrder (dpy,
  171.                                                           XScreenNumberOfScreen (info->screen));
  172.  
  173.             switch (render_order) {
  174.             default:
  175.             case SubPixelUnknown:
  176.                 xft_rgba = FC_RGBA_UNKNOWN;
  177.                 break;
  178.             case SubPixelHorizontalRGB:
  179.                 xft_rgba = FC_RGBA_RGB;
  180.                 break;
  181.             case SubPixelHorizontalBGR:
  182.                 xft_rgba = FC_RGBA_BGR;
  183.                 break;
  184.             case SubPixelVerticalRGB:
  185.                 xft_rgba = FC_RGBA_VRGB;
  186.                 break;
  187.             case SubPixelVerticalBGR:
  188.                 xft_rgba = FC_RGBA_VBGR;
  189.                 break;
  190.             case SubPixelNone:
  191.                 xft_rgba = FC_RGBA_NONE;
  192.                 break;
  193.             }
  194.         }
  195. #endif
  196.     }
  197.  
  198.     if (xft_hinting) {
  199.         switch (xft_hintstyle) {
  200.         case FC_HINT_NONE:
  201.             hint_style = CAIRO_HINT_STYLE_NONE;
  202.             break;
  203.         case FC_HINT_SLIGHT:
  204.             hint_style = CAIRO_HINT_STYLE_SLIGHT;
  205.             break;
  206.         case FC_HINT_MEDIUM:
  207.             hint_style = CAIRO_HINT_STYLE_MEDIUM;
  208.             break;
  209.         case FC_HINT_FULL:
  210.             hint_style = CAIRO_HINT_STYLE_FULL;
  211.             break;
  212.         default:
  213.             hint_style = CAIRO_HINT_STYLE_DEFAULT;
  214.         }
  215.     } else {
  216.         hint_style = CAIRO_HINT_STYLE_NONE;
  217.     }
  218.  
  219.     switch (xft_rgba) {
  220.     case FC_RGBA_RGB:
  221.         subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
  222.         break;
  223.     case FC_RGBA_BGR:
  224.         subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
  225.         break;
  226.     case FC_RGBA_VRGB:
  227.         subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
  228.         break;
  229.     case FC_RGBA_VBGR:
  230.         subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
  231.         break;
  232.     case FC_RGBA_UNKNOWN:
  233.     case FC_RGBA_NONE:
  234.     default:
  235.         subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
  236.     }
  237.  
  238.     switch (xft_lcdfilter) {
  239.     case FC_LCD_NONE:
  240.         lcd_filter = CAIRO_LCD_FILTER_NONE;
  241.         break;
  242.     case FC_LCD_DEFAULT:
  243.         lcd_filter = CAIRO_LCD_FILTER_FIR5;
  244.         break;
  245.     case FC_LCD_LIGHT:
  246.         lcd_filter = CAIRO_LCD_FILTER_FIR3;
  247.         break;
  248.     case FC_LCD_LEGACY:
  249.         lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
  250.         break;
  251.     default:
  252.         lcd_filter = CAIRO_LCD_FILTER_DEFAULT;
  253.         break;
  254.     }
  255.  
  256.     if (xft_antialias) {
  257.         if (subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT)
  258.             antialias = CAIRO_ANTIALIAS_GRAY;
  259.         else
  260.             antialias = CAIRO_ANTIALIAS_SUBPIXEL;
  261.     } else {
  262.         antialias = CAIRO_ANTIALIAS_NONE;
  263.     }
  264.  
  265.     cairo_font_options_set_hint_style (&info->font_options, hint_style);
  266.     cairo_font_options_set_antialias (&info->font_options, antialias);
  267.     cairo_font_options_set_subpixel_order (&info->font_options, subpixel_order);
  268.     _cairo_font_options_set_lcd_filter (&info->font_options, lcd_filter);
  269.     cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON);
  270. }
  271.  
  272. void
  273. _cairo_xlib_screen_destroy (cairo_xlib_display_t *display,
  274.                             cairo_xlib_screen_t *info)
  275. {
  276.     Display *dpy;
  277.     int i;
  278.  
  279.     dpy = display->display;
  280.  
  281.     while (! cairo_list_is_empty (&info->surfaces)) {
  282.         cairo_xlib_surface_t *surface;
  283.  
  284.         surface = cairo_list_first_entry (&info->surfaces,
  285.                                           cairo_xlib_surface_t,
  286.                                           link);
  287.         cairo_surface_finish (&surface->base);
  288.     }
  289.  
  290.     for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
  291.         if (info->gc_depths[i] != 0) {
  292.             XFreeGC (dpy, info->gc[i]);
  293.             info->gc_depths[i] = 0;
  294.         }
  295.     }
  296.  
  297.     while (! cairo_list_is_empty (&info->visuals)) {
  298.         _cairo_xlib_visual_info_destroy (cairo_list_first_entry (&info->visuals,
  299.                                                                  cairo_xlib_visual_info_t,
  300.                                                                  link));
  301.     }
  302.  
  303.     cairo_list_del (&info->link);
  304.  
  305.     free (info);
  306. }
  307.  
  308. cairo_status_t
  309. _cairo_xlib_screen_get (Display *dpy,
  310.                         Screen *screen,
  311.                         cairo_xlib_screen_t **out)
  312. {
  313.     cairo_xlib_display_t *display;
  314.     cairo_device_t *device;
  315.     cairo_xlib_screen_t *info;
  316.     cairo_status_t status;
  317.  
  318.     device = _cairo_xlib_device_create (dpy);
  319.     status = device->status;
  320.     if (unlikely (status))
  321.         goto CLEANUP_DEVICE;
  322.  
  323.     status =  _cairo_xlib_display_acquire (device, &display);
  324.     if (unlikely (status))
  325.         goto CLEANUP_DEVICE;
  326.  
  327.     info = _cairo_xlib_display_get_screen (display, screen);
  328.     if (info != NULL) {
  329.         *out = info;
  330.         goto CLEANUP_DISPLAY;
  331.     }
  332.  
  333.     info = malloc (sizeof (cairo_xlib_screen_t));
  334.     if (unlikely (info == NULL)) {
  335.         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  336.         goto CLEANUP_DISPLAY;
  337.     }
  338.  
  339.     info->device = device;
  340.     info->screen = screen;
  341.     info->has_font_options = FALSE;
  342.     memset (info->gc_depths, 0, sizeof (info->gc_depths));
  343.     memset (info->gc, 0, sizeof (info->gc));
  344.  
  345.     cairo_list_init (&info->surfaces);
  346.     cairo_list_init (&info->visuals);
  347.     cairo_list_add (&info->link, &display->screens);
  348.  
  349.     *out = info;
  350.  
  351.   CLEANUP_DISPLAY:
  352.     cairo_device_release (&display->base);
  353.  
  354.   CLEANUP_DEVICE:
  355.     cairo_device_destroy (device);
  356.     return status;
  357. }
  358.  
  359. GC
  360. _cairo_xlib_screen_get_gc (cairo_xlib_display_t *display,
  361.                            cairo_xlib_screen_t *info,
  362.                            int depth,
  363.                            Drawable drawable)
  364. {
  365.     GC gc = NULL;
  366.     int i;
  367.  
  368.     for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
  369.         if (info->gc_depths[i] == depth) {
  370.             info->gc_depths[i] = 0;
  371.             gc = info->gc[i];
  372.             break;
  373.         }
  374.     }
  375.  
  376.     if (gc == NULL) {
  377.         XGCValues gcv;
  378.  
  379.         gcv.graphics_exposures = False;
  380.         gcv.fill_style = FillTiled;
  381.         gc = XCreateGC (display->display,
  382.                         drawable,
  383.                         GCGraphicsExposures | GCFillStyle, &gcv);
  384.     }
  385.  
  386.     return gc;
  387. }
  388.  
  389. void
  390. _cairo_xlib_screen_put_gc (cairo_xlib_display_t *display,
  391.                            cairo_xlib_screen_t *info,
  392.                            int depth,
  393.                            GC gc)
  394. {
  395.     int i;
  396.  
  397.     for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
  398.         if (info->gc_depths[i] == 0)
  399.             break;
  400.     }
  401.  
  402.     if (i == ARRAY_LENGTH (info->gc)) {
  403.         /* perform random substitution to ensure fair caching over depths */
  404.         i = rand () % ARRAY_LENGTH (info->gc);
  405.         XFreeGC(display->display, info->gc[i]);
  406.     }
  407.  
  408.     info->gc[i] = gc;
  409.     info->gc_depths[i] = depth;
  410. }
  411.  
  412. cairo_status_t
  413. _cairo_xlib_screen_get_visual_info (cairo_xlib_display_t *display,
  414.                                     cairo_xlib_screen_t *info,
  415.                                     Visual *v,
  416.                                     cairo_xlib_visual_info_t **out)
  417. {
  418.     cairo_xlib_visual_info_t *visual;
  419.     cairo_status_t status;
  420.  
  421.     cairo_list_foreach_entry (visual,
  422.                               cairo_xlib_visual_info_t,
  423.                               &info->visuals,
  424.                               link)
  425.     {
  426.         if (visual->visualid == v->visualid) {
  427.             *out = visual;
  428.             return CAIRO_STATUS_SUCCESS;
  429.         }
  430.     }
  431.  
  432.     status = _cairo_xlib_visual_info_create (display->display,
  433.                                              XScreenNumberOfScreen (info->screen),
  434.                                              v->visualid,
  435.                                              &visual);
  436.     if (unlikely (status))
  437.         return status;
  438.  
  439.     cairo_list_add (&visual->link, &info->visuals);
  440.     *out = visual;
  441.     return CAIRO_STATUS_SUCCESS;
  442. }
  443.  
  444. cairo_font_options_t *
  445. _cairo_xlib_screen_get_font_options (cairo_xlib_screen_t *info)
  446. {
  447.     if (! info->has_font_options) {
  448.         _cairo_font_options_init_default (&info->font_options);
  449.         _cairo_font_options_set_round_glyph_positions (&info->font_options, CAIRO_ROUND_GLYPH_POS_ON);
  450.  
  451.         if (info->screen != NULL) {
  452.             cairo_xlib_display_t *display;
  453.  
  454.             if (! _cairo_xlib_display_acquire (info->device, &display)) {
  455.                 _cairo_xlib_init_screen_font_options (display->display,
  456.                                                       info);
  457.                 cairo_device_release (&display->base);
  458.             }
  459.         }
  460.  
  461.         info->has_font_options = TRUE;
  462.     }
  463.  
  464.     return &info->font_options;
  465. }
  466.  
  467. #endif /* !CAIRO_HAS_XLIB_XCB_FUNCTIONS */
  468.