summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/pdf/pdfcolorstack.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/pdf/pdfcolorstack.c')
-rw-r--r--Build/source/texk/web2c/luatexdir/pdf/pdfcolorstack.c357
1 files changed, 357 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/pdf/pdfcolorstack.c b/Build/source/texk/web2c/luatexdir/pdf/pdfcolorstack.c
new file mode 100644
index 00000000000..fbb88692fe9
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/pdf/pdfcolorstack.c
@@ -0,0 +1,357 @@
+/*
+
+Copyright 2009-2011 Taco Hoekwater <taco@luatex.org>
+
+This file is part of LuaTeX.
+
+LuaTeX 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.
+
+LuaTeX 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 Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU General Public License along
+with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "ptexlib.h"
+
+/*tex
+
+ This module implements color stack support. The following array and
+ especially stack data structures are used.
+
+ \startitemize
+ \startitem
+ They automatically grow dynamically.
+ \stopitem
+ \startitem
+ The size never decreases.
+ \stopitem
+ \startitem
+ The variable with name ending in "size" contains the number how many
+ entries the data structure can hold.
+ \stopitem
+ \startitem
+ The variable with name ending in "used" contains the number of
+ actually used entries.
+ \stopitem
+ \startitem
+ Memory of strings in stack entries must be allocated and freed if the
+ stack is cleared.
+ \stopitem
+ \stopitemize
+
+*/
+
+#define MAX_COLORSTACKS 32768
+
+/*
+ The colorstack number is stored in two bytes (info field of the node);
+ condition (newcolorstack): |MAX_COLORSTACKS mod STACK_INCREMENT = 0|
+*/
+
+#define COLOR_DEFAULT "0 g 0 G"
+
+typedef struct {
+ char **page_stack;
+ char **form_stack;
+ char *page_current;
+ char *form_current;
+ char *form_init;
+ int page_size;
+ int form_size;
+ int page_used;
+ int form_used;
+ int literal_mode;
+ boolean page_start;
+} colstack_type;
+
+static colstack_type *colstacks = NULL;
+static int colstacks_size = 0;
+static int colstacks_used = 0;
+
+/*tex
+
+ Initialization is done, if the color stacks are used, |init_colorstacks()| is
+ defined as macro to avoid unnecessary procedure calls.
+
+*/
+
+#define init_colorstacks() if (colstacks_size == 0) colstacks_first_init();
+
+static void colstacks_first_init(void)
+{
+ colstacks_size = STACK_INCREMENT;
+ colstacks = xtalloc((unsigned) colstacks_size, colstack_type);
+ colstacks_used = 1;
+ colstacks[0].page_stack = NULL;
+ colstacks[0].form_stack = NULL;
+ colstacks[0].page_size = 0;
+ colstacks[0].form_size = 0;
+ colstacks[0].page_used = 0;
+ colstacks[0].form_used = 0;
+ colstacks[0].page_current = xstrdup(COLOR_DEFAULT);
+ colstacks[0].form_current = xstrdup(COLOR_DEFAULT);
+ colstacks[0].form_init = xstrdup(COLOR_DEFAULT);
+ colstacks[0].literal_mode = direct_always;
+ colstacks[0].page_start = true;
+}
+
+int colorstackused(void)
+{
+ init_colorstacks();
+ return colstacks_used;
+}
+
+/*tex
+
+ A new color stack is setup with the given parameters. The stack number is
+ returned or -1 in case of error (no room).
+
+*/
+
+int newcolorstack(const char *str, int literal_mode, boolean page_start)
+{
+ colstack_type *colstack;
+ int colstack_num;
+ init_colorstacks();
+ /*tex Make room: */
+ if (colstacks_used == MAX_COLORSTACKS) {
+ return -1;
+ }
+ if (colstacks_used == colstacks_size) {
+ colstacks_size += STACK_INCREMENT;
+ /*tex
+ If |(MAX_COLORSTACKS mod STACK_INCREMENT = 0)| then we don't
+ need to check the case that size overruns |MAX_COLORSTACKS|.
+ */
+ colstacks = xreallocarray(colstacks, colstack_type, (unsigned) colstacks_size);
+ }
+ /*tex Claim new color stack. */
+ colstack_num = colstacks_used++;
+ colstack = &colstacks[colstack_num];
+ /*tex Configure the new color stack. */
+ colstack->page_stack = NULL;
+ colstack->form_stack = NULL;
+ colstack->page_size = 0;
+ colstack->page_used = 0;
+ colstack->form_size = 0;
+ colstack->form_used = 0;
+ colstack->literal_mode = literal_mode;
+ colstack->page_start = page_start;
+ colstack->page_current = NULL;
+ colstack->form_current = NULL;
+ colstack->form_init = NULL;
+ if (str) {
+ colstack->page_current = xstrdup(str);
+ colstack->form_current = xstrdup(str);
+ colstack->form_init = xstrdup(str);
+ }
+ return colstack_num;
+}
+
+#define get_colstack(n) (&colstacks[n])
+
+/*tex Put a string on top of the string pool and updates |pool_ptr|. */
+
+static void put_cstring_on_str_pool(char *str)
+{
+ int save_selector = selector;
+ selector = new_string;
+ if (str == NULL || *str == 0) {
+ return;
+ }
+ tprint(str);
+ selector = save_selector;
+}
+
+static int colorstackset(int colstack_no, str_number s)
+{
+ colstack_type *colstack = get_colstack(colstack_no);
+
+ if (global_shipping_mode == SHIPPING_PAGE) {
+ xfree(colstack->page_current);
+ colstack->page_current = makecstring(s);
+ } else {
+ xfree(colstack->form_current);
+ colstack->form_current = makecstring(s);
+ }
+ return colstack->literal_mode;
+}
+
+int colorstackcurrent(int colstack_no)
+{
+ colstack_type *colstack = get_colstack(colstack_no);
+
+ if (global_shipping_mode == SHIPPING_PAGE) {
+ put_cstring_on_str_pool(colstack->page_current);
+ } else {
+ put_cstring_on_str_pool(colstack->form_current);
+ }
+ return colstack->literal_mode;
+}
+
+static int colorstackpush(int colstack_no, str_number s)
+{
+ colstack_type *colstack = get_colstack(colstack_no);
+ char *str;
+ if (global_shipping_mode == SHIPPING_PAGE) {
+ if (colstack->page_used == colstack->page_size) {
+ colstack->page_size += STACK_INCREMENT;
+ xretalloc(colstack->page_stack, (unsigned) colstack->page_size, char *);
+ }
+ colstack->page_stack[colstack->page_used++] = colstack->page_current;
+ str = makecstring(s);
+ if (*str == 0) {
+ colstack->page_current = NULL;
+ } else {
+ colstack->page_current = xstrdup(str);
+ }
+ free(str);
+ } else {
+ if (colstack->form_used == colstack->form_size) {
+ colstack->form_size += STACK_INCREMENT;
+ xretalloc(colstack->form_stack, (unsigned) colstack->form_size, char *);
+ }
+ colstack->form_stack[colstack->form_used++] = colstack->form_current;
+ str = makecstring(s);
+ if (*str == 0) {
+ colstack->form_current = NULL;
+ } else {
+ colstack->form_current = xstrdup(str);
+ }
+ free(str);
+ }
+ return colstack->literal_mode;
+}
+
+int colorstackpop(int colstack_no)
+{
+ colstack_type *colstack = get_colstack(colstack_no);
+ if (global_shipping_mode == SHIPPING_PAGE) {
+ if (colstack->page_used == 0) {
+ formatted_warning("pdf backend","pop empty color page stack %u",(unsigned int) colstack_no);
+ return colstack->literal_mode;
+ }
+ xfree(colstack->page_current);
+ colstack->page_current = colstack->page_stack[--colstack->page_used];
+ put_cstring_on_str_pool(colstack->page_current);
+ } else {
+ if (colstack->form_used == 0) {
+ formatted_warning("pdf backend","pop empty color form stack %u",(unsigned int) colstack_no);
+ return colstack->literal_mode;
+ }
+ xfree(colstack->form_current);
+ colstack->form_current = colstack->form_stack[--colstack->form_used];
+ put_cstring_on_str_pool(colstack->form_current);
+ }
+ return colstack->literal_mode;
+}
+
+void colorstackpagestart(void)
+{
+ int i, j;
+ colstack_type *colstack;
+ if (global_shipping_mode == SHIPPING_PAGE) {
+ return;
+ }
+ for (i = 0; i < colstacks_used; i++) {
+ colstack = &colstacks[i];
+ for (j = 0; j < colstack->form_used; j++) {
+ xfree(colstack->form_stack[j]);
+ }
+ colstack->form_used = 0;
+ xfree(colstack->form_current);
+ if (colstack->form_init == NULL) {
+ colstack->form_current = NULL;
+ } else {
+ colstack->form_current = xstrdup(colstack->form_init);
+ }
+ }
+}
+
+int colorstackskippagestart(int colstack_no)
+{
+ colstack_type *colstack = get_colstack(colstack_no);
+ if (!colstack->page_start) {
+ return 1;
+ }
+ if (colstack->page_current == NULL) {
+ return 0;
+ }
+ if (strcmp(COLOR_DEFAULT, colstack->page_current) == 0) {
+ return 2;
+ }
+ return 0;
+}
+
+void pdf_out_colorstack(PDF pdf, halfword p)
+{
+ int old_setting;
+ str_number s;
+ int cmd = pdf_colorstack_cmd(p);
+ int stack_no = pdf_colorstack_stack(p);
+ int literal_mode = 0;
+ if (stack_no >= colorstackused()) {
+ formatted_warning("pdf backend","color stack %u is not initialized",(unsigned int) stack_no);
+ return;
+ }
+ switch (cmd) {
+ case colorstack_set:
+ case colorstack_push:
+ old_setting = selector;
+ selector = new_string;
+ show_token_list(token_link(pdf_colorstack_data(p)), null, -1);
+ selector = old_setting;
+ s = make_string();
+ if (cmd == colorstack_set)
+ literal_mode = colorstackset(stack_no, s);
+ else
+ literal_mode = colorstackpush(stack_no, s);
+ if (str_length(s) > 0)
+ pdf_literal(pdf, s, literal_mode, false);
+ flush_str(s);
+ return;
+ break;
+ case colorstack_pop:
+ literal_mode = colorstackpop(stack_no);
+ break;
+ case colorstack_current:
+ literal_mode = colorstackcurrent(stack_no);
+ break;
+ default:
+ break;
+ }
+ if (cur_length > 0) {
+ s = make_string();
+ pdf_literal(pdf, s, literal_mode, false);
+ flush_str(s);
+ }
+}
+
+void pdf_out_colorstack_startpage(PDF pdf)
+{
+ int start_status;
+ int literal_mode;
+ str_number s;
+ int i = 0;
+ int max = colorstackused();
+ while (i < max) {
+ start_status = colorstackskippagestart(i);
+ if (start_status == 0) {
+ literal_mode = colorstackcurrent(i);
+ if (cur_length > 0) {
+ s = make_string();
+ pdf_literal(pdf, s, literal_mode, false);
+ flush_str(s);
+ }
+ }
+ i++;
+ }
+}