1# -*- mode: Perl -*-
2# /=====================================================================\ #
3# |  color                                                              | #
4# | Implementation for LaTeXML                                          | #
5# |=====================================================================| #
6# | Part of LaTeXML:                                                    | #
7# |  Public domain software, produced as part of work done by the       | #
8# |  United States Government & not subject to copyright in the US.     | #
9# |---------------------------------------------------------------------| #
10# | Bruce Miller <bruce.miller@nist.gov>                        #_#     | #
11# | http://dlmf.nist.gov/LaTeXML/                              (o o)    | #
12# \=========================================================ooo==U==ooo=/ #
13package LaTeXML::Package::Pool;
14use strict;
15use warnings;
16use LaTeXML::Package;
17
18#======================================================================
19# Ignorable options (mostly drivers)
20foreach my $option (qw(monochrome debugshow dvipdf dvipdfm dvipdfmx pdftex xetex
21  dvipsone dviwindo emtex dviwin textures pctexps pctexwin
22  pctexhp pctex32 truetex tcidvi vtex nodvipsnames
23  usenames)) {
24  DeclareOption($option, undef); }
25
26# options that want the dvipsnam definitions
27foreach my $option (qw(dvips xdvi oztex dvipsnames)) {
28  DeclareOption($option, sub { InputDefinitions('dvipsnam', type => 'def'); return; }); }
29
30#======================================================================
31# change this to something like ConvertColor... Oh, already have that?
32sub ParseColor {
33  my ($model, $spec) = @_;
34  $model = ToString($model) if ref $model; $model = lc($model) if $model;
35  $spec = ToString($spec) if ref $spec;
36  $spec =~ s/^\s+//;
37  $spec =~ s/\s+$//;
38  if ($spec =~ /^\{\s*(.*?)\s*\}$/) {    # Trim
39    $spec = $1; }
40  my $color;
41  if ($model && $model eq 'named') {
42    $spec = 'named_' . $spec; $model = undef; }
43  if ($model) {
44    $color = Color($model, ($spec =~ /,/ ? split(/\s*,\s*/, $spec) : split(/\s+/, $spec)))->toCore;
45    Error('unexpected', $spec, $STATE->getStomach,
46      "Don't understand '$spec' as a color") unless $color; }
47  else {
48    $color = LookupColor($spec);
49    if (!$color) {
50      AssignValue('color_' . $spec => Black);
51      Error('unexpected', $spec, $STATE->getStomach,
52        "Can't find color named '$spec'; assuming Black"); } }
53  return $color || Black; }
54
55#======================================================================
56# are there default named colors that we should be loading?
57
58DefPrimitive('\definecolor{}{}{}', sub {
59    my ($stomach, $name, $model, $spec) = @_;
60    ($name, $model, $spec) = map { $_ && Expand($_) } $name, $model, $spec;
61    DefColor(ToString($name), ParseColor($model, $spec));
62    Box(undef, undef, undef, Invocation(T_CS('\definecolor'), $name, $model, $spec)); });
63
64# I don't think this is quite right, but...
65# [I think we need do do something like "named_color_".$name
66#  and corresponding changes to getColor, as well?
67# What are we supposed to do with $dmodel???
68DefPrimitive('\DefineNamedColor{}{}{}{}', sub {
69    my ($stomach, $dmodel, $name, $model, $spec) = @_;
70    ($dmodel, $name, $model, $spec) = map { $_ && Expand($_) } $dmodel, $name, $model, $spec;
71    DefColor('named_' . ToString($name), ParseColor($model, $spec));
72    Box(undef, undef, undef, Invocation(T_CS('\DefineNamedColor'), $dmodel, $name, $model, $spec)); });
73
74# \color{name} or \color[model]{spec}
75DefPrimitive('\color[]{}', sub {
76    my ($stomach, $model, $spec) = @_;
77    ($model, $spec) = map { $_ && Expand($_) } $model, $spec;
78    my $color = ParseColor($model, $spec);
79    AssignValue('preambleTextcolor', $color) if LookupValue('inPreamble');
80    MergeFont(color => $color);
81    Box(undef, undef, undef,
82      Invocation(T_CS('\color'), T_OTHER('rgb'),    # Revert to ACTUAL color, not user's name
83        T_OTHER(join(',', $color->rgb->components)))); });
84
85#\pagecolor{name} or \pagecolor[model]{spec}
86DefPrimitive('\pagecolor[]{}', sub {
87    my ($stomach, $model, $spec) = @_;
88    ($model, $spec) = map { $_ && Expand($_) } $model, $spec;
89    my $color = ParseColor($model, $spec);
90    MergeFont(background => $color);
91    Box(undef, undef, undef, Invocation(T_CS('\pagecolor'), $model, $spec)); });
92
93# NOTE: the color in effect at \begin{document} will be returned by \normalcolor
94# Do other font properties act this way?
95DefPrimitive('\normalcolor', sub {
96    my $color = (LookupValue('preambleTextcolor') || Black());
97    MergeFont(color => $color);
98    Box(undef, undef, undef, T_CS('\normalcolor')); });
99
100#\textcolor{name}{text} or \textcolor[model]{spec}{text}
101DefMacro('\textcolor[]{}{}', '{\ifx.#1.\color{#2}\else\color[#1]{#2}\fi#3}');
102
103#\colorbox{name}{text} or \colorbox[model]{spec}{text}
104DefMacro('\colorbox[]{}{}', '\hbox{\ifx.#1.\pagecolor{#2}\else\pagecolor[#1]{#2}\fi#3}');
105
106#\fcolorbox{name}{text} or \fcolorbox[model]{spec}{text}
107DefConstructor('\fcolorbox[]{}{} Undigested',
108  "<ltx:text framed='rectangle' framecolor='#framecolor'"
109    . " _noautoclose='1'>#text</ltx:text>",
110  bounded => 1, mode => 'text',
111  afterDigest => sub {
112    my ($stomach, $whatsit) = @_;
113    my ($model, $fspec, $bspec, $text) = $whatsit->getArgs;
114    $whatsit->setProperty(framecolor => ParseColor($model, $fspec));
115    MergeFont(background => ParseColor($model, $bspec));
116    $whatsit->setProperty(text => Digest($text)); });
117
118#********************************************************************************
119# Low-level stuff; redefined from LaTeX stubs
120
121# Not sure what \current@color should return... the string form?
122# \current@color
123# Similarly, I'm not sure what set@color needs to do that isn't redundant
124DefMacroI('\set@color', undef, '');
125
126DefMacroI('\color@begingroup', undef, '\begingroup');
127DefMacroI('\color@endgroup',   undef, '\endgroup');
128DefMacroI('\color@setgroup',   undef, '\begingroup\set@color');
129DefMacroI('\color@hbox',       undef, '\hbox\bgroup\color@begingroup');
130DefMacroI('\color@vbox',       undef, '\vbox\bgroup\color@begingroup');
131DefMacroI('\color@endbox',     undef, '\color@endgroup\egroup');
132
133#********************************************************************************
134# Default defined colors
135RawTeX(<<'EOTeX');
136\definecolor{black}{rgb}{0,0,0}
137\definecolor{white}{rgb}{1,1,1}
138\definecolor{red}{rgb}{1,0,0}
139\definecolor{green}{rgb}{0,1,0}
140\definecolor{blue}{rgb}{0,0,1}
141\definecolor{cyan}{cmyk}{1,0,0,0}
142\definecolor{magenta}{cmyk}{0,1,0,0}
143\definecolor{yellow}{cmyk}{0,0,1,0}
144EOTeX
145#********************************************************************************
146ProcessOptions();
1471;
148