--- loncom/xml/lonplot.pm 2008/05/26 10:51:42 1.142 +++ loncom/xml/lonplot.pm 2009/03/18 14:05:19 1.148.2.2 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Dynamic plot # -# $Id: lonplot.pm,v 1.142 2008/05/26 10:51:42 foxr Exp $ +# $Id: lonplot.pm,v 1.148.2.2 2009/03/18 14:05:19 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -496,7 +496,7 @@ my %axis_defaults = yformat => { default => 'on', test => sub {$_[0]=~/^(on|off|\d+(f|F|e|E))$/}, - description => 'X-axis number formatting', + description => 'Y-axis number formatting', edit_type => 'choice', choices => ['on', 'off', '2e', '2f'], }, @@ -757,6 +757,7 @@ sub get_font { $selected_font = $font_properties{$Apache::lonplot::plot{'fontface'}}; } if ($target eq 'tex' && defined($Apache::lonplot::plot{'texfont'})) { +# $selected_font = $font_properties{'classic'}; $size = $Apache::lonplot::plot{'texfont'}; } return ($size, $selected_font); @@ -819,6 +820,13 @@ sub parse_label { return $result; } +# +# Note that there are severe restrictions on font selection in the +# ps driver now. later in life Gnuplot is supposed to support +# utf-8 fonts in the posts script driver. When this happens, +# the tex entries with comments that include the word +# should be changed to print the correct glyphs rather than some +# approximation or fallback of what is intended. my %lookup = ( # Greek alphabet: @@ -888,31 +896,31 @@ my %lookup = '#134' => {'tex' => '{/Text \262}', 'web' => "\x{2020}"}, '#135' => {'tex' => '{/Text \263}', 'web' => "\x{2021}"}, '#136' => {'tex' => '\\\\^', 'web' => '\\\\^'}, - '#137' => {'tex' => '{/Text \275}', 'web' => "\x{2030}"}, - '#138' => {'tex' => 'S', 'web' => "\x{160}"}, # no S-caron in ps fonts. + '#137' => {'tex' => '%o', 'web' => "\x{2030}"}, # Per Mille + '#138' => {'tex' => 'S', 'web' => "\x{160}"}, # S-Caron '#139' => {'tex' => '<', 'web' => '<'}, - '#140' => {'tex' => '{/Text \352}', 'web' => "\x{152}"}, + '#140' => {'tex' => 'AE', 'web' => "\x{152}"}, # AE ligature '#145' => {'tex' => '\140', 'web' => "\x{2018}"}, '#146' => {'tex' => '\47', 'web' => "\x{2019}"}, - '#147' => {'tex' => '{/Text \252}', 'web' => "\x{201c}"}, - '#148' => {'tex' => '{/Text \315}', 'web' => '\\"'}, + '#147' => {'tex' => '\140\140', 'web' => "\x{201c}"}, # Left " + '#148' => {'tex' => '\47\47', 'web' => '\\"'}, # Right " '#149' => {'tex' => '{/Symbol \267}', 'web' => "\x{2022}"}, - '#150' => {'tex' => '{/Text \55}', 'web' => "\x{2013}"}, #Untested here en dash + '#150' => {'tex' => '{/Text \55}', 'web' => "\x{2013}"}, # en dash '#151' => {'tex' => '{/Symbol \55}', 'web' => "\x{2014}"}, # em dash - '#152' => {'tex' => '~', 'web' => '~'}, - '#153' => {'tex' => '{/Text \324}', 'web' => "\x{2122}"}, # trademark + '#152' => {'tex' => '\\\\~', 'web' => '\\\\~'}, + '#153' => {'tex' => '{/Symbol \324}', 'web' => "\x{2122}"}, # trademark # Accented letters, and other furreign language glyphs. '#154' => {'tex' => 's', 'web' => "\x{161}"}, # small s-caron no ps. '#155' => {'tex' => '>', 'web' => '\76'}, # > - '#156' => {'tex' => '{/Text \372}', 'web' => "\x{153}"}, # oe ligature. - '#159', => {'tex' => 'Y', 'web' => "\x{178}"}, # Y-umlaut - can't print + '#156' => {'tex' => '{/Text \366}', 'web' => "\x{153}"}, # oe ligature. + '#159', => {'tex' => 'Y', 'web' => "\x{178}"}, # Y-umlaut - can't print '(nbsp|#160)' => {'tex' => ' ', 'web' => ' '}, # non breaking space. '(iexcl|#161)' => {'tex' => '{/Text \241}', 'web' => "\x{a1}"}, # inverted ! '(cent|#162)' => {'tex' => '{/Text \242}', 'web' => "\x{a2}"}, # Cent currency. '(pound|#163)' => {'tex' => '{/Text \243}', 'web' => "\x{a3}"}, # GB Pound currency. - '(curren|#164)' => {'tex' => '{/Text \250}', 'web' => "\x{a4}"}, # Generic currency symb. + '(curren|#164)' => {'tex' => '{/ZapfDingbats \161}','web' => "\x{a4}"}, # Generic currency symb. '(yen|#165)' => {'tex' => '{/Text \245}', 'web' => "\x{a5}"}, # Yen currency. '(brvbar|#166)' => {'tex' => '{/Symbol \174}', 'web' => "\x{a6}"}, # Broken vert bar no print. '(sect|#167)' => {'tex' => '{\247}', 'web' => "\x{a7}"}, # Section symbol. @@ -921,20 +929,20 @@ my %lookup = '(ordf|#170)' => {'tex' => '{/Text \343}', 'web' => "\x{aa}"}, # Feminine ordinal. '(laquo|#171)' => {'tex' => '{/Text \253}', 'web' => "\x{ab}"}, # << quotes. '(not|#172)' => {'tex' => '\254', 'web' => "\x{ac}"}, # Logical not. - '(shy|#173)' => {'tex' => '-', 'web' => "\x{ad}"}, # soft hyphen. + '(shy|#173)' => {'tex' => '\255', 'web' => "\x{ad}"}, # soft hyphen. '(reg|#174)' => {'tex' => '{/Symbol \342}', 'web' => "\x{ae}"}, # Registered tm. - '(macr|#175)' => {'tex' => '^{-}', 'web' => "\x{af}"}, # 'naked' macron (overbar). - '(deg|#176)' => {'tex' => '{/Text \312}', 'web' => "\x{b0}"}, # Degree symbo.. + '(macr|#175)' => {'tex' => '^{\255}', 'web' => "\x{af}"}, # 'naked' macron (overbar). + '(deg|#176)' => {'tex' => '{/Text \260}', 'web' => "\x{b0}"}, # Degree symbo..` '(plusmn|#177)' => {'tex' => '{/Symbol \261}', 'web' => "\x{b1}"}, # +/- symbol. '(sup2|#178)' => {'tex' => '^2', 'web' => "\x{b2}"}, # Superscript 2. '(sup3|#179)' => {'tex' => '^3', 'web' => "\x{b3}"}, # Superscript 3. - '(acute|#180)' => {'tex' => '{/Text \302}', 'web' => "\x{b4}"}, # 'naked' acute accent. + '(acute|#180)' => {'tex' => '{/Text \222}', 'web' => "\x{b4}"}, # 'naked' acute accent. '(micro|#181)' => {'tex' => '{/Symbol \155}', 'web' => "\x{b5}"}, # Micro (small mu). '(para|#182)' => {'tex' => '{/Text \266}', 'web' => "\x{b6}"}, # Paragraph symbol. - '(middot|#183)' => {'tex' => '^.', 'web' => "\x{b7}"}, # middle dot (maybe text 267 is better)? + '(middot|#183)' => {'tex' => '\267', 'web' => "\x{b7}"}, # middle dot '(cedil|#184)' => {'tex' => '\233', 'web' => "\x{b8}"}, # 'naked' cedilla. '(sup1|#185)' => {'tex' => '^1', 'web' => "\x{b9}"}, # superscript 1. - '(ordm|#186)' => {'tex' => '\353', 'web' => "\x{ba}"}, # masculine ordinal. + '(ordm|#186)' => {'tex' => '{\260}', 'web' => "\x{ba}"}, # masculine ordinal. '(raquo|#187)', => {'tex' => '\273', 'web' => "\x{bb}"}, # Right angle quotes. '(frac14|#188)' => {'tex' => '\274', 'web' => "\x{bc}"}, # 1/4. '(frac12|#189)' => {'tex' => '\275', 'web' => "\x{bd}"}, # 1/2. @@ -992,7 +1000,7 @@ my %lookup = '(ntilde|#241)' => {'tex' => '\361', 'web' => "\x{f1}"}, # n tilde. '(ograve|#242)' => {'tex' => '\362', 'web' => "\x{f2}"}, # o grave. '(oacute|#243)' => {'tex' => '\363', 'web' => "\x{f3}"}, # o acute. - '(ocirc'|#244)' => {'tex' => '\364', 'web' => "\x{f4}"}, # o circumflex. + '(ocirc|#244)' => {'tex' => '\364', 'web' => "\x{f4}"}, # o circumflex. '(otilde|#245)' => {'tex' => '\365', 'web' => "\x{f5}"}, # o tilde. '(ouml|#246)' => {'tex' => '\366', 'web' => "\x{f6}"}, # o umlaut. '(divide|#247)' => {'tex' => '\367', 'web' => "\x{f7}"}, # division symbol @@ -1007,15 +1015,15 @@ my %lookup = # Latin extended A entities: - '(OElig|#338)' => {'tex' => '{/Text \352}', 'web' => "\x{152}"}, # OE ligature. - '(oelig|#339)' => {'tex' => '{/Text \372}', 'web' => "\x{153}"}, # oe ligature. + '(OElig|#338)' => {'tex' => '{/Text \326}', 'web' => "\x{152}"}, # OE ligature. + '(oelig|#339)' => {'tex' => '{/Text \366}', 'web' => "\x{153}"}, # oe ligature. '(Scaron|#352)' => {'tex' => 'S', 'web' => "\x{160}"}, # S caron no printable. '(scaron|#353)' => {'tex' => 's', 'web' => "\x{161}"}, # s caron no printable. '(Yuml|#376)' => {'tex' => 'Y', 'web' => "\x{178}"}, # Y umlaut - no printable. # Latin extended B. - '(fnof|#402)' => {'tex' =>'{/Symbol 246}', 'web' => "\x{192}"}, # f with little hook. + '(fnof|#402)' => {'tex' =>'{/Symbol \246}', 'web' => "\x{192}"}, # f with little hook. # Standalone accents: @@ -1030,30 +1038,30 @@ my %lookup = '(ensp|#8194)' => {'tex' => ' ', 'web' => "\x{2002}"}, # en space. '(emsp|#8195)' => {'tex' => ' ', 'web' => "\x{2003}"}, # em space. '(thinsp|#8201)' => {'tex' => ' ', 'web' => "\x{2009}"}, # thin space. - '(zwnj|#8204)' => {'tex' => '', 'web' => "\x{200c}"}, # Zero width non joiner. - '(zwj|#8205)' => {'tex' => '', 'web' => "\x{200d}"}, # Zero width joiner. - '(lrm|#8206)' => {'tex' => '', 'web' => "\x{200e}"}, # Left to right mark - '(rlm|#8207)' => {'tex' => '', 'web' => "\x{200f}"}, # right to left mark. + '(zwnj|#8204)' => {'tex' => ' ', 'web' => "\x{200c}"}, # Zero width non joiner. + '(zwj|#8205)' => {'tex' => ' ', 'web' => "\x{200d}"}, # Zero width joiner. + '(lrm|#8206)' => {'tex' => ' ', 'web' => "\x{200e}"}, # Left to right mark + '(rlm|#8207)' => {'tex' => ' ', 'web' => "\x{200f}"}, # right to left mark. '(ndash|#8211)' => {'tex' => '{/Text \55}', 'web' => "\x{2013}"}, # en dash. '(mdash|#8212)' => {'tex' => '{/Symbol \55}', 'web' => "\x{2014}"}, # em dash. '(lsquo|#8216)' => {'tex' => '{/Text \140}', 'web' => "\x{2018}"}, # Left single quote. - '(rsquo|#8217)' => {'tex' => '{/Symbol \242}', 'web' => "\x{2019}"}, # Right single quote. - '(sbquo|#8218)' => {'tex' => ',', 'web' => "\x{201a}"}, # Single low-9 quote. - '(ldquo|#8220)' => {'tex' => '{/Text \252}', 'web' => "\x{201c}"}, # Left double quote. - '(rdquo|#8221)' => {'tex' => '{/Text \272}', 'web' => "\x{201d}"}, # Right double quote. - '(bdquo|#8222)' => {'tex' => '{/Text \271}', 'web' => "\x{201e}"}, # Double low-9 quote. - '(dagger|#8224)' => {'tex' => '{/Text \262}', 'web' => "\x{2020}"}, # Is this a dagger I see before me now? - '(Dagger|#8225)' => {'tex' => '{/Text \263}', 'web' => "\x{2021}"}, # it's handle pointing towards my heart? + '(rsquo|#8217)' => {'tex' => '\47', 'web' => "\x{2019}"}, # Right single quote. + '(sbquo|#8218)' => {'tex' => '\54', 'web' => "\x{201a}"}, # Single low-9 quote. + '(ldquo|#8220)' => {'tex' => '\42', 'web' => "\x{201c}"}, # Left double quote. + '(rdquo|#8221)' => {'tex' => '\42', 'web' => "\x{201d}"}, # Right double quote. + '(bdquo|#8222)' => {'tex' => ',', 'web' => "\x{201e}"}, # Double low-9 quote. + '(dagger|#8224)' => {'tex' => '+', 'web' => "\x{2020}"}, # Is this a dagger I see before me now? + '(Dagger|#8225)' => {'tex' => '\261', 'web' => "\x{2021}"}, # it's handle pointing towards my heart? '(bull|#8226)' => {'tex' => '\267', 'web' => "\x{2022}"}, # Bullet. - '(hellep|#8230)' => {'tex' => '{/Text \274}', 'web' => "\x{2026}"}, # Ellipses. - '(permil|#8240)' => {'tex' => '{/Text \275}', 'web' => "\x{2031}"}, # Per mille. + '(hellep|#8230)' => {'tex' => '{/Symbol \274}', 'web' => "\x{2026}"}, # Ellipses. + '(permil|#8240)' => {'tex' => '%_o', 'web' => "\x{2031}"}, # Per mille. '(prime|#8242)' => {'tex' => '\264', 'web' => "\x{2032}"}, # Prime. '(Prime|#8243)' => {'tex' => '{/Symbol \262}', 'web' => "\x{2033}"}, # double prime. - '(lsaquo|#8249)' => {'tex' => '{/Text \254}', 'web' => "\x{2039}"}, # < quote. - '(rsaquo|#8250)' => {'tex' => '{/Text \255}', 'web' => "\x{2040}"}, # > quote. + '(lsaquo|#8249)' => {'tex' => '<', 'web' => "\x{2039}"}, # < quote. + '(rsaquo|#8250)' => {'tex' => '\74', 'web' => "\x{203a}"}, # > quote. '(oline|#8254)' => {'tex' => '{/Symbol \140}', 'web' => "\x{203e}"}, # Overline. '(frasl|#8260)' => {'tex' => '/', 'web' => "\x{2044}"}, # Fraction slash. - '(euro|#8364)' => {'tex' => '{/Symbol \240}', 'web' => "\x{20a0}"}, # Euro currency. + '(euro|#8364)' => {'tex' => '{/Symbol \240}', 'web' => "\x{20ac}"}, # Euro currency. # Letter like symbols. @@ -1084,10 +1092,11 @@ my %lookup = '(empty|#8709)' => {'tex' => '{/Symbol \306}', 'web' => "\x{2205}"}, # Null set. '(nabla|#8711)' => {'tex' => '{/Symbol \321}', 'web' => "\x{2207}"}, # Gradient e.g. '(isin|#8712)' => {'tex' => '{/Symbol \316}', 'web' => "\x{2208}"}, # Element of the set. + '(notin|#8713)' => {'tex' => '{/Symbol \317}', 'web' => "\x{2209}"}, # Not an element of '(ni|#8715)' => {'tex' => '{/Symbol \47}', 'web' => "\x{220b}"}, # Contains as a member '(prod|#8719)' => {'tex' => '{/Symbol \325}', 'web' => "\x{220f}"}, # Product '(sum|#8721)' => {'tex' => '{/Symbol \345}', 'web' => "\x{2211}"}, # Sum of. - '(minus|#8722)' => {'tex' => '-', 'web' => "\x{2212}"}, # - sign. + '(minus|#8722)' => {'tex' => '{/Symbol \55}', 'web' => "\x{2212}"}, # - sign. '(lowast|#8727)' => {'tex' => '*', 'web' => "\x{2217}"}, # * '(radic|#8730)' => {'tex' => '{/Symbol \326}', 'web' => "\x{221a}"}, # Square root. '(prop|#8733)' => {'tex' => '{/Symbol \265}', 'web' => "\x{221d}"}, # Proportional to. @@ -1098,10 +1107,15 @@ my %lookup = '(cap|#8745)' => {'tex' => '{/Symbol \307}', 'web' => "\x{2229}"}, # Set intersection. '(cup|#8746)' => {'tex' => '{/Symbol \310}', 'web' => "\x{222a}"}, # Set union. '(int|8747)' => {'tex' => '{/Symbol \362}', 'web' => "\x{222b}"}, # Integral. - '(there4|#8756)' => {'tex' => '{/Symbol \134}', 'web' => "\x{2234}"}, # Therefore triple dots. - '(sim|#8764)' => {'tex' => '~', 'web' => "\x{223c}"}, # Simlar to. - '(cong|#8773)' => {'tex' => '{/Symbol \100}', 'web' => "\x{2245}"}, # Congruent to/with. - '(asymp|#8776)' => {'tex' => '{/Symbol \278}', 'web' => "\x{2248}"}, # Asymptotic to. + + # Some gnuplot guru will have to explain to me why the next three + # require the extra slashes... else they print very funkily. + + '(there4|#8756)' => {'tex' => '{/Symbol \\\134}', 'web' => "\x{2234}"}, # Therefore triple dots. + '(sim|#8764)' => {'tex' => '\\\176', 'web' => "\x{223c}"}, # Simlar to. + '(cong|#8773)' => {'tex' => '{/Symbol \\\100}','web' => "\x{2245}"}, # Congruent to/with. + + '(asymp|#8776)' => {'tex' => '{/Symbol \273}', 'web' => "\x{2248}"}, # Asymptotic to. '(ne|#8800)' => {'tex' => '{/Symbol \271}', 'web' => "\x{2260}"}, # not equal to. '(equiv|#8801)' => {'tex' => '{/Symbol \272}', 'web' => "\x{2261}"}, # Equivalent to. '(le|8804)' => {'tex' => '{/Symbol \243}', 'web' => "\x{2264}"}, # Less than or equal to. @@ -1122,8 +1136,12 @@ my %lookup = '(rceil|8969)' => {'tex' => '{/Symbol \371}', 'web' => "\x{2309}"}, # Right ceiling. '(lfloor|8970)' => {'tex' => '{/Symbol \353}', 'web' => "\x{230a}"}, # Left floor. '(rfloor|8971)' => {'tex' => '{/Symbol \373}', 'web' => "\x{230b}"}, # Right floor. - '(lang|9001)' => {'tex' => '{/Symbol \341}', 'web' => "\x{2329}"}, # Left angle bracket. - '(rang|9002)' => {'tex' => '{/Symbol \361}', 'web' => "\x{232a}"}, # Right angle bracket. + + # The gnuplot png font evidently does not have the big angle brackets at + # positions 0x2329, 0x232a so use ordinary brackets. + + '(lang|9001)' => {'tex' => '{/Symbol \341}', 'web' => '<'}, # Left angle bracket. + '(rang|9002)' => {'tex' => '{/Symbol \361}', 'web' => '>'}, # Right angle bracket. # Gemoetric shapes. @@ -1344,6 +1362,7 @@ sub start_function { my $function = &Apache::lonxml::get_all_text("/function",$parser, $style); $function = &Apache::run::evaluate($function,$safeeval,$$parstack[-1]); + $function=~s/\^/\*\*/gs; $curves[-1]->{'function'} = $function; } elsif ($target eq 'edit') { $result .= &Apache::edit::tag_start($target,$token,'Gnuplot compatible curve function'); @@ -1414,7 +1433,7 @@ sub start_data { } # complain if the number of data points is not the same as # in previous sets of data. - if (($curves[-1]->{'data'}) && ($#data != $#{@{$curves[-1]->{'data'}->[0]}})){ + if (($curves[-1]->{'data'}) && ($#data != $#{$curves[-1]->{'data'}->[0]})){ &Apache::lonxml::warning ('Number of data points is not consistent with previous '. 'number of data points'); @@ -1570,6 +1589,8 @@ sub write_gnuplot_file { $gnuplot_input .= $fontsize; $gnuplot_input .= "\nset output \"/home/httpd/perl/tmp/". &unescape($filename).".eps\"\n"; + $gnuplot_input .= "set encoding iso_8859_1\n"; # Get access to extended font. + } # cartesian or polar plot? if (lc($Apache::lonplot::plot{'plottype'}) eq 'polar') { @@ -1656,20 +1677,36 @@ sub write_gnuplot_file { $gnuplot_input .= ( $xtics{'mirror'} eq 'on'?"mirror ":"nomirror "); $gnuplot_input .= "$xtics{'start'}, "; $gnuplot_input .= "$xtics{'increment'}, "; - $gnuplot_input .= "$xtics{'end'}\n"; + $gnuplot_input .= "$xtics{'end'} "; + if ($target eq 'tex') { + $gnuplot_input .= 'font "Helvetica,22"'; # Needed in iso 8859-1 enc. + } + $gnuplot_input .= "\n"; if ($xtics{'minorfreq'} != 0) { $gnuplot_input .= "set mxtics ".$xtics{'minorfreq'}."\n"; } + } else { + if ($target eq 'tex') { + $gnuplot_input .= 'set xtics font "Helvetica,22"'."\n"; # needed in iso 8859-1 enc + } } if (%ytics) { $gnuplot_input .= "set ytics $ytics{'location'} "; $gnuplot_input .= ( $ytics{'mirror'} eq 'on'?"mirror ":"nomirror "); $gnuplot_input .= "$ytics{'start'}, "; $gnuplot_input .= "$ytics{'increment'}, "; - $gnuplot_input .= "$ytics{'end'}\n"; + $gnuplot_input .= "$ytics{'end'} "; + if ($target eq 'tex') { + $gnuplot_input .= 'font "Helvetica,22"'; # Needed in iso-8859-1 encoding. + } + $gnuplot_input .= "\n"; if ($ytics{'minorfreq'} != 0) { $gnuplot_input .= "set mytics ".$ytics{'minorfreq'}."\n"; } + } else { + if ($target eq 'tex') { + $gnuplot_input .= 'set ytics font "Helvetica,22"'."\n"; # Needed for iso 8859-1 enc. + } } # axis if (%axis) {