~ubuntu-branches/ubuntu/jaunty/libgdiplus/jaunty-updates

« back to all changes in this revision

Viewing changes to cairo/src/cairo-xlib-surface.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2007-05-17 13:38:42 UTC
  • mfrom: (1.1.13 upstream)
  • Revision ID: james.westby@ubuntu.com-20070517133842-t8b8d4lxmhb3vnp0
Tags: 1.2.4-1ubuntu1
* Sync with Debian:
  + debian/control:
    - Add sparc to archs
    - Set Maintainer field...

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
 *
34
34
 * Contributor(s):
35
35
 *      Carl D. Worth <cworth@cworth.org>
 
36
 *      Behdad Esfahbod <behdad@behdad.org>
36
37
 */
37
38
 
38
39
#include "cairoint.h"
69
70
_cairo_xlib_surface_show_glyphs (void                *abstract_dst,
70
71
                                 cairo_operator_t     op,
71
72
                                 cairo_pattern_t     *src_pattern,
72
 
                                 const cairo_glyph_t *glyphs,
 
73
                                 cairo_glyph_t       *glyphs,
73
74
                                 int                  num_glyphs,
74
75
                                 cairo_scaled_font_t *scaled_font);
75
76
 
177
178
        return 1;
178
179
    case CAIRO_FORMAT_A8:
179
180
        return 8;
180
 
    case CAIRO_FORMAT_RGB16_565:
181
 
        return 16;
182
181
    case CAIRO_FORMAT_RGB24:
183
182
        return 24;
184
183
    case CAIRO_FORMAT_ARGB32:
611
610
    _swap_ximage_to_native (ximage);
612
611
 
613
612
    /*
614
 
     * Compute the pixel format masks from either a visual or a
615
 
     * XRenderFormat, failing we assume the drawable is an
616
 
     * alpha-only pixmap as it could only have been created
617
 
     * that way through the cairo_xlib_surface_create_for_bitmap
618
 
     * function.
 
613
     * Compute the pixel format masks from either a XrenderFormat or
 
614
     * else from a visual; failing that we assume the drawable is an
 
615
     * alpha-only pixmap as it could only have been created that way
 
616
     * through the cairo_xlib_surface_create_for_bitmap function.
619
617
     */
