diff options
Diffstat (limited to 'Build/source/texk/dvipdfm-x/cs_type2.c')
-rw-r--r-- | Build/source/texk/dvipdfm-x/cs_type2.c | 808 |
1 files changed, 0 insertions, 808 deletions
diff --git a/Build/source/texk/dvipdfm-x/cs_type2.c b/Build/source/texk/dvipdfm-x/cs_type2.c deleted file mode 100644 index df7250c6b7c..00000000000 --- a/Build/source/texk/dvipdfm-x/cs_type2.c +++ /dev/null @@ -1,808 +0,0 @@ -/* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - - Copyright (C) 2002-2020 by Jin-Hwan Cho and Shunsaku Hirata, - the dvipdfmx project team. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -*/ - -/* - * Type 2 Charstring support: - * Decode and encode Type 2 charstring - * - * All local/global subroutine calls in a given charstring is replace by the - * content of subroutine charstrings. We do this because some PostScript RIP - * may have problems with sparse subroutine array. Workaround for this is to - * re-order subroutine array so that no gap appears in the subroutine array, - * or put dummy charstrings that contains only `return' in the gap. However, - * re-ordering of subroutine is rather difficult for Type 2 charstrings due - * to the bias which depends on the total number of subroutines. Replacing - * callgsubr/callsubr calls with the content of the corresponding subroutine - * charstring may be more efficient than putting dummy subroutines in the - * case of subsetted font. Adobe distiller seems doing same thing. - * - * And also note that subroutine numbers within subroutines can depend on the - * content of operand stack as follows: - * - * ... l m callsubr << subr #(m+bias): n add callsubr >> ... - * - * I've not implemented the `random' operator which generates a pseudo-random - * number in the range (0, 1] and push them into argument stack. - * How pseudo-random sequences are generated is not documented in the Type 2 - * charstring spec.. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> - -/* fabs, sqrt ... */ -#include <math.h> - -#include "error.h" - -/* data types, limits */ -#include "cff_types.h" -#include "cff_limits.h" - -#include "cs_type2.h" - -#define CS_TYPE2_DEBUG_STR "Type2 Charstring Parser" -#define CS_TYPE2_DEBUG 5 - -/* decoder/encoder status codes */ -#define CS_BUFFER_ERROR -3 -#define CS_STACK_ERROR -2 -#define CS_PARSE_ERROR -1 -#define CS_PARSE_OK 0 -#define CS_PARSE_END 1 -#define CS_SUBR_RETURN 2 -#define CS_CHAR_END 3 - -static int status = CS_PARSE_ERROR; - -#define DST_NEED(a,b) {if ((a) < (b)) { status = CS_BUFFER_ERROR ; return ; }} -#define SRC_NEED(a,b) {if ((a) < (b)) { status = CS_PARSE_ERROR ; return ; }} -#define NEED(a,b) {if ((a) < (b)) { status = CS_STACK_ERROR ; return ; }} - -/* hintmask and cntrmask need number of stem zones */ -static int num_stems = 0; -static int phase = 0; - -/* subroutine nesting */ -static int nest = 0; - -/* advance width */ -static int have_width = 0; -static double width = 0.0; - -/* - * Standard Encoding Accented Characters: - * Optional four arguments for endchar. See, CFF spec., p.35. - * This is obsolete feature and is no longer supported. - */ -#if 0 -/* adx ady bchar achar endchar */ -static double seac[4] = {0.0, 0.0, 0.0, 0.0}; -#endif - -/* Operand stack and Transient array */ -static int stack_top = 0; -static double arg_stack[CS_ARG_STACK_MAX]; -static double trn_array[CS_TRANS_ARRAY_MAX]; - -/* - * Type 2 CharString encoding - */ - -/* - * 1-byte CharString operaotrs: - * cs_escape is first byte of two-byte operator - */ - -/* RESERVED 0 */ -#define cs_hstem 1 -/* RESERVED 2 */ -#define cs_vstem 3 -#define cs_vmoveto 4 -#define cs_rlineto 5 -#define cs_hlineto 6 -#define cs_vlineto 7 -#define cs_rrcurveto 8 -/* cs_closepath 9 : TYPE1 */ -#define cs_callsubr 10 -#define cs_return 11 -#define cs_escape 12 -/* cs_hsbw 13 : TYPE1 */ -#define cs_endchar 14 -/* RESERVED 15 */ -/* RESERVED 16 */ -/* RESERVED 17 */ -#define cs_hstemhm 18 -#define cs_hintmask 19 -#define cs_cntrmask 20 -#define cs_rmoveto 21 -#define cs_hmoveto 22 -#define cs_vstemhm 23 -#define cs_rcurveline 24 -#define cs_rlinecurve 25 -#define cs_vvcurveto 26 -#define cs_hhcurveto 27 -/* SHORTINT 28 : first byte of shortint*/ -#define cs_callgsubr 29 -#define cs_vhcurveto 30 -#define cs_hvcurveto 31 - -/* - * 2-byte CharString operaotrs: - * "dotsection" is obsoleted in Type 2 charstring. - */ - -#define cs_dotsection 0 -/* cs_vstem3 1 : TYPE1 */ -/* cs_hstem3 2 : TYPE1 */ -#define cs_and 3 -#define cs_or 4 -#define cs_not 5 -/* cs_seac 6 : TYPE1 */ -/* cs_sbw 7 : TYPE1 */ -/* RESERVED 8 */ -#define cs_abs 9 -#define cs_add 10 -#define cs_sub 11 -#define cs_div 12 -/* RESERVED 13 */ -#define cs_neg 14 -#define cs_eq 15 -/* cs_callothersubr 16 : TYPE1 */ -/* cs_pop 17 : TYPE1 */ -#define cs_drop 18 -/* RESERVED 19 */ -#define cs_put 20 -#define cs_get 21 -#define cs_ifelse 22 -#define cs_random 23 -#define cs_mul 24 -/* RESERVED 25 */ -#define cs_sqrt 26 -#define cs_dup 27 -#define cs_exch 28 -#define cs_index 29 -#define cs_roll 30 -/* cs_setcurrentpoint 31 : TYPE1 */ -/* RESERVED 32 */ -/* RESERVED 33 */ -#define cs_hflex 34 -#define cs_flex 35 -#define cs_hflex1 36 -#define cs_flex1 37 - -/* - * clear_stack() put all operands sotred in operand stack to dest. - */ -static void -clear_stack (card8 **dest, card8 *limit) -{ - int i; - - for (i = 0; i < stack_top; i++) { - double value; - int ivalue; - value = arg_stack[i]; - /* Nearest integer value */ - ivalue = (int) floor(value+0.5); - if (value >= 0x8000L || value <= (-0x8000L - 1)) { - /* - * This number cannot be represented as a single operand. - * We must use `a b mul ...' or `a c div' to represent large values. - */ - ERROR("%s: Argument value too large. (This is bug)", CS_TYPE2_DEBUG_STR); - } else if (fabs(value - ivalue) > 3.0e-5) { - /* 16.16-bit signed fixed value */ - DST_NEED(limit, *dest + 5); - *(*dest)++ = 255; - ivalue = (int) floor(value); /* mantissa */ - *(*dest)++ = (ivalue >> 8) & 0xff; - *(*dest)++ = ivalue & 0xff; - ivalue = (int)((value - ivalue) * 0x10000l); /* fraction */ - *(*dest)++ = (ivalue >> 8) & 0xff; - *(*dest)++ = ivalue & 0xff; - /* Everything else are integers. */ - } else if (ivalue >= -107 && ivalue <= 107) { - DST_NEED(limit, *dest + 1); - *(*dest)++ = ivalue + 139; - } else if (ivalue >= 108 && ivalue <= 1131) { - DST_NEED(limit, *dest + 2); - ivalue = 0xf700u + ivalue - 108; - *(*dest)++ = (ivalue >> 8) & 0xff; - *(*dest)++ = ivalue & 0xff; - } else if (ivalue >= -1131 && ivalue <= -108) { - DST_NEED(limit, *dest + 2); - ivalue = 0xfb00u - ivalue - 108; - *(*dest)++ = (ivalue >> 8) & 0xff; - *(*dest)++ = ivalue & 0xff; - } else if (ivalue >= -32768 && ivalue <= 32767) { /* shortint */ - DST_NEED(limit, *dest + 3); - *(*dest)++ = 28; - *(*dest)++ = (ivalue >> 8) & 0xff; - *(*dest)++ = (ivalue) & 0xff; - } else { /* Shouldn't come here */ - ERROR("%s: Unexpected error.", CS_TYPE2_DEBUG_STR); - } - } - - stack_top = 0; /* clear stack */ - - return; -} - -/* - * Single byte operators: - * Path construction, Operator for finishing a path, Hint operators. - * - * phase: - * 0: inital state - * 1: hint declaration, first stack-clearing operator appeared - * 2: in path construction - */ - -static void -do_operator1 (card8 **dest, card8 *limit, card8 **data, card8 *endptr) -{ - card8 op = **data; - - *data += 1; - - switch (op) { - case cs_hstemhm: - case cs_vstemhm: - /* charstring may have hintmask if above operator have seen */ - case cs_hstem: - case cs_vstem: - if (phase == 0 && (stack_top % 2)) { - have_width = 1; - width = arg_stack[0]; - } - num_stems += stack_top/2; - clear_stack(dest, limit); - DST_NEED(limit, *dest + 1); - *(*dest)++ = op; - phase = 1; - break; - case cs_hintmask: - case cs_cntrmask: - if (phase < 2) { - if (phase == 0 && (stack_top % 2)) { - have_width = 1; - width = arg_stack[0]; - } - num_stems += stack_top/2; - } - clear_stack(dest, limit); - DST_NEED(limit, *dest + 1); - *(*dest)++ = op; - if (num_stems > 0) { - int masklen = (num_stems + 7) / 8; - DST_NEED(limit, *dest + masklen); - SRC_NEED(endptr, *data + masklen); - memmove(*dest, *data, masklen); - *data += masklen; - *dest += masklen; - } - phase = 2; - break; - case cs_rmoveto: - if (phase == 0 && (stack_top % 2)) { - have_width = 1; - width = arg_stack[0]; - } - clear_stack(dest, limit); - DST_NEED(limit, *dest + 1); - *(*dest)++ = op; - phase = 2; - break; - case cs_hmoveto: - case cs_vmoveto: - if (phase == 0 && (stack_top % 2) == 0) { - have_width = 1; - width = arg_stack[0]; - } - clear_stack(dest, limit); - DST_NEED(limit, *dest + 1); - *(*dest)++ = op; - phase = 2; - break; - case cs_endchar: - if (stack_top == 1) { - have_width = 1; - width = arg_stack[0]; - clear_stack(dest, limit); - } else if (stack_top == 4 || stack_top == 5) { - WARN("\"seac\" character deprecated in Type 2 charstring."); - status = CS_PARSE_ERROR; - return; - } else if (stack_top > 0) { - WARN("%s: Operand stack not empty.", CS_TYPE2_DEBUG_STR); - } - DST_NEED(limit, *dest + 1); - *(*dest)++ = op; - status = CS_CHAR_END; - break; - /* above oprators are candidate for first stack-clearing operator */ - case cs_rlineto: - case cs_hlineto: - case cs_vlineto: - case cs_rrcurveto: - case cs_rcurveline: - case cs_rlinecurve: - case cs_vvcurveto: - case cs_hhcurveto: - case cs_vhcurveto: - case cs_hvcurveto: - if (phase < 2) { - WARN("%s: Broken Type 2 charstring.", CS_TYPE2_DEBUG_STR); - status = CS_PARSE_ERROR; - return; - } - clear_stack(dest, limit); - DST_NEED(limit, *dest + 1); - *(*dest)++ = op; - break; - /* all operotors above are stack-clearing operator */ - /* no output */ - case cs_return: - case cs_callgsubr: - case cs_callsubr: - ERROR("%s: Unexpected call(g)subr/return", CS_TYPE2_DEBUG_STR); - break; - default: - /* no-op ? */ - WARN("%s: Unknown charstring operator: 0x%02x", CS_TYPE2_DEBUG_STR, op); - status = CS_PARSE_ERROR; - break; - } - - return; -} - -/* - * Double byte operators: - * Flex, arithmetic, conditional, and storage operators. - * - * Following operators are not supported: - * random: How random ? - */ -static void -do_operator2 (card8 **dest, card8 *limit, card8 **data, card8 *endptr) -{ - card8 op; - - *data += 1; - - SRC_NEED(endptr, *data + 1); - - op = **data; - *data += 1; - - switch(op) { - case cs_dotsection: /* deprecated */ - WARN("Operator \"dotsection\" deprecated in Type 2 charstring."); - status = CS_PARSE_ERROR; - return; - case cs_hflex: - case cs_flex: - case cs_hflex1: - case cs_flex1: - if (phase < 2) { - WARN("%s: Broken Type 2 charstring.", CS_TYPE2_DEBUG_STR); - status = CS_PARSE_ERROR; - return; - } - clear_stack(dest, limit); - DST_NEED(limit, *dest + 2); - *(*dest)++ = cs_escape; - *(*dest)++ = op; - break; - /* all operator above are stack-clearing */ - /* no output */ - case cs_and: - NEED(stack_top, 2); - stack_top--; - if (arg_stack[stack_top] && arg_stack[stack_top-1]) { - arg_stack[stack_top-1] = 1.0; - } else { - arg_stack[stack_top-1] = 0.0; - } - break; - case cs_or: - NEED(stack_top, 2); - stack_top--; - if (arg_stack[stack_top] || arg_stack[stack_top-1]) { - arg_stack[stack_top-1] = 1.0; - } else { - arg_stack[stack_top-1] = 0.0; - } - break; - case cs_not: - NEED(stack_top, 1); - if (arg_stack[stack_top-1]) { - arg_stack[stack_top-1] = 0.0; - } else { - arg_stack[stack_top-1] = 1.0; - } - break; - case cs_abs: - NEED(stack_top, 1); - arg_stack[stack_top-1] = fabs(arg_stack[stack_top-1]); - break; - case cs_add: - NEED(stack_top, 2); - arg_stack[stack_top-2] += arg_stack[stack_top-1]; - stack_top--; - break; - case cs_sub: - NEED(stack_top, 2); - arg_stack[stack_top-2] -= arg_stack[stack_top-1]; - stack_top--; - break; - case cs_div: /* doesn't check overflow */ - NEED(stack_top, 2); - arg_stack[stack_top-2] /= arg_stack[stack_top-1]; - stack_top--; - break; - case cs_neg: - NEED(stack_top, 1); - arg_stack[stack_top-1] *= -1.0; - break; - case cs_eq: - NEED(stack_top, 2); - stack_top--; - if (arg_stack[stack_top] == arg_stack[stack_top-1]) { - arg_stack[stack_top-1] = 1.0; - } else { - arg_stack[stack_top-1] = 0.0; - } - break; - case cs_drop: - NEED(stack_top, 1); - stack_top--; - break; - case cs_put: - NEED(stack_top, 2); - { - int idx = (int)arg_stack[--stack_top]; - NEED(CS_TRANS_ARRAY_MAX, idx); - trn_array[idx] = arg_stack[--stack_top]; - } - break; - case cs_get: - NEED(stack_top, 1); - { - int idx = (int)arg_stack[stack_top-1]; - NEED(CS_TRANS_ARRAY_MAX, idx); - arg_stack[stack_top-1] = trn_array[idx]; - } - break; - case cs_ifelse: - NEED(stack_top, 4); - stack_top -= 3; - if (arg_stack[stack_top+1] > arg_stack[stack_top+2]) { - arg_stack[stack_top-1] = arg_stack[stack_top]; - } - break; - case cs_mul: - NEED(stack_top, 2); - arg_stack[stack_top-2] = arg_stack[stack_top-2] * arg_stack[stack_top-1]; - stack_top--; - break; - case cs_sqrt: - NEED(stack_top, 1); - arg_stack[stack_top-1] = sqrt(arg_stack[stack_top-1]); - break; - case cs_dup: - NEED(stack_top, 1); - NEED(CS_ARG_STACK_MAX, stack_top+1); - arg_stack[stack_top] = arg_stack[stack_top-1]; - stack_top++; - break; - case cs_exch: - NEED(stack_top, 2); - { - double save = arg_stack[stack_top-2]; - arg_stack[stack_top-2] = arg_stack[stack_top-1]; - arg_stack[stack_top-1] = save; - } - break; - case cs_index: - NEED(stack_top, 2); /* need two arguments at least */ - { - int idx = (int)arg_stack[stack_top-1]; - if (idx < 0) { - arg_stack[stack_top-1] = arg_stack[stack_top-2]; - } else { - NEED(stack_top, idx+2); - arg_stack[stack_top-1] = arg_stack[stack_top-idx-2]; - } - } - break; - case cs_roll: - NEED(stack_top, 2); - { - int N, J; - J = (int)arg_stack[--stack_top]; - N = (int)arg_stack[--stack_top]; - NEED(stack_top, N); - if (J > 0) { - J = J % N; - while (J-- > 0) { - double save = arg_stack[stack_top-1]; - int i = stack_top - 1; - while (i > stack_top-N) { - arg_stack[i] = arg_stack[i-1]; - i--; - } - arg_stack[i] = save; - } - } else { - J = (-J) % N; - while (J-- > 0) { - double save = arg_stack[stack_top-N]; - int i = stack_top - N; - while (i < stack_top-1) { - arg_stack[i] = arg_stack[i+1]; - i++; - } - arg_stack[i] = save; - } - } - } - break; - case cs_random: - WARN("%s: Charstring operator \"random\" found.", CS_TYPE2_DEBUG_STR); - NEED(CS_ARG_STACK_MAX, stack_top+1); - arg_stack[stack_top++] = 1.0; - break; - default: - /* no-op ? */ - WARN("%s: Unknown charstring operator: 0x0c%02x", CS_TYPE2_DEBUG_STR, op); - status = CS_PARSE_ERROR; - break; - } - - return; -} - -/* - * integer: - * exactly the same as the DICT encoding (except 29) - */ -static void -get_integer (card8 **data, card8 *endptr) -{ - int result = 0; - card8 b0 = **data, b1, b2; - - *data += 1; - - if (b0 == 28) { /* shortint */ - SRC_NEED(endptr, *data + 2); - b1 = **data; - b2 = *(*data+1); - result = b1*256+b2; - if (result > 0x7fff) - result -= 0x10000L; - *data += 2; - } else if (b0 >= 32 && b0 <= 246) { /* int (1) */ - result = b0 - 139; - } else if (b0 >= 247 && b0 <= 250) { /* int (2) */ - SRC_NEED(endptr, *data + 1); - b1 = **data; - result = (b0-247)*256+b1+108; - *data += 1; - } else if (b0 >= 251 && b0 <= 254) { - SRC_NEED(endptr, *data + 1); - b1 = **data; - result = -(b0-251)*256-b1-108; - *data += 1; - } else { - status = CS_PARSE_ERROR; - return; - } - - NEED(CS_ARG_STACK_MAX, stack_top+1); - arg_stack[stack_top++] = (double) result; - - return; -} - -/* - * Signed 16.16-bits fixed number for Type 2 charstring encoding - */ -static void -get_fixed (card8 **data, card8 *endptr) -{ - int ivalue; - double rvalue; - - *data += 1; - - SRC_NEED(endptr, *data + 4); - - ivalue = *(*data) * 0x100 + *(*data+1); - rvalue = (ivalue > 0x7fffL) ? (ivalue - 0x10000L) : ivalue; - ivalue = *(*data+2) * 0x100 + *(*data+3); - rvalue += ((double) ivalue) / 0x10000L; - - NEED(CS_ARG_STACK_MAX, stack_top+1); - arg_stack[stack_top++] = rvalue; - *data += 4; - - return; -} - -/* - * Subroutines: - * The bias for subroutine number is introduced in type 2 charstrings. - * - * subr: set to a pointer to the subroutine charstring. - * len: set to the length of subroutine charstring. - * subr_idx: CFF INDEX data that contains subroutines. - * id: biased subroutine number. - */ -static void -get_subr (card8 **subr, int *len, cff_index *subr_idx, int id) -{ - card16 count; - - if (subr_idx == NULL) - ERROR("%s: Subroutine called but no subroutine found.", CS_TYPE2_DEBUG_STR); - - count = subr_idx->count; - - /* Adding bias number */ - if (count < 1240) { - id += 107; - } else if (count < 33900) { - id += 1131; - } else { - id += 32768; - } - - if (id > count) - ERROR("%s: Invalid Subr index: %ld (max=%u)", CS_TYPE2_DEBUG_STR, id, count); - - *len = (subr_idx->offset)[id + 1] - (subr_idx->offset)[id]; - *subr = subr_idx->data + (subr_idx->offset)[id] - 1; - - return; -} - -/* - * NOTE: - * The Type 2 interpretation of a number encoded in five-bytes (those with - * an initial byte value of 255) differs from how it is interpreted in the - * Type 1 format. - */ - -static void -do_charstring (card8 **dest, card8 *limit, - card8 **data, card8 *endptr, - cff_index *gsubr_idx, cff_index *subr_idx) -{ - card8 b0 = 0, *subr; - int len; - - if (nest > CS_SUBR_NEST_MAX) - ERROR("%s: Subroutine nested too deeply.", CS_TYPE2_DEBUG_STR); - - nest++; - - while (*data < endptr && status == CS_PARSE_OK) { - b0 = **data; - if (b0 == 255) { /* 16-bit.16-bit fixed signed number */ - get_fixed(data, endptr); - } else if (b0 == cs_return) { - status = CS_SUBR_RETURN; - } else if (b0 == cs_callgsubr) { - if (stack_top < 1) { - status = CS_STACK_ERROR; - } else { - stack_top--; - get_subr(&subr, &len, gsubr_idx, (int) arg_stack[stack_top]); - if (*dest + len > limit) - ERROR("%s: Possible buffer overflow.", CS_TYPE2_DEBUG_STR); - do_charstring(dest, limit, &subr, subr + len, - gsubr_idx, subr_idx); - *data += 1; - } - } else if (b0 == cs_callsubr) { - if (stack_top < 1) { - status = CS_STACK_ERROR; - } else { - stack_top--; - get_subr(&subr, &len, subr_idx, (int) arg_stack[stack_top]); - if (limit < *dest + len) - ERROR("%s: Possible buffer overflow.", CS_TYPE2_DEBUG_STR); - do_charstring(dest, limit, &subr, subr + len, - gsubr_idx, subr_idx); - *data += 1; - } - } else if (b0 == cs_escape) { - do_operator2(dest, limit, data, endptr); - } else if (b0 < 32 && b0 != 28) { /* 19, 20 need mask */ - do_operator1(dest, limit, data, endptr); - } else if ((b0 <= 22 && b0 >= 27) || b0 == 31) { /* reserved */ - status = CS_PARSE_ERROR; /* not an error ? */ - } else { /* integer */ - get_integer(data, endptr); - } - } - - if (status == CS_SUBR_RETURN) { - status = CS_PARSE_OK; - } else if (status == CS_CHAR_END && *data < endptr) { - WARN("%s: Garbage after endchar.", CS_TYPE2_DEBUG_STR); - } else if (status < CS_PARSE_OK) { /* error */ - ERROR("%s: Parsing charstring failed: (status=%d, stack=%d)", - CS_TYPE2_DEBUG_STR, status, stack_top); - } - - nest--; - - return; -} - -static void -cs_parse_init (void) -{ - status = CS_PARSE_OK; - nest = 0; - phase = 0; - num_stems = 0; - stack_top = 0; -} - -/* - * Not just copying... - */ -int -cs_copy_charstring (card8 *dst, int dstlen, - card8 *src, int srclen, - cff_index *gsubr, cff_index *subr, - double default_width, double nominal_width, cs_ginfo *ginfo) -{ - card8 *save = dst; - - cs_parse_init(); - - width = 0.0; - have_width = 0; - - /* expand call(g)subrs */ - do_charstring(&dst, dst + dstlen, &src, src + srclen, gsubr, subr); - - if (ginfo) { - ginfo->flags = 0; /* not used */ - if (have_width) { - ginfo->wx = nominal_width + width; - } else { - ginfo->wx = default_width; - } - } - - return (int)(dst - save); -} |