summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/pdf/pdfcolorstack.w
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/pdf/pdfcolorstack.w')
-rw-r--r--Build/source/texk/web2c/luatexdir/pdf/pdfcolorstack.w386
1 files changed, 386 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/pdf/pdfcolorstack.w b/Build/source/texk/web2c/luatexdir/pdf/pdfcolorstack.w
new file mode 100644
index 00000000000..1e472c7f713
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/pdf/pdfcolorstack.w
@@ -0,0 +1,386 @@
+% pdfcolorstack.w
+%
+% Copyright 2009-2010 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/>.
+
+@ @c
+#include "ptexlib.h"
+
+static const char _svn_version[] =
+ "$Id: pdfcolorstack.w 3571 2010-04-02 13:50:45Z taco $"
+ "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/pdf/pdfcolorstack.w $";
+
+
+@* Color Stack and Matrix Transformation Support.
+
+
+@ In the following array and especially stack data structures are used.
+
+They have the following properties:
+
+ \item{-} They automatically grow dynamically.
+ \item{-} The size never decreases.
+ \item{-} The variable with name ending in "size" contains the number how many
+ entries the data structure can hold.
+ \item{-} The variable with name ending in "used" contains the number of
+ actually used entries.
+ \item{-} Memory of strings in stack entries must be allocated and
+ freed if the stack is cleared.
+
+
+@ Color Stack
+@c
+#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"
+/* |literal_mode|s, see pdftex.web */
+#define SET_ORIGIN 0
+#define DIRECT_PAGE 1
+#define DIRECT_ALWAYS 2
+
+/* remember shipout mode: page/form */
+boolean page_mode;
+
+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;
+
+@ Initialization is done, if the color stacks are used,
+ |init_colorstacks()| is defined as macro to avoid unnecessary
+ procedure calls.
+@c
+#define init_colorstacks() if (colstacks_size == 0) colstacks_first_init();
+
+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;
+}
+
+@ @c
+int colorstackused(void)
+{
+ init_colorstacks();
+ return colstacks_used;
+}
+
+@ |newcolorstack()|
+ A new color stack is setup with the given parameters.
+ The stack number is returned or -1 in case of error (no room).
+@c
+int newcolorstack(int s, int literal_mode, boolean page_start)
+{
+ colstack_type *colstack;
+ int colstack_num;
+ char *str;
+
+ init_colorstacks();
+
+ /* make room */
+ if (colstacks_used == MAX_COLORSTACKS) {
+ return -1;
+ }
+ if (colstacks_used == colstacks_size) {
+ colstacks_size += STACK_INCREMENT;
+ /* 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);
+ }
+ /* claim new color stack */
+ colstack_num = colstacks_used++;
+ colstack = &colstacks[colstack_num];
+ /* 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;
+ str = makecstring(s);
+ if (*str == 0) {
+ colstack->page_current = NULL;
+ colstack->form_current = NULL;
+ colstack->form_init = NULL;
+ } else {
+ colstack->page_current = xstrdup(str);
+ colstack->form_current = xstrdup(str);
+ colstack->form_init = xstrdup(str);
+ }
+ free(str);
+ return colstack_num;
+}
+
+@ @c
+#define get_colstack(n) (&colstacks[n])
+
+@ Puts a string on top of the string pool and updates |pool_ptr|.
+@c
+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;
+}
+
+@ @c
+int colorstackset(int colstack_no, str_number s)
+{
+ colstack_type *colstack = get_colstack(colstack_no);
+
+ if (page_mode) {
+ xfree(colstack->page_current);
+ colstack->page_current = makecstring(s);
+ } else {
+ xfree(colstack->form_current);
+ colstack->form_current = makecstring(s);
+ }
+ return colstack->literal_mode;
+}
+
+@ @c
+int colorstackcurrent(int colstack_no)
+{
+ colstack_type *colstack = get_colstack(colstack_no);
+
+ if (page_mode) {
+ put_cstring_on_str_pool(colstack->page_current);
+ } else {
+ put_cstring_on_str_pool(colstack->form_current);
+ }
+ return colstack->literal_mode;
+}
+
+@ @c
+static int colorstackpush(int colstack_no, str_number s)
+{
+ colstack_type *colstack = get_colstack(colstack_no);
+ char *str;
+ if (page_mode) {
+ if (colstack->page_used == colstack->page_size) {
+ colstack->page_size += STACK_INCREMENT;
+ colstack->page_stack = 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;
+ colstack->form_stack = 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;
+}
+
+@ @c
+int colorstackpop(int colstack_no)
+{
+ colstack_type *colstack = get_colstack(colstack_no);
+
+ if (page_mode) {
+ if (colstack->page_used == 0) {
+ pdftex_warn("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) {
+ pdftex_warn("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;
+}
+
+@ @c
+void colorstackpagestart(void)
+{
+ int i, j;
+ colstack_type *colstack;
+
+ if (page_mode) {
+ /* see procedure |pdf_out_colorstack_startpage| */
+ 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);
+ }
+ }
+}
+
+@ @c
+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;
+}
+
+
+@ @c
+void pdf_out_colorstack(PDF pdf, halfword p)
+{
+ int old_setting;
+ str_number s;
+ int cmd;
+ int stack_no;
+ int literal_mode;
+ cmd = pdf_colorstack_cmd(p);
+ stack_no = pdf_colorstack_stack(p);
+ literal_mode = 0;
+ if (stack_no >= colorstackused()) {
+ tprint_nl("");
+ tprint("Color stack ");
+ print_int(stack_no);
+ tprint(" is not initialized for use!");
+ tprint_nl("");
+ 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);
+ }
+}
+
+@ @c
+void pdf_out_colorstack_startpage(PDF pdf)
+{
+ int i;
+ int max;
+ int start_status;
+ int literal_mode;
+ str_number s;
+ i = 0;
+ 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);
+ }
+ }
+ incr(i);
+ }
+}