1 /*
2 * Copyright (c) 2014-2019 Hayaki Saito
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy of
5 * this software and associated documentation files (the "Software"), to deal in
6 * the Software without restriction, including without limitation the rights to
7 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8 * the Software, and to permit persons to whom the Software is furnished to do so,
9 * subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21
22 #include "config.h"
23
24 #if STDC_HEADERS
25 # include <stdio.h>
26 # include <stdlib.h>
27 #endif /* STDC_HEADERS */
28 #if HAVE_ASSERT_H
29 # include <assert.h>
30 #endif /* HAVE_ASSERT_H */
31
32 #include <sixel.h>
33 #include "output.h"
34
35
36 /* create new output context object */
37 SIXELAPI SIXELSTATUS
sixel_output_new(sixel_output_t ** output,sixel_write_function fn_write,void * priv,sixel_allocator_t * allocator)38 sixel_output_new(
39 sixel_output_t /* out */ **output,
40 sixel_write_function /* in */ fn_write,
41 void /* in */ *priv,
42 sixel_allocator_t /* in */ *allocator)
43 {
44 SIXELSTATUS status = SIXEL_FALSE;
45 size_t size;
46
47 if (allocator == NULL) {
48 status = sixel_allocator_new(&allocator, NULL, NULL, NULL, NULL);
49 if (SIXEL_FAILED(status)) {
50 goto end;
51 }
52 } else {
53 sixel_allocator_ref(allocator);
54 }
55 size = sizeof(sixel_output_t) + SIXEL_OUTPUT_PACKET_SIZE * 2;
56
57 *output = (sixel_output_t *)sixel_allocator_malloc(allocator, size);
58 if (*output == NULL) {
59 sixel_helper_set_additional_message(
60 "sixel_output_new: sixel_allocator_malloc() failed.");
61 status = SIXEL_BAD_ALLOCATION;
62 goto end;
63 }
64
65 (*output)->ref = 1;
66 (*output)->has_8bit_control = 0;
67 (*output)->has_sdm_glitch = 0;
68 (*output)->has_gri_arg_limit = 1;
69 (*output)->skip_dcs_envelope = 0;
70 (*output)->palette_type = SIXEL_PALETTETYPE_AUTO;
71 (*output)->fn_write = fn_write;
72 (*output)->save_pixel = 0;
73 (*output)->save_count = 0;
74 (*output)->active_palette = (-1);
75 (*output)->node_top = NULL;
76 (*output)->node_free = NULL;
77 (*output)->priv = priv;
78 (*output)->pos = 0;
79 (*output)->penetrate_multiplexer = 0;
80 (*output)->encode_policy = SIXEL_ENCODEPOLICY_AUTO;
81 (*output)->allocator = allocator;
82
83 status = SIXEL_OK;
84
85 end:
86 return status;
87 }
88
89
90 /* deprecated: create an output object */
91 SIXELAPI sixel_output_t *
sixel_output_create(sixel_write_function fn_write,void * priv)92 sixel_output_create(sixel_write_function fn_write, void *priv)
93 {
94 SIXELSTATUS status = SIXEL_FALSE;
95 sixel_output_t *output = NULL;
96
97 status = sixel_output_new(&output, fn_write, priv, NULL);
98 if (SIXEL_FAILED(status)) {
99 goto end;
100 }
101
102 end:
103 return output;
104 }
105
106
107 /* destroy output context object */
108 SIXELAPI void
sixel_output_destroy(sixel_output_t * output)109 sixel_output_destroy(sixel_output_t *output)
110 {
111 sixel_allocator_t *allocator;
112
113 if (output) {
114 allocator = output->allocator;
115 sixel_allocator_free(allocator, output);
116 sixel_allocator_unref(allocator);
117 }
118 }
119
120
121 /* increase reference count of output context object (thread-unsafe) */
122 SIXELAPI void
sixel_output_ref(sixel_output_t * output)123 sixel_output_ref(sixel_output_t *output)
124 {
125 /* TODO: be thread-safe */
126 ++output->ref;
127 }
128
129
130 /* decrease reference count of output context object (thread-unsafe) */
131 SIXELAPI void
sixel_output_unref(sixel_output_t * output)132 sixel_output_unref(sixel_output_t *output)
133 {
134 /* TODO: be thread-safe */
135 if (output) {
136 assert(output->ref > 0);
137 output->ref--;
138 if (output->ref == 0) {
139 sixel_output_destroy(output);
140 }
141 }
142 }
143
144
145 /* get 8bit output mode which indicates whether it uses C1 control characters */
146 SIXELAPI int
sixel_output_get_8bit_availability(sixel_output_t * output)147 sixel_output_get_8bit_availability(sixel_output_t *output)
148 {
149 return output->has_8bit_control;
150 }
151
152
153 /* set 8bit output mode state */
154 SIXELAPI void
sixel_output_set_8bit_availability(sixel_output_t * output,int availability)155 sixel_output_set_8bit_availability(sixel_output_t *output, int availability)
156 {
157 output->has_8bit_control = availability;
158 }
159
160
161 /* set whether limit arguments of DECGRI('!') to 255 */
162 SIXELAPI void
sixel_output_set_gri_arg_limit(sixel_output_t * output,int value)163 sixel_output_set_gri_arg_limit(
164 sixel_output_t /* in */ *output, /* output context */
165 int /* in */ value) /* 0: don't limit arguments of DECGRI
166 1: limit arguments of DECGRI to 255 */
167 {
168 output->has_gri_arg_limit = value;
169 }
170
171
172 /* set GNU Screen penetration feature enable or disable */
173 SIXELAPI void
sixel_output_set_penetrate_multiplexer(sixel_output_t * output,int penetrate)174 sixel_output_set_penetrate_multiplexer(sixel_output_t *output, int penetrate)
175 {
176 output->penetrate_multiplexer = penetrate;
177 }
178
179
180 /* set whether we skip DCS envelope */
181 SIXELAPI void
sixel_output_set_skip_dcs_envelope(sixel_output_t * output,int skip)182 sixel_output_set_skip_dcs_envelope(sixel_output_t *output, int skip)
183 {
184 output->skip_dcs_envelope = skip;
185 }
186
187
188 /* set palette type: RGB or HLS */
189 SIXELAPI void
sixel_output_set_palette_type(sixel_output_t * output,int palettetype)190 sixel_output_set_palette_type(sixel_output_t *output, int palettetype)
191 {
192 output->palette_type = palettetype;
193 }
194
195
196 /* set encodeing policy: auto, fast or size */
197 SIXELAPI void
sixel_output_set_encode_policy(sixel_output_t * output,int encode_policy)198 sixel_output_set_encode_policy(sixel_output_t *output, int encode_policy)
199 {
200 output->encode_policy = encode_policy;
201 }
202
203 /* emacs Local Variables: */
204 /* emacs mode: c */
205 /* emacs tab-width: 4 */
206 /* emacs indent-tabs-mode: nil */
207 /* emacs c-basic-offset: 4 */
208 /* emacs End: */
209 /* vim: set expandtab ts=4 sts=4 sw=4 : */
210 /* EOF */
211