620
 
    if (surface->visual) {
 
618
    if (surface->xrender_format) {
 
619
        masks.bpp = ximage->bits_per_pixel;
 
620
        masks.red_mask =   (unsigned long) surface->xrender_format->direct.redMask
 
621
            << surface->xrender_format->direct.red;
 
622
        masks.green_mask = (unsigned long) surface->xrender_format->direct.greenMask
 
623
            << surface->xrender_format->direct.green;
 
624
        masks.blue_mask =  (unsigned long) surface->xrender_format->direct.blueMask
 
625
            << surface->xrender_format->direct.blue;
 
626
        masks.alpha_mask = (unsigned long) surface->xrender_format->direct.alphaMask
 
627
            << surface->xrender_format->direct.alpha;
 
628
    } else if (surface->visual) {
621
629
        masks.bpp = ximage->bits_per_pixel;
622
630
        masks.alpha_mask = 0;
623
631
        masks.red_mask = surface->visual->red_mask;
624
632
        masks.green_mask = surface->visual->green_mask;
625
633
        masks.blue_mask = surface->visual->blue_mask;
626
 
    } else if (surface->xrender_format) {
627
 
        masks.bpp = ximage->bits_per_pixel;
628
 
        masks.red_mask = (unsigned long)surface->xrender_format->direct.redMask << surface->xrender_format->direct.red;
629
 
        masks.green_mask = (unsigned long)surface->xrender_format->direct.greenMask << surface->xrender_format->direct.green;
630
 
        masks.blue_mask = (unsigned long)surface->xrender_format->direct.blueMask << surface->xrender_format->direct.blue;
631
 
        masks.alpha_mask = (unsigned long)surface->xrender_format->direct.alphaMask << surface->xrender_format->direct.alpha;
632
634
    } else {
633
635
        masks.bpp = ximage->bits_per_pixel;
634
636
        masks.red_mask = 0;
746
748
static cairo_status_t
747
749
_draw_image_surface (cairo_xlib_surface_t   *surface,
748
750
                     cairo_image_surface_t  *image,
 
751
                     int                    src_x,
 
752
                     int                    src_y,
 
753
                     int                    width,
 
754
                     int                    height,
749
755
                     int                    dst_x,
750
756
                     int                    dst_y)
751
757
{
776
782
 
777
783
    _cairo_xlib_surface_ensure_gc (surface);
778
784
    XPutImage(surface->dpy, surface->drawable, surface->gc,
779
 
              &ximage, 0, 0, dst_x, dst_y,
780
 
              image->width, image->height);
 
785
              &ximage, src_x, src_y, dst_x, dst_y,
 
786
              width, height);
781
787
 
782
788
    return CAIRO_STATUS_SUCCESS;
783
789
 
841
847
    cairo_xlib_surface_t *surface = abstract_surface;
842
848
 
843
849
    /* ignore errors */
844
 
    _draw_image_surface (surface, image, image_rect->x, image_rect->y);
 
850
    _draw_image_surface (surface, image, 0, 0, image->width, image->height,
 
851
                         image_rect->x, image_rect->y);
845
852
 
846
853
    cairo_surface_destroy (&image->base);
847
854
}
861
868
static cairo_status_t
862
869
_cairo_xlib_surface_clone_similar (void                 *abstract_surface,
863
870
                                   cairo_surface_t      *src,
 
871
                                   int                   src_x,
 
872
                                   int                   src_y,
 
873
                                   int                   width,
 
874
                                   int                   height,
864
875
                                   cairo_surface_t     **clone_out)
865
876
{
866
877
    cairo_xlib_surface_t *surface = abstract_surface;
886
897
        if (clone->base.status)
887
898
            return CAIRO_STATUS_NO_MEMORY;
888
899
 
889
 
        _draw_image_surface (clone, image_src, 0, 0);
 
900
        _draw_image_surface (clone, image_src, src_x, src_y,
 
901
                             width, height, src_x, src_y);
890
902
 
891
903
        *clone_out = &clone->base;
892
904
 
1097
1109
/* There is a bug in most older X servers with compositing using a
1098
1110
 * untransformed repeating source pattern when the source is in off-screen
1099
1111
 * video memory, and another with repeated transformed images using a
1100
 
 * general tranform matrix. When these bugs could be triggered, we need a
 
1112
 * general transform matrix. When these bugs could be triggered, we need a
1101
1113
 * fallback: in the common case where we have no transformation and the
1102
1114
 * source and destination have the same format/visual, we can do the
1103
1115
 * operation using the core protocol for the first bug, otherwise, we need
1157
1169
 
1158
1170
                /* If these are on the same screen but otherwise incompatible,
1159
1171
                 * make a copy as core drawing can't cross depths and doesn't
1160
 
                 * work rightacross visuals of the same depth
 
1172
                 * work right across visuals of the same depth
1161
1173
                 */
1162
1174
                if (_cairo_xlib_surface_same_screen (dst, src) &&
1163
1175
                    !_surfaces_compatible (dst, src))
2259
2271
    XRenderPictFormat   *xrender_format;
2260
2272
} cairo_xlib_surface_font_private_t;
2261
2273
 
 
2274
static void
 
2275
_cairo_xlib_surface_remove_scaled_font (Display *dpy,
 
2276
                                       void    *data)
 
2277
{
 
2278
    cairo_scaled_font_t *scaled_font = data;
 
2279
    cairo_xlib_surface_font_private_t   *font_private = scaled_font->surface_private;
 
2280
 
 
2281
    _cairo_scaled_font_reset_cache (scaled_font);
 
2282
 
 
2283
    /* separate function to avoid deadlock if we tried to remove the
 
2284
     * close display hook ala _cairo_xlib_surface_scaled_font_fini() */
 
2285
    if (font_private) {
 
2286
        XRenderFreeGlyphSet (font_private->dpy, font_private->glyphset);
 
2287
        free (font_private);
 
2288
        scaled_font->surface_private = NULL;
 
2289
    }
 
2290
}
 
2291
 
2262
2292
static cairo_status_t
2263
2293
_cairo_xlib_surface_font_init (Display              *dpy,
2264
2294
                               cairo_scaled_font_t  *scaled_font,
2266
2296
{
2267
2297
    cairo_xlib_surface_font_private_t   *font_private;
2268
2298
 
 
2299
    if (!_cairo_xlib_add_close_display_hook (dpy,
 
2300
                _cairo_xlib_surface_remove_scaled_font,
 
2301
                scaled_font, scaled_font))
 
2302
        return CAIRO_STATUS_NO_MEMORY;
 
2303
 
2269
2304
    font_private = malloc (sizeof (cairo_xlib_surface_font_private_t));
2270
2305
    if (!font_private)
2271
2306
        return CAIRO_STATUS_NO_MEMORY;
2276
2311
    font_private->glyphset = XRenderCreateGlyphSet (dpy, font_private->xrender_format);
2277
2312
    scaled_font->surface_private = font_private;
2278
2313
    scaled_font->surface_backend = &cairo_xlib_surface_backend;
 
2314
 
2279
2315
    return CAIRO_STATUS_SUCCESS;
2280
2316
}
2281
2317
 
2285
2321
    cairo_xlib_surface_font_private_t   *font_private = scaled_font->surface_private;
2286
2322
 
2287
2323
    if (font_private) {
 
2324
        _cairo_xlib_remove_close_display_hook (font_private->dpy, scaled_font);
2288
2325
        XRenderFreeGlyphSet (font_private->dpy, font_private->glyphset);
2289
2326
        free (font_private);
2290
2327
    }
2381
2418
     *
2382
2419
     *  This is a postscript-y model, where each glyph has its own
2383
2420
     *  coordinate space, so it's what we expose in terms of metrics. It's
2384
 
     *  apparantly what everyone's expecting. Everyone except the Render
 
2421
     *  apparently what everyone's expecting. Everyone except the Render
2385
2422
     *  extension. Render wants to see a glyph tile starting at (0,0), with
2386
2423
     *  an origin offset inside, like this:
2387
2424
     *
2400
2437
     */
2401
2438
 
2402
2439
    /* XXX: FRAGILE: We're ignore device_transform scaling here. A bug? */
2403
 
    glyph_info.x = - (int) floor(glyph_surface->base.device_transform.x0 + 0.5);
2404
 
    glyph_info.y = - (int) floor(glyph_surface->base.device_transform.y0 + 0.5);
 
2440
    glyph_info.x = - _cairo_lround (glyph_surface->base.device_transform.x0);
 
2441
    glyph_info.y = - _cairo_lround (glyph_surface->base.device_transform.y0);
2405
2442
    glyph_info.width = glyph_surface->width;
2406
2443
    glyph_info.height = glyph_surface->height;
2407
 
    glyph_info.xOff = 0;
2408
 
    glyph_info.yOff = 0;
 
2444
    glyph_info.xOff = scaled_glyph->x_advance;
 
2445
    glyph_info.yOff = scaled_glyph->y_advance;
2409
2446
 
2410
2447
    data = glyph_surface->data;
2411
2448
 
2488
2525
    return status;
2489
2526
}
2490
2527
 
2491
 
#define N_STACK_BUF 1024
2492
 
 
2493
 
static cairo_status_t
2494
 
_cairo_xlib_surface_show_glyphs8  (cairo_xlib_surface_t *dst,
2495
 
                                   cairo_operator_t op,
2496
 
                                   cairo_xlib_surface_t *src,
2497
 
                                   int src_x_offset, int src_y_offset,
2498
 
                                   const cairo_glyph_t *glyphs,
2499
 
                                   int num_glyphs,
2500
 
                                   cairo_scaled_font_t *scaled_font)
2501
 
{
2502
 
    cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
2503
 
    XGlyphElt8 *elts = NULL;
2504
 
    XGlyphElt8 stack_elts [N_STACK_BUF];
2505
 
 
2506
 
    char *chars = NULL;
2507
 
    char stack_chars [N_STACK_BUF];
2508
 
 
2509
 
    int i;
2510
 
    int thisX, thisY;
2511
 
    int lastX = 0, lastY = 0;
2512
 
 
2513
 
    /* Acquire arrays of suitable sizes. */
2514
 
    if (num_glyphs < N_STACK_BUF) {
2515
 
        elts = stack_elts;
2516
 
        chars = stack_chars;
2517
 
    } else {
2518
 
        elts = malloc (num_glyphs * sizeof (XGlyphElt8) +
2519
 
                       num_glyphs * sizeof (unsigned char));
2520
 
        if (elts == NULL)
2521
 
            return CAIRO_STATUS_NO_MEMORY;
2522
 
 
2523
 
        chars = (char *) (elts + num_glyphs);
2524
 
    }
2525
 
 
2526
 
    for (i = 0; i < num_glyphs; ++i) {
2527
 
        chars[i] = glyphs[i].index;
2528
 
        elts[i].chars = &(chars[i]);
2529
 
        elts[i].nchars = 1;
2530
 
        elts[i].glyphset = font_private->glyphset;
2531
 
        thisX = (int) floor (glyphs[i].x + 0.5);
2532
 
        thisY = (int) floor (glyphs[i].y + 0.5);
2533
 
        elts[i].xOff = thisX - lastX;
2534
 
        elts[i].yOff = thisY - lastY;
2535
 
        lastX = thisX;
2536
 
        lastY = thisY;
2537
 
    }
2538
 
 
2539
 
    XRenderCompositeText8  (dst->dpy,
2540
 
                            _render_operator (op),
2541
 
                            src->src_picture,
2542
 
                            dst->dst_picture,
2543
 
                            font_private->xrender_format,
2544
 
                            src_x_offset + elts[0].xOff, src_y_offset + elts[0].yOff,
2545
 
                            elts[0].xOff, elts[0].yOff,
2546
 
                            elts, num_glyphs);
2547
 
 
2548
 
    if (elts != stack_elts)
2549
 
        free (elts);
2550
 
 
2551
 
    return CAIRO_STATUS_SUCCESS;
2552
 
}
2553
 
 
2554
 
static cairo_status_t
2555
 
_cairo_xlib_surface_show_glyphs16 (cairo_xlib_surface_t *dst,
2556
 
                                   cairo_operator_t op,
2557
 
                                   cairo_xlib_surface_t *src,
2558
 
                                   int src_x_offset, int src_y_offset,
2559
 
                                   const cairo_glyph_t *glyphs,
2560
 
                                   int num_glyphs,
2561
 
                                   cairo_scaled_font_t *scaled_font)
2562
 
{
2563
 
    cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
2564
 
    XGlyphElt16 *elts = NULL;
2565
 
    XGlyphElt16 stack_elts [N_STACK_BUF];
2566
 
 
2567
 
    unsigned short *chars = NULL;
2568
 
    unsigned short stack_chars [N_STACK_BUF];
2569
 
 
2570
 
    int i;
2571
 
    int thisX, thisY;
2572
 
    int lastX = 0, lastY = 0;
2573
 
 
2574
 
    /* Acquire arrays of suitable sizes. */
2575
 
    if (num_glyphs < N_STACK_BUF) {
2576
 
        elts = stack_elts;
2577
 
        chars = stack_chars;
2578
 
    } else {
2579
 
        elts = malloc (num_glyphs * sizeof (XGlyphElt16) +
2580
 
                       num_glyphs * sizeof (unsigned short));
2581
 
        if (elts == NULL)
2582
 
            return CAIRO_STATUS_NO_MEMORY;
2583
 
 
2584
 
        chars = (unsigned short *) (elts + num_glyphs);
2585
 
    }
2586
 
 
2587
 
    for (i = 0; i < num_glyphs; ++i) {
2588
 
        chars[i] = glyphs[i].index;
2589
 
        elts[i].chars = &(chars[i]);
2590
 
        elts[i].nchars = 1;
2591
 
        elts[i].glyphset = font_private->glyphset;
2592
 
        thisX = (int) floor (glyphs[i].x + 0.5);
2593
 
        thisY = (int) floor (glyphs[i].y + 0.5);
2594
 
        elts[i].xOff = thisX - lastX;
2595
 
        elts[i].yOff = thisY - lastY;
2596
 
        lastX = thisX;
2597
 
        lastY = thisY;
2598
 
    }
2599
 
 
2600
 
    XRenderCompositeText16 (dst->dpy,
2601
 
                            _render_operator (op),
2602
 
                            src->src_picture,
2603
 
                            dst->dst_picture,
2604
 
                            font_private->xrender_format,
2605
 
                            src_x_offset + elts[0].xOff, src_y_offset + elts[0].yOff,
2606
 
                            elts[0].xOff, elts[0].yOff,
2607
 
                            elts, num_glyphs);
2608
 
 
2609
 
    if (elts != stack_elts)
2610
 
        free (elts);
2611
 
 
2612
 
    return CAIRO_STATUS_SUCCESS;
2613
 
}
2614
 
 
2615
 
static cairo_status_t
2616
 
_cairo_xlib_surface_show_glyphs32 (cairo_xlib_surface_t *dst,
2617
 
                                   cairo_operator_t op,
2618
 
                                   cairo_xlib_surface_t *src,
2619
 
                                   int src_x_offset, int src_y_offset,
2620
 
                                   const cairo_glyph_t *glyphs,
2621
 
                                   int num_glyphs,
2622
 
                                   cairo_scaled_font_t *scaled_font)
2623
 
{
2624
 
    cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
2625
 
    XGlyphElt32 *elts = NULL;
2626
 
    XGlyphElt32 stack_elts [N_STACK_BUF];
2627
 
 
2628
 
    unsigned int *chars = NULL;
2629
 
    unsigned int stack_chars [N_STACK_BUF];
2630
 
 
2631
 
    int i;
2632
 
    int thisX, thisY;
2633
 
    int lastX = 0, lastY = 0;
2634
 
 
2635
 
    /* Acquire arrays of suitable sizes. */
2636
 
    if (num_glyphs < N_STACK_BUF) {
2637
 
        elts = stack_elts;
2638
 
        chars = stack_chars;
2639
 
    } else {
2640
 
        elts = malloc (num_glyphs * sizeof (XGlyphElt32) +
2641
 
                       num_glyphs * sizeof (unsigned int));
2642
 
        if (elts == NULL)
2643
 
            return CAIRO_STATUS_NO_MEMORY;
2644
 
 
2645
 
        chars = (unsigned int *) (elts + num_glyphs);
2646
 
    }
2647
 
 
2648
 
    for (i = 0; i < num_glyphs; ++i) {
2649
 
        chars[i] = glyphs[i].index;
2650
 
        elts[i].chars = &(chars[i]);
2651
 
        elts[i].nchars = 1;
2652
 
        elts[i].glyphset = font_private->glyphset;
2653
 
        thisX = (int) floor (glyphs[i].x + 0.5);
2654
 
        thisY = (int) floor (glyphs[i].y + 0.5);
2655
 
        elts[i].xOff = thisX - lastX;
2656
 
        elts[i].yOff = thisY - lastY;
2657
 
        lastX = thisX;
2658
 
        lastY = thisY;
2659
 
    }
2660
 
 
2661
 
    XRenderCompositeText32 (dst->dpy,
2662
 
                            _render_operator (op),
2663
 
                            src->src_picture,
2664
 
                            dst->dst_picture,
2665
 
                            font_private->xrender_format,
2666
 
                            src_x_offset + elts[0].xOff, src_y_offset + elts[0].yOff,
2667
 
                            elts[0].xOff, elts[0].yOff,
2668
 
                            elts, num_glyphs);
2669
 
 
2670
 
    if (elts != stack_elts)
2671
 
        free (elts);
2672
 
 
2673
 
    return CAIRO_STATUS_SUCCESS;
2674
 
}
2675
 
 
2676
 
typedef cairo_status_t (*cairo_xlib_surface_show_glyphs_func_t)
2677
 
    (cairo_xlib_surface_t *, cairo_operator_t, cairo_xlib_surface_t *, int, int,
2678
 
     const cairo_glyph_t *, int, cairo_scaled_font_t *);
 
2528
typedef void (*cairo_xrender_composite_text_func_t)
 
2529
              (Display                      *dpy,
 
2530
               int                          op,
 
2531
               Picture                      src,
 
2532
               Picture                      dst,
 
2533
               _Xconst XRenderPictFormat    *maskFormat,
 
2534
               int                          xSrc,
 
2535
               int                          ySrc,
 
2536
               int                          xDst,
 
2537
               int                          yDst,
 
2538
               _Xconst XGlyphElt8           *elts,
 
2539
               int                          nelt);
 
2540
 
 
2541
/* Build a struct of the same size of cairo_glyph_t that can be used both as
 
2542
 * an input glyph with double coordinates, and as "working" glyph with
 
2543
 * integer from-current-point offsets. */
 
2544
typedef struct {
 
2545
  unsigned long index;
 
2546
  union {
 
2547
    struct {
 
2548
      double x;
 
2549
      double y;
 
2550
    } d;
 
2551
    struct {
 
2552
      int x;
 
2553
      int y;
 
2554
    } i;
 
2555
  } p;
 
2556
} cairo_xlib_glyph_t;
 
2557
 
 
2558
#define GLYPH_INDEX_SKIP ((unsigned long) -1)
 
2559
#define STACK_ELTS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (XGlyphElt8)))
 
2560
 
 
2561
static cairo_status_t
 
2562
_cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
 
2563
                                       cairo_xlib_glyph_t *glyphs,
 
2564
                                       int num_glyphs,
 
2565
                                       int width,
 
2566
                                       int num_elts,
 
2567
                                       cairo_scaled_font_t *scaled_font,
 
2568
                                       cairo_operator_t op,
 
2569
                                       cairo_xlib_surface_t *src,
 
2570
                                       cairo_surface_attributes_t *attributes)
 
2571
{
 
2572
    /* Which XRenderCompositeText function to use */
 
2573
    cairo_xrender_composite_text_func_t composite_text_func;
 
2574
    int size;
 
2575
 
 
2576
    /* Element buffer stuff */
 
2577
    XGlyphElt8 *elts;
 
2578
    XGlyphElt8 stack_elts[STACK_ELTS_LEN];
 
2579
 
 
2580
    /* Reuse the input glyph array for output char generation */
 
2581
    char *char8 = (char *) glyphs;
 
2582
    unsigned short *char16 = (unsigned short *) glyphs;
 
2583
    unsigned int *char32 = (unsigned int *) glyphs;
 
2584
 
 
2585
    int i;
 
2586
    int nelt; /* Element index */
 
2587
    int n; /* Num output glyphs in current element */
 
2588
    int j; /* Num output glyphs so far */
 
2589
 
 
2590
    cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
 
2591
 
 
2592
    switch (width) {
 
2593
    case 1:
 
2594
        /* don't cast the 8-variant, to catch possible mismatches */
 
2595
        composite_text_func = XRenderCompositeText8;
 
2596
        size = sizeof (char);
 
2597
        break;
 
2598
    case 2:
 
2599
        composite_text_func = (cairo_xrender_composite_text_func_t) XRenderCompositeText16;
 
2600
        size = sizeof (unsigned short);
 
2601
        break;
 
2602
    default:
 
2603
    case 4:
 
2604
        composite_text_func = (cairo_xrender_composite_text_func_t) XRenderCompositeText32;
 
2605
        size = sizeof (unsigned int);
 
2606
    }
 
2607
 
 
2608
    /* Allocate element array */
 
2609
    if (num_elts <= STACK_ELTS_LEN) {
 
2610
      elts = stack_elts;
 
2611
    } else {
 
2612
      elts = malloc (num_elts * sizeof (XGlyphElt8));
 
2613
      if (elts == NULL)
 
2614
          return CAIRO_STATUS_NO_MEMORY;
 
2615
    }
 
2616
 
 
2617
    /* Fill them in */
 
2618
    nelt = 0;
 
2619
    n = 0;
 
2620
    j = 0;
 
2621
    for (i = 0; i < num_glyphs; i++) {
 
2622
 
 
2623
      /* Skip glyphs marked so */
 
2624
      if (glyphs[i].index == GLYPH_INDEX_SKIP)
 
2625
        continue;
 
2626
 
 
2627
      /* Start a new element for first output glyph, and for glyphs with
 
2628
       * unexpected position */
 
2629
      if (!j || glyphs[i].p.i.x || glyphs[i].p.i.y) {
 
2630
          if (j) {
 
2631
            elts[nelt].nchars = n;
 
2632
            nelt++;
 
2633
            n = 0;
 
2634
          }
 
2635
          elts[nelt].chars = char8 + size * j;
 
2636
          elts[nelt].glyphset = font_private->glyphset;
 
2637
          elts[nelt].xOff = glyphs[i].p.i.x;
 
2638
          elts[nelt].yOff = glyphs[i].p.i.y;
 
2639
      }
 
2640
 
 
2641
      switch (width) {
 
2642
      case 1: char8 [j] = (char)           glyphs[i].index; break;
 
2643
      case 2: char16[j] = (unsigned short) glyphs[i].index; break;
 
2644
      default:
 
2645
      case 4: char32[j] = (unsigned int)   glyphs[i].index; break;
 
2646
      }
 
2647
 
 
2648
      n++;
 
2649
      j++;
 
2650
    }
 
2651
 
 
2652
    if (n) {
 
2653
        elts[nelt].nchars = n;
 
2654
        nelt++;
 
2655
        n = 0;
 
2656
    }
 
2657
 
 
2658
    composite_text_func (dst->dpy,
 
2659
                         _render_operator (op),
 
2660
                         src->src_picture,
 
2661
                         dst->dst_picture,
 
2662
                         font_private->xrender_format,
 
2663
                         attributes->x_offset + elts[0].xOff,
 
2664
                         attributes->y_offset + elts[0].yOff,
 
2665
                         elts[0].xOff, elts[0].yOff,
 
2666
                         (XGlyphElt8 *) elts, nelt);
 
2667
 
 
2668
    if (elts != stack_elts)
 
2669
      free (elts);
 
2670
 
 
2671
    return CAIRO_STATUS_SUCCESS;
 
2672
}
 
2673
 
 
2674
#undef STACK_ELTS_LEN
 
2675
 
 
2676
static cairo_status_t
 
2677
_cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
 
2678
                                 cairo_xlib_glyph_t *glyphs,
 
2679
                                 int num_glyphs,
 
2680
                                 cairo_scaled_font_t *scaled_font,
 
2681
                                 cairo_operator_t op,
 
2682
                                 cairo_xlib_surface_t *src,
 
2683
                                 cairo_surface_attributes_t *attributes)
 
2684
{
 
2685
    int i;
 
2686
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
2687
    cairo_scaled_glyph_t *scaled_glyph;
 
2688
    cairo_fixed_t x = 0, y = 0;
 
2689
 
 
2690
    unsigned long max_index = 0;
 
2691
    int width = 1;
 
2692
    int num_elts = 0;
 
2693
    int num_out_glyphs = 0;
 
2694
 
 
2695
    int max_request_size = XMaxRequestSize (dst->dpy)
 
2696
                         - MAX (sz_xRenderCompositeGlyphs8Req,
 
2697
                                MAX(sz_xRenderCompositeGlyphs16Req,
 
2698
                                    sz_xRenderCompositeGlyphs32Req));
 
2699
    int request_size = 0;
 
2700
 
 
2701
    _cairo_xlib_surface_ensure_dst_picture (dst);
 
2702
 
 
2703
    for (i = 0; i < num_glyphs; i++) {
 
2704
        int this_x, this_y;
 
2705
        int old_width;
 
2706
 
 
2707
        status = _cairo_scaled_glyph_lookup (scaled_font,
 
2708
                                             glyphs[i].index,
 
2709
                                             CAIRO_SCALED_GLYPH_INFO_SURFACE |
 
2710
                                             CAIRO_SCALED_GLYPH_INFO_METRICS,
 
2711
                                             &scaled_glyph);
 
2712
        if (status != CAIRO_STATUS_SUCCESS)
 
2713
            return status;
 
2714
 
 
2715
        this_x = _cairo_lround (glyphs[i].p.d.x);
 
2716
        this_y = _cairo_lround (glyphs[i].p.d.y);
 
2717
 
 
2718
        /* Glyph skipping:
 
2719
         *
 
2720
         * We skip any initial size-zero glyphs to avoid an X server bug (present
 
2721
         * in at least Xorg 7.1 without EXA) which stops rendering glyphs after
 
2722
         * the first zero-size glyph.  However, we don't skip all size-zero
 
2723
         * glyphs, since that will force a new element at every space.  We
 
2724
         * skip initial size-zero glyphs and hope that it's enough.  Since
 
2725
         * Xft never exposed that bug, this assumption should be correct.
 
2726
         *
 
2727
         * We also skip any glyphs that have troublesome coordinates.  We want
 
2728
         * to make sure that (glyph2.x - (glyph1.x + glyph1.width)) fits in
 
2729
         * a signed 16bit integer, otherwise it will overflow in the render
 
2730
         * protocol.
 
2731
         * To ensure this, we'll make sure that (glyph2.x - glyph1.x) fits in
 
2732
         * a signed 15bit integer.  The trivial option would be to allow
 
2733
         * coordinates -8192..8192, but that's kinda dull.  It probably will
 
2734
         * take a decade or so to get monitors 8192x4096 or something.  A
 
2735
         * negative value of -8192 on the other hand, is absolutely useless.
 
2736
         * Note that we do want to allow some negative positions.  The glyph
 
2737
         * may start off the screen but part of it make it to the screen.
 
2738
         * Anyway, we will allow positions in the range -1024..15359.  That
 
2739
         * will buy us a few more years before this stops working.
 
2740
         */
 
2741
        if ((!num_out_glyphs && !(scaled_glyph->surface->width && scaled_glyph->surface->height)) ||
 
2742
            (((this_x+1024)|(this_y+1024))&~0x3fffu)) {
 
2743
            glyphs[i].index = GLYPH_INDEX_SKIP;
 
2744
            continue;
 
2745
        }
 
2746
 
 
2747
        old_width = width;
 
2748
 
 
2749
        /* Update max glyph index */
 
2750
        if (glyphs[i].index > max_index) {
 
2751
            max_index = glyphs[i].index;
 
2752
            if (max_index >= 65536)
 
2753
              width = 4;
 
2754
            else if (max_index >= 256)
 
2755
              width = 2;
 
2756
            if (width != old_width)
 
2757
              request_size += (width - old_width) * num_out_glyphs;
 
2758
        }
 
2759
 
 
2760
        /* If we will pass the max request size by adding this glyph,
 
2761
         * flush current glyphs.  Note that we account for a
 
2762
         * possible element being added below. */
 
2763
        if (request_size + width > max_request_size - sz_xGlyphElt) {
 
2764
            status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, i,
 
2765
                                                            old_width, num_elts,
 
2766
                                                            scaled_font, op, src, attributes);
 
2767
            if (status != CAIRO_STATUS_SUCCESS)
 
2768
                return status;
 
2769
 
 
2770
            glyphs += i;
 
2771
            num_glyphs -= i;
 
2772
            i = 0;
 
2773
            max_index = glyphs[i].index;
 
2774
            width = max_index < 256 ? 1 : max_index < 65536 ? 2 : 4;
 
2775
            request_size = 0;
 
2776
            num_elts = 0;
 
2777
            num_out_glyphs = 0;
 
2778
            x = y = 0;
 
2779
 
 
2780
        }
 
2781
 
 
2782
        /* Convert absolute glyph position to relative-to-current-point
 
2783
         * position */
 
2784
        glyphs[i].p.i.x = this_x - x;
 
2785
        glyphs[i].p.i.y = this_y - y;
 
2786
 
 
2787
        /* Start a new element for the first glyph, or for any glyph that
 
2788
         * has unexpected position */
 
2789
        if (!num_out_glyphs || glyphs[i].p.i.x || glyphs[i].p.i.y) {
 
2790
            num_elts++;
 
2791
            request_size += sz_xGlyphElt;
 
2792
        }
 
2793
 
 
2794
        /* Send unsent glyphs to the server */
 
2795
        if (scaled_glyph->surface_private == NULL) {
 
2796
            _cairo_xlib_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
 
2797
            scaled_glyph->surface_private = (void *) 1;
 
2798
        }
 
2799
 
 
2800
        /* adjust current-position */
 
2801
        x = this_x + scaled_glyph->x_advance;
 
2802
        y = this_y + scaled_glyph->y_advance;
 
2803
 
 
2804
        num_out_glyphs++;
 
2805
        request_size += width;
 
2806
    }
 
