Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Copyright © 2012 Intel Corporation
  3.  *
  4.  * This library is free software; you can redistribute it and/or
  5.  * modify it either under the terms of the GNU Lesser General Public
  6.  * License version 2.1 as published by the Free Software Foundation
  7.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  8.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  9.  * notice, a recipient may use your version of this file under either
  10.  * the MPL or the LGPL.
  11.  *
  12.  * You should have received a copy of the LGPL along with this library
  13.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  14.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  15.  * You should have received a copy of the MPL along with this library
  16.  * in the file COPYING-MPL-1.1
  17.  *
  18.  * The contents of this file are subject to the Mozilla Public License
  19.  * Version 1.1 (the "License"); you may not use this file except in
  20.  * compliance with the License. You may obtain a copy of the License at
  21.  * http://www.mozilla.org/MPL/
  22.  *
  23.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  24.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  25.  * the specific language governing rights and limitations.
  26.  *
  27.  * The Original Code is the cairo graphics library.
  28.  *
  29.  * The Initial Developer of the Original Code is Chris Wilson
  30.  *
  31.  * Contributor(s):
  32.  *      Chris Wilson <chris@chris-wilson.co.uk>
  33.  */
  34.  
  35. #include "cairoint.h"
  36.  
  37. #include "cairo-damage-private.h"
  38. #include "cairo-region-private.h"
  39.  
  40. static const cairo_damage_t __cairo_damage__nil = { CAIRO_STATUS_NO_MEMORY };
  41.  
  42. cairo_damage_t *
  43. _cairo_damage_create_in_error (cairo_status_t status)
  44. {
  45.     _cairo_error_throw (status);
  46.     return (cairo_damage_t *) &__cairo_damage__nil;
  47. }
  48.  
  49. cairo_damage_t *
  50. _cairo_damage_create (void)
  51. {
  52.     cairo_damage_t *damage;
  53.  
  54.     damage = malloc (sizeof (*damage));
  55.     if (unlikely (damage == NULL)) {
  56.         _cairo_error_throw(CAIRO_STATUS_NO_MEMORY);
  57.         return (cairo_damage_t *) &__cairo_damage__nil;
  58.     }
  59.  
  60.     damage->status = CAIRO_STATUS_SUCCESS;
  61.     damage->region = NULL;
  62.     damage->dirty = 0;
  63.     damage->tail = &damage->chunks;
  64.     damage->chunks.base = damage->boxes;
  65.     damage->chunks.size = ARRAY_LENGTH(damage->boxes);
  66.     damage->chunks.count = 0;
  67.     damage->chunks.next = NULL;
  68.  
  69.     damage->remain = damage->chunks.size;
  70.  
  71.     return damage;
  72. }
  73.  
  74. void
  75. _cairo_damage_destroy (cairo_damage_t *damage)
  76. {
  77.     struct _cairo_damage_chunk *chunk, *next;
  78.  
  79.     if (damage == (cairo_damage_t *) &__cairo_damage__nil)
  80.         return;
  81.  
  82.     for (chunk = damage->chunks.next; chunk != NULL; chunk = next) {
  83.         next = chunk->next;
  84.         free (chunk);
  85.     }
  86.     cairo_region_destroy (damage->region);
  87.     free (damage);
  88. }
  89.  
  90. static cairo_damage_t *
  91. _cairo_damage_add_boxes(cairo_damage_t *damage,
  92.                         const cairo_box_t *boxes,
  93.                         int count)
  94. {
  95.     struct _cairo_damage_chunk *chunk;
  96.     int n, size;
  97.  
  98.     TRACE ((stderr, "%s x%d\n", __FUNCTION__, count));
  99.  
  100.     if (damage == NULL)
  101.         damage = _cairo_damage_create ();
  102.     if (damage->status)
  103.         return damage;
  104.  
  105.     damage->dirty += count;
  106.  
  107.     n = count;
  108.     if (n > damage->remain)
  109.         n = damage->remain;
  110.  
  111.     memcpy (damage->tail->base + damage->tail->count, boxes,
  112.             n * sizeof (cairo_box_t));
  113.  
  114.     count -= n;
  115.     damage->tail->count += n;
  116.     damage->remain -= n;
  117.  
  118.     if (count == 0)
  119.         return damage;
  120.  
  121.     size = 2 * damage->tail->size;
  122.     if (size < count)
  123.         size = (count + 64) & ~63;
  124.  
  125.     chunk = malloc (sizeof (*chunk) + sizeof (cairo_box_t) * size);
  126.     if (unlikely (chunk == NULL)) {
  127.         _cairo_damage_destroy (damage);
  128.         return (cairo_damage_t *) &__cairo_damage__nil;
  129.     }
  130.  
  131.     chunk->next = NULL;
  132.     chunk->base = (cairo_box_t *) (chunk + 1);
  133.     chunk->size = size;
  134.     chunk->count = count;
  135.  
  136.     damage->tail->next = chunk;
  137.     damage->tail = chunk;
  138.  
  139.     memcpy (damage->tail->base, boxes + n,
  140.             count * sizeof (cairo_box_t));
  141.     damage->remain = size - count;
  142.  
  143.     return damage;
  144. }
  145.  
  146. cairo_damage_t *
  147. _cairo_damage_add_box(cairo_damage_t *damage,
  148.                       const cairo_box_t *box)
  149. {
  150.     TRACE ((stderr, "%s: (%d, %d),(%d, %d)\n", __FUNCTION__,
  151.             box->p1.x, box->p1.y, box->p2.x, box->p2.y));
  152.  
  153.     return _cairo_damage_add_boxes(damage, box, 1);
  154. }
  155.  
  156. cairo_damage_t *
  157. _cairo_damage_add_rectangle(cairo_damage_t *damage,
  158.                             const cairo_rectangle_int_t *r)
  159. {
  160.     cairo_box_t box;
  161.  
  162.     TRACE ((stderr, "%s: (%d, %d)x(%d, %d)\n", __FUNCTION__,
  163.             r->x, r->y, r->width, r->height));
  164.  
  165.     box.p1.x = r->x;
  166.     box.p1.y = r->y;
  167.     box.p2.x = r->x + r->width;
  168.     box.p2.y = r->y + r->height;
  169.  
  170.     return _cairo_damage_add_boxes(damage, &box, 1);
  171. }
  172.  
  173. cairo_damage_t *
  174. _cairo_damage_add_region (cairo_damage_t *damage,
  175.                           const cairo_region_t *region)
  176. {
  177.     cairo_box_t *boxes;
  178.     int nbox;
  179.  
  180.     TRACE ((stderr, "%s\n", __FUNCTION__));
  181.  
  182.     boxes = _cairo_region_get_boxes (region, &nbox);
  183.     return _cairo_damage_add_boxes(damage, boxes, nbox);
  184. }
  185.  
  186. cairo_damage_t *
  187. _cairo_damage_reduce (cairo_damage_t *damage)
  188. {
  189.     cairo_box_t *free_boxes = NULL;
  190.     cairo_box_t *boxes, *b;
  191.     struct _cairo_damage_chunk *chunk, *last;
  192.  
  193.     TRACE ((stderr, "%s: dirty=%d\n", __FUNCTION__,
  194.             damage ? damage->dirty : -1));
  195.     if (damage == NULL || damage->status || !damage->dirty)
  196.         return damage;
  197.  
  198.     if (damage->region) {
  199.         cairo_region_t *region;
  200.  
  201.         region = damage->region;
  202.         damage->region = NULL;
  203.  
  204.         damage = _cairo_damage_add_region (damage, region);
  205.         cairo_region_destroy (region);
  206.  
  207.         if (unlikely (damage->status))
  208.             return damage;
  209.     }
  210.  
  211.     boxes = damage->tail->base;
  212.     if (damage->dirty > damage->tail->size) {
  213.         boxes = free_boxes = malloc (damage->dirty * sizeof (cairo_box_t));
  214.         if (unlikely (boxes == NULL)) {
  215.             _cairo_damage_destroy (damage);
  216.             return (cairo_damage_t *) &__cairo_damage__nil;
  217.         }
  218.  
  219.         b = boxes;
  220.         last = NULL;
  221.     } else {
  222.         b = boxes + damage->tail->count;
  223.         last = damage->tail;
  224.     }
  225.  
  226.     for (chunk = &damage->chunks; chunk != last; chunk = chunk->next) {
  227.         memcpy (b, chunk->base, chunk->count * sizeof (cairo_box_t));
  228.         b += chunk->count;
  229.     }
  230.  
  231.     damage->region = _cairo_region_create_from_boxes (boxes, damage->dirty);
  232.     free (free_boxes);
  233.  
  234.     if (unlikely (damage->region->status)) {
  235.         _cairo_damage_destroy (damage);
  236.         return (cairo_damage_t *) &__cairo_damage__nil;
  237.     }
  238.  
  239.     damage->dirty = 0;
  240.     return damage;
  241. }
  242.