diff --git a/src/Makefile.am b/src/Makefile.am index cb0ddd016..0114d4ab6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,6 +11,7 @@ CXX = gcc -g -O2 -fno-rtti -fno-exceptions -Wabi -Wpadded -Wcast-align noinst_LTLIBRARIES = libharfbuzz-1.la HBSOURCES = \ + hb-blob.c \ hb-buffer.c \ hb-buffer-private.h \ hb-private.h \ @@ -22,11 +23,13 @@ HBSOURCES = \ hb-ot-layout-gsub-private.h \ hb-ot-layout-open-private.h \ hb-ot-layout-private.h \ + hb-refcount-private.h \ $(NULL) HBHEADERS = \ - hb-common.h \ + hb-blob.h \ hb-buffer.h \ + hb-common.h \ hb-ot-layout.h \ $(NULL) diff --git a/src/hb-blob.c b/src/hb-blob.c new file mode 100644 index 000000000..bcdf13418 --- /dev/null +++ b/src/hb-blob.c @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * + * This is part of HarfBuzz, an OpenType Layout engine library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + */ + +#include "hb-private.h" + +#include "hb-blob.h" +#include "hb-refcount-private.h" + +struct _hb_blob_t { + const char *data; + unsigned int len; + hb_memory_mode_t mode; + + hb_reference_count_t ref_count; + hb_destroy_func_t destroy; + void *user_data; +}; +static hb_blob_t _hb_blob_nil = { + NULL, + 0, + HB_MEMORY_MODE_READONLY, + + HB_REFERENCE_COUNT_INVALID, + NULL, + NULL +}; + +static void +_hb_blob_destroy_user_data (hb_blob_t *blob) +{ + if (blob->destroy) { + blob->destroy (blob->user_data); + blob->destroy = NULL; + blob->user_data = NULL; + } +} + +hb_blob_t * +hb_blob_create (const char *data, + unsigned int len, + hb_memory_mode_t mode, + hb_destroy_func_t destroy, + void *user_data) +{ + hb_blob_t *blob; + + blob = malloc (sizeof (hb_blob_t)); + if (!blob) { + if (destroy) + destroy (user_data); + return &_hb_blob_nil; + } + + blob->data = data; + blob->len = len; + blob->mode = mode; + + HB_REFERENCE_COUNT_INIT (blob->ref_count, 1); + blob->destroy = destroy; + blob->user_data = user_data; + + if (blob->mode == HB_MEMORY_MODE_DUPLICATE) { + blob->mode = HB_MEMORY_MODE_READONLY; + hb_blob_make_writeable (blob); + } + + return blob; +} + +hb_blob_t * +hb_blob_reference (hb_blob_t *blob) +{ + if (blob == NULL || HB_REFERENCE_COUNT_IS_INVALID (blob->ref_count)) + return blob; + + assert (HB_REFERENCE_COUNT_HAS_REFERENCE (blob->ref_count)); + + _hb_reference_count_inc (blob->ref_count); + + return blob; +} + +void +hb_blob_destroy (hb_blob_t *blob) +{ + if (blob == NULL || HB_REFERENCE_COUNT_IS_INVALID (blob->ref_count)) + return; + + assert (HB_REFERENCE_COUNT_HAS_REFERENCE (blob->ref_count)); + + if (!_hb_reference_count_dec_and_test (blob->ref_count)) + return; + + _hb_blob_destroy_user_data (blob); + + free (blob); +} + +const char * +hb_blob_get_data (hb_blob_t *blob, + unsigned int *len) +{ + if (len) + *len = blob->len; + + return blob->data; +} + +hb_bool_t +hb_blob_is_writeable (hb_blob_t *blob) +{ + return blob->mode == HB_MEMORY_MODE_WRITEABLE; +} + +hb_bool_t +hb_blob_try_writeable_inplace (hb_blob_t *blob) +{ + if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITEABLE) { + /* XXX + * mprotect + blob->mode == HB_MEMORY_MODE_WRITEABLE; + */ + } + + return blob->mode == HB_MEMORY_MODE_WRITEABLE; +} + +/* DANGER: May rebase or nullify */ +void +hb_blob_make_writeable (hb_blob_t *blob) +{ + if (blob->mode == HB_MEMORY_MODE_READONLY_NEVER_DUPLICATE) + { + _hb_blob_destroy_user_data (blob); + blob->data = NULL; + blob->len = 0; + } + else if (blob->mode == HB_MEMORY_MODE_READONLY) + { + char *new_data; + + new_data = malloc (blob->len); + if (new_data) + memcpy (new_data, blob->data, blob->len); + + _hb_blob_destroy_user_data (blob); + + if (!new_data) { + blob->data = NULL; + blob->len = 0; + } else + blob->data = new_data; + + blob->mode = HB_MEMORY_MODE_WRITEABLE; + } + else + hb_blob_try_writeable_inplace (blob); +} diff --git a/src/hb-blob.h b/src/hb-blob.h new file mode 100644 index 000000000..6cb7c34bb --- /dev/null +++ b/src/hb-blob.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2009 Red Hat, Inc. + * + * This is part of HarfBuzz, an OpenType Layout engine library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Red Hat Author(s): Behdad Esfahbod + */ + +#ifndef HB_BLOB_H +#define HB_BLOB_H + +#include "hb-common.h" + +HB_BEGIN_DECLS + +typedef struct _hb_blob_t hb_blob_t; +typedef void (*hb_destroy_func_t) (void *user_data); + +typedef enum { + HB_MEMORY_MODE_DUPLICATE, + HB_MEMORY_MODE_READONLY, + HB_MEMORY_MODE_WRITEABLE, + HB_MEMORY_MODE_READONLY_NEVER_DUPLICATE, + HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITEABLE, +} hb_memory_mode_t; + +hb_blob_t * +hb_blob_create (const char *data, + unsigned int len, + hb_memory_mode_t mode, + hb_destroy_func_t destroy, + void *user_data); + +hb_blob_t * +hb_blob_reference (hb_blob_t *blob); + +void +hb_blob_destroy (hb_blob_t *blob); + +const char * +hb_blob_get_data (hb_blob_t *blob, + unsigned int *len); + +hb_bool_t +hb_blob_is_writeable (hb_blob_t *blob); + +hb_bool_t +hb_blob_try_writeable_inplace (hb_blob_t *blob); + +/* DANGER: May rebase or nullify */ +void +hb_blob_make_writeable (hb_blob_t *blob); + +HB_END_DECLS + +#endif /* HB_BLOB_H */ diff --git a/src/hb-private.h b/src/hb-private.h index 6698a7cea..196bc3c1f 100644 --- a/src/hb-private.h +++ b/src/hb-private.h @@ -49,6 +49,8 @@ #include #include /* XXX */ +#include +#include /* Basics */ diff --git a/src/hb-refcount-private.h b/src/hb-refcount-private.h new file mode 100644 index 000000000..e8acb2569 --- /dev/null +++ b/src/hb-refcount-private.h @@ -0,0 +1,54 @@ +/* + * Copyright © 2007 Chris Wilson + * + * This is part of HarfBuzz, an OpenType Layout engine library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Contributor(s): + * Chris Wilson + */ + +#ifndef HB_REFCOUNT_PRIVATE_H +#define HB_REFCOUNT_PRIVATE_H + +typedef int hb_atomic_int_t; + +/* Encapsulate operations on the object's reference count */ +typedef struct { + hb_atomic_int_t ref_count; +} hb_reference_count_t; + +/* XXX add real atomic ops */ +#define _hb_reference_count_inc(RC) ((RC).ref_count++) +#define _hb_reference_count_dec_and_test(RC) ((RC).ref_count-- == 1) + +#define HB_REFERENCE_COUNT_INIT(RC, VALUE) ((RC).ref_count = (VALUE)) + +#define HB_REFERENCE_COUNT_GET_VALUE(RC) ((RC).ref_count+0) +#define HB_REFERENCE_COUNT_SET_VALUE(RC, VALUE) ((RC).ref_count = (VALUE), 0) + +#define HB_REFERENCE_COUNT_INVALID_VALUE ((hb_atomic_int_t) -1) +#define HB_REFERENCE_COUNT_INVALID {HB_REFERENCE_COUNT_INVALID_VALUE} + +#define HB_REFERENCE_COUNT_IS_INVALID(RC) (HB_REFERENCE_COUNT_GET_VALUE (RC) == HB_REFERENCE_COUNT_INVALID_VALUE) + +#define HB_REFERENCE_COUNT_HAS_REFERENCE(RC) (HB_REFERENCE_COUNT_GET_VALUE (RC) > 0) + +#endif /* HB_REFCOUNT_PRIVATE_H */