2807
 
 
2808
    if (num_elts)
 
2809
        status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, num_glyphs,
 
2810
                                                        width, num_elts,
 
2811
                                                        scaled_font, op, src, attributes);
 
2812
 
 
2813
    return status;
 
2814
}
 
2815
 
 
2816
#undef GLYPH_INDEX_SKIP
2679
2817
 
2680
2818
static cairo_int_status_t
2681
2819
_cairo_xlib_surface_show_glyphs (void                *abstract_dst,
2682
2820
                                 cairo_operator_t     op,
2683
2821
                                 cairo_pattern_t     *src_pattern,
2684
 
                                 const cairo_glyph_t *glyphs,
 
2822
                                 cairo_glyph_t       *glyphs,
2685
2823
                                 int                  num_glyphs,
2686
2824
                                 cairo_scaled_font_t *scaled_font)
2687
2825
{
2692
2830
    cairo_surface_attributes_t attributes;
2693
2831
    cairo_xlib_surface_t *src = NULL;
2694
2832
 
2695
 
    cairo_glyph_t *output_glyphs;
2696
 
    const cairo_glyph_t *glyphs_chunk;
2697
 
    int glyphs_remaining, chunk_size, max_chunk_size;
2698
 
    cairo_scaled_glyph_t *scaled_glyph;
2699
2833
    cairo_xlib_surface_font_private_t *font_private;
2700
2834
 
2701
 
    int i, o;
2702
 
    unsigned long max_index = 0;
2703
 
 
2704
 
    cairo_xlib_surface_show_glyphs_func_t show_glyphs_func;
2705
 
 
2706
2835
    cairo_pattern_union_t solid_pattern;
2707
2836
 
2708
2837
    if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || !dst->xrender_format)
