summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Deutschmann <whissi@gentoo.org>2019-10-15 12:24:12 +0200
committerThomas Deutschmann <whissi@gentoo.org>2020-08-13 11:26:55 +0200
commite088156d5b620e5e639580dacf85c6dc13823c74 (patch)
tree57f5c025e203279944da512166c20bc0521d8ccd /base/gsutil.c
downloadghostscript-gpl-patches-e088156d5b620e5e639580dacf85c6dc13823c74.tar.gz
ghostscript-gpl-patches-e088156d5b620e5e639580dacf85c6dc13823c74.tar.bz2
ghostscript-gpl-patches-e088156d5b620e5e639580dacf85c6dc13823c74.zip
Import Ghostscript 9.50ghostscript-9.50
Signed-off-by: Thomas Deutschmann <whissi@gentoo.org>
Diffstat (limited to 'base/gsutil.c')
-rw-r--r--base/gsutil.c372
1 files changed, 372 insertions, 0 deletions
diff --git a/base/gsutil.c b/base/gsutil.c
new file mode 100644
index 00000000..d936d894
--- /dev/null
+++ b/base/gsutil.c
@@ -0,0 +1,372 @@
+/* Copyright (C) 2001-2019 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied,
+ modified or distributed except as expressly authorized under the terms
+ of the license contained in the file LICENSE in this distribution.
+
+ Refer to licensing information at http://www.artifex.com or contact
+ Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
+ CA 94945, U.S.A., +1(415)492-9861, for further information.
+*/
+
+
+/* Utilities for Ghostscript library */
+
+#include "string_.h"
+#include "memory_.h"
+#include "gstypes.h"
+#include "gserrors.h"
+#include "gsmemory.h" /* for init procedure */
+#include "gsrect.h" /* for prototypes */
+#include "gsuid.h"
+#include "gsutil.h" /* for prototypes */
+#include "gzstate.h"
+#include "gxdcolor.h"
+
+/* ------ Unique IDs ------ */
+
+ulong
+gs_next_ids(const gs_memory_t *mem, uint count)
+{
+ gs_lib_ctx_core_t *core = mem->gs_lib_ctx->core;
+ ulong id = core->gs_next_id;
+
+ core->gs_next_id += count;
+ return id;
+}
+
+/* ------ Memory utilities ------ */
+
+/* Transpose an 8 x 8 block of bits. line_size is the raster of */
+/* the input data. dist is the distance between output bytes. */
+
+void
+memflip8x8(const byte * inp, int line_size, byte * outp, int dist)
+{
+ uint aceg, bdfh;
+
+ {
+ const byte *ptr4 = inp + (line_size << 2);
+ const int ls2 = line_size << 1;
+
+ aceg = ((uint)*inp) | ((uint)inp[ls2] << 8) |
+ ((uint)*ptr4 << 16) | ((uint)ptr4[ls2] << 24);
+ inp += line_size, ptr4 += line_size;
+ bdfh = ((uint)*inp) | ((uint)inp[ls2] << 8) |
+ ((uint)*ptr4 << 16) | ((uint)ptr4[ls2] << 24);
+ }
+
+ /* Check for all 8 bytes being the same. */
+ /* This is especially worth doing for the case where all are zero. */
+ if (aceg == bdfh && (aceg >> 8) == (aceg & 0xffffff)) {
+ if (aceg == 0 || aceg == 0xffffffff)
+ goto store;
+ *outp = (byte)-(int)((aceg >> 7) & 1);
+ outp[dist] = (byte)-(int)((aceg >> 6) & 1);
+ outp += dist << 1;
+ *outp = (byte)-(int)((aceg >> 5) & 1);
+ outp[dist] = (byte)-(int)((aceg >> 4) & 1);
+ outp += dist << 1;
+ *outp = (byte)-(int)((aceg >> 3) & 1);
+ outp[dist] = (byte)-(int)((aceg >> 2) & 1);
+ outp += dist << 1;
+ *outp = (byte)-(int)((aceg >> 1) & 1);
+ outp[dist] = (byte)-(int)(aceg & 1);
+ return;
+ } {
+ register uint temp;
+
+/* Transpose a block of bits between registers. */
+#define TRANSPOSE(r,s,mask,shift)\
+ (r ^= (temp = ((s >> shift) ^ r) & mask),\
+ s ^= temp << shift)
+
+/* Transpose blocks of 4 x 4 */
+ TRANSPOSE(aceg, aceg, 0x00000f0f, 20);
+ TRANSPOSE(bdfh, bdfh, 0x00000f0f, 20);
+
+/* Transpose blocks of 2 x 2 */
+ TRANSPOSE(aceg, aceg, 0x00330033, 10);
+ TRANSPOSE(bdfh, bdfh, 0x00330033, 10);
+
+/* Transpose blocks of 1 x 1 */
+ TRANSPOSE(aceg, bdfh, 0x55555555, 1);
+
+#undef TRANSPOSE
+ }
+
+ store:
+ *outp = (byte)aceg;
+ outp[dist] = (byte)bdfh;
+ outp += dist << 1;
+ *outp = (byte)(aceg >>= 8);
+ outp[dist] = (byte)(bdfh >>= 8);
+ outp += dist << 1;
+ *outp = (byte)(aceg >>= 8);
+ outp[dist] = (byte)(bdfh >>= 8);
+ outp += dist << 1;
+ *outp = (byte)(aceg >> 8);
+ outp[dist] = (byte)(bdfh >> 8);
+}
+
+#ifdef PACIFY_VALGRIND
+void
+memflip8x8_eol(const byte * inp, int line_size, byte * outp, int dist, int bits)
+{
+ uint aceg, bdfh;
+ uint mask;
+
+ {
+ const byte *ptr4 = inp + (line_size << 2);
+ const int ls2 = line_size << 1;
+
+ aceg = ((uint)*inp) | ((uint)inp[ls2] << 8) |
+ ((uint)*ptr4 << 16) | ((uint)ptr4[ls2] << 24);
+ inp += line_size, ptr4 += line_size;
+ bdfh = ((uint)*inp) | ((uint)inp[ls2] << 8) |
+ ((uint)*ptr4 << 16) | ((uint)ptr4[ls2] << 24);
+ }
+
+ /* Keep just the defined bits */
+ mask = (0xff00>>(bits&7)) & 0xff;
+ mask |= mask<<8;
+ mask |= mask<<16;
+ aceg &= mask;
+ bdfh &= mask;
+
+ /* Check for all 8 bytes being the same. */
+ /* This is especially worth doing for the case where all are zero. */
+ if (aceg == bdfh && (aceg >> 8) == (aceg & 0xffffff)) {
+ if (aceg == 0 || aceg == 0xffffffff)
+ goto store;
+ *outp = (byte)-(int)((aceg >> 7) & 1);
+ outp[dist] = (byte)-(int)((aceg >> 6) & 1);
+ outp += dist << 1;
+ *outp = (byte)-(int)((aceg >> 5) & 1);
+ outp[dist] = (byte)-(int)((aceg >> 4) & 1);
+ outp += dist << 1;
+ *outp = (byte)-(int)((aceg >> 3) & 1);
+ outp[dist] = (byte)-(int)((aceg >> 2) & 1);
+ outp += dist << 1;
+ *outp = (byte)-(int)((aceg >> 1) & 1);
+ outp[dist] = (byte)-(int)(aceg & 1);
+ return;
+ } {
+ register uint temp;
+
+/* Transpose a block of bits between registers. */
+#define TRANSPOSE(r,s,mask,shift)\
+ (r ^= (temp = ((s >> shift) ^ r) & mask),\
+ s ^= temp << shift)
+
+/* Transpose blocks of 4 x 4 */
+ TRANSPOSE(aceg, aceg, 0x00000f0f, 20);
+ TRANSPOSE(bdfh, bdfh, 0x00000f0f, 20);
+
+/* Transpose blocks of 2 x 2 */
+ TRANSPOSE(aceg, aceg, 0x00330033, 10);
+ TRANSPOSE(bdfh, bdfh, 0x00330033, 10);
+
+/* Transpose blocks of 1 x 1 */
+ TRANSPOSE(aceg, bdfh, 0x55555555, 1);
+
+#undef TRANSPOSE
+ }
+
+ store:
+ *outp = (byte)aceg;
+ outp[dist] = (byte)bdfh;
+ outp += dist << 1;
+ *outp = (byte)(aceg >>= 8);
+ outp[dist] = (byte)(bdfh >>= 8);
+ outp += dist << 1;
+ *outp = (byte)(aceg >>= 8);
+ outp[dist] = (byte)(bdfh >>= 8);
+ outp += dist << 1;
+ *outp = (byte)(aceg >> 8);
+ outp[dist] = (byte)(bdfh >> 8);
+}
+#endif
+
+/* Get an unsigned, big-endian 32-bit value. */
+ulong
+get_u32_msb(const byte *p)
+{
+ return ((uint)p[0] << 24) + ((uint)p[1] << 16) + ((uint)p[2] << 8) + p[3];
+}
+
+/* Put an unsigned, big-endian 32-bit value. */
+void
+put_u32_msb(byte *p, const ulong n, const int offs)
+{
+ (p + offs)[0] = n >> 24 & 255;
+ (p + offs)[1] = n >> 16 & 255;
+ (p + offs)[2] = n >> 8 & 255;
+ (p + offs)[3] = n & 255;
+}
+
+/* ------ String utilities ------ */
+
+/* Compare two strings, returning -1 if the first is less, */
+/* 0 if they are equal, and 1 if first is greater. */
+/* We can't use memcmp, because we always use unsigned characters. */
+int
+bytes_compare(const byte * s1, uint len1, const byte * s2, uint len2)
+{
+ register uint len = len1;
+
+ if (len2 < len)
+ len = len2;
+ {
+ register const byte *p1 = s1;
+ register const byte *p2 = s2;
+
+ while (len--)
+ if (*p1++ != *p2++)
+ return (p1[-1] < p2[-1] ? -1 : 1);
+ }
+ /* Now check for differing lengths */
+ return (len1 == len2 ? 0 : len1 < len2 ? -1 : 1);
+}
+
+/* Test whether a string matches a pattern with wildcards. */
+/* '*' = any substring, '?' = any character, '\' quotes next character. */
+const string_match_params string_match_params_default = {
+ '*', '?', '\\', false, false
+};
+
+bool
+string_match(const byte * str, uint len, const byte * pstr, uint plen,
+ register const string_match_params * psmp)
+{
+ const byte *pback = 0;
+ const byte *spback = 0; /* initialized only to pacify gcc */
+ const byte *p = pstr, *pend = pstr + plen;
+ const byte *sp = str, *spend = str + len;
+
+ if (psmp == 0)
+ psmp = &string_match_params_default;
+ again:while (p < pend) {
+ register byte ch = *p;
+
+ if (ch == psmp->any_substring) {
+ pback = ++p, spback = sp;
+ continue;
+ } else if (ch == psmp->any_char) {
+ if (sp == spend)
+ return false; /* str too short */
+ p++, sp++;
+ continue;
+ } else if (ch == psmp->quote_next) {
+ if (++p == pend)
+ return true; /* bad pattern */
+ ch = *p;
+ }
+ if (sp == spend)
+ return false; /* str too short */
+ if (*sp == ch ||
+ (psmp->ignore_case && (*sp ^ ch) == 0x20 &&
+ (ch &= ~0x20) >= 0x41 && ch <= 0x5a) ||
+ (psmp->slash_equiv && ((ch == '\\' && *sp == '/') ||
+ (ch == '/' && *sp == '\\')))
+ )
+ p++, sp++;
+ else if (pback == 0)
+ return false; /* no * to back up to */
+ else {
+ sp = ++spback;
+ p = pback;
+ }
+ }
+ if (sp < spend) { /* We got a match, but there are chars left over. */
+ /* If we can back up, back up to the only place that */
+ /* could produce a complete match, otherwise fail. */
+ if (pback == 0)
+ return false;
+ p = pback;
+ pback = 0;
+ sp = spend - (pend - p);
+ goto again;
+ }
+ return true;
+}
+
+/* ------ UID utilities ------ */
+
+/* Compare two UIDs for equality. */
+/* We know that at least one of them is valid. */
+bool
+uid_equal(register const gs_uid * puid1, register const gs_uid * puid2)
+{
+ if (puid1->id != puid2->id)
+ return false;
+ if (puid1->id >= 0)
+ return true; /* UniqueID */
+ return
+ !memcmp((const char *)puid1->xvalues,
+ (const char *)puid2->xvalues,
+ (uint) - (puid1->id) * sizeof(long));
+}
+
+/* Copy the XUID data for a uid, if needed, updating the uid in place. */
+int
+uid_copy(gs_uid *puid, gs_memory_t *mem, client_name_t cname)
+{
+ if (uid_is_XUID(puid)) {
+ uint xsize = uid_XUID_size(puid);
+ long *xvalues = (long *)
+ gs_alloc_byte_array(mem, xsize, sizeof(long), cname);
+
+ if (xvalues == 0)
+ return_error(gs_error_VMerror);
+ memcpy(xvalues, uid_XUID_values(puid), xsize * sizeof(long));
+ puid->xvalues = xvalues;
+ }
+ return 0;
+}
+
+/* ------ Rectangle utilities ------ */
+
+/*
+ * Calculate the difference of two rectangles, a list of up to 4 rectangles.
+ * Return the number of rectangles in the list, and set the first rectangle
+ * to the intersection.
+ */
+int
+int_rect_difference(gs_int_rect * outer, const gs_int_rect * inner,
+ gs_int_rect * diffs /*[4] */ )
+{
+ int x0 = outer->p.x, y0 = outer->p.y;
+ int x1 = outer->q.x, y1 = outer->q.y;
+ int count = 0;
+
+ if (y0 < inner->p.y) {
+ diffs[0].p.x = x0, diffs[0].p.y = y0;
+ diffs[0].q.x = x1, diffs[0].q.y = min(y1, inner->p.y);
+ outer->p.y = y0 = diffs[0].q.y;
+ ++count;
+ }
+ if (y1 > inner->q.y) {
+ diffs[count].p.x = x0, diffs[count].p.y = max(y0, inner->q.y);
+ diffs[count].q.x = x1, diffs[count].q.y = y1;
+ outer->q.y = y1 = diffs[count].p.y;
+ ++count;
+ }
+ if (x0 < inner->p.x) {
+ diffs[0].p.x = x0, diffs[0].p.y = y0;
+ diffs[0].q.x = min(x1, inner->p.x), diffs[0].q.y = y1;
+ outer->p.x = x0 = diffs[count].q.x;
+ ++count;
+ }
+ if (x1 > inner->q.x) {
+ diffs[count].p.x = max(x0, inner->q.x), diffs[count].p.y = y0;
+ diffs[count].q.x = x1, diffs[count].q.y = y1;
+ outer->q.x = x1 = diffs[count].p.x;
+ ++count;
+ }
+ return count;
+}