2742
2871
        (font_private != NULL && font_private->dpy != dst->dpy))
2743
2872
        return CAIRO_INT_STATUS_UNSUPPORTED;
2744
2873
 
2745
 
    /* We make a copy of the glyphs so that we can elide any size-zero
2746
 
     * glyphs to workaround an X server bug, (present in at least Xorg
2747
 
     * 7.1 without EXA). */
2748
 
    output_glyphs = malloc (num_glyphs * sizeof (cairo_glyph_t));
2749
 
    if (output_glyphs == NULL)
2750
 
        return CAIRO_STATUS_NO_MEMORY;
2751
 
 
2752
2874
    /* After passing all those tests, we're now committed to rendering
2753
2875
     * these glyphs or to fail trying. We first upload any glyphs to
2754
2876
     * the X server that it doesn't have already, then we draw
2806
2928
    if (status)
2807
2929
        goto BAIL;
2808
2930
 
2809
 
    /* Send all unsent glyphs to the server, and count the max of the glyph indices */
2810
 
    for (i = 0, o = 0; i < num_glyphs; i++) {
2811
 
        if (glyphs[i].index > max_index)
2812
 
            max_index = glyphs[i].index;
2813
 
        status = _cairo_scaled_glyph_lookup (scaled_font,
2814
 
                                             glyphs[i].index,
2815
 
                                             CAIRO_SCALED_GLYPH_INFO_SURFACE,
2816
 
                                             &scaled_glyph);
2817
 
        if (status != CAIRO_STATUS_SUCCESS)
2818
 
            goto BAIL;
2819
 
        /* Don't put any size-zero glyphs into output_glyphs to avoid
2820
 
         * an X server bug which stops rendering glyphs after the
2821
 
         * first size-zero glyph. */
2822
 
        if (scaled_glyph->surface->width && scaled_glyph->surface->height) {
2823
 
            output_glyphs[o++] = glyphs[i];
2824
 
            if (scaled_glyph->surface_private == NULL) {
2825
 
                _cairo_xlib_surface_add_glyph (dst->dpy, scaled_font, scaled_glyph);
2826
 
                scaled_glyph->surface_private = (void *) 1;
2827
 
            }
2828
 
        }
2829
 
    }
2830
 
    num_glyphs = o;
2831
 
 
2832
 
    _cairo_xlib_surface_ensure_dst_picture (dst);
2833
 
 
2834
 
    max_chunk_size = XMaxRequestSize (dst->dpy);
2835
 
    if (max_index < 256) {
2836
 
        max_chunk_size -= sz_xRenderCompositeGlyphs8Req;
2837
 
        show_glyphs_func = _cairo_xlib_surface_show_glyphs8;
2838
 
    } else if (max_index < 65536) {
2839
 
        max_chunk_size -= sz_xRenderCompositeGlyphs16Req;
2840
 
        show_glyphs_func = _cairo_xlib_surface_show_glyphs16;
2841
 
    } else {
2842
 
        max_chunk_size -= sz_xRenderCompositeGlyphs32Req;
2843
 
        show_glyphs_func = _cairo_xlib_surface_show_glyphs32;
2844
 
    }
2845
 
    max_chunk_size /= sz_xGlyphElt;
2846
 
 
2847
 
    for (glyphs_remaining = num_glyphs, glyphs_chunk = output_glyphs;
2848
 
         glyphs_remaining;
2849
 
         glyphs_remaining -= chunk_size, glyphs_chunk += chunk_size)
2850
 
    {
2851
 
        chunk_size = MIN (glyphs_remaining, max_chunk_size);
2852
 
 
2853
 
        status = show_glyphs_func (dst, op, src,
2854
 
                                   attributes.x_offset, attributes.y_offset,
2855
 
                                   glyphs_chunk, chunk_size, scaled_font);
2856
 
        if (status != CAIRO_STATUS_SUCCESS)
2857
 
            break;
2858
 
    }
 
2931
    _cairo_xlib_surface_emit_glyphs (dst, (cairo_xlib_glyph_t *) glyphs, num_glyphs,
 
2932
                                     scaled_font, op, src, &attributes);
2859
2933
 
2860
2934
  BAIL:
2861
2935
    _cairo_scaled_font_thaw_cache (scaled_font);
2862
 
    free (output_glyphs);
2863
2936
 
2864
2937
    if (src)
2865
2938
        _cairo_pattern_release_surface (src_pattern, &src->base, &attributes);