diff --git a/manual/luatex-callbacks.tex b/manual/luatex-callbacks.tex index ddeeb05b1b49916057391734bee115ef39881a93..62a37c5bce1b1b3e46ee08cecb6314afc36bf09c 100644 --- a/manual/luatex-callbacks.tex +++ b/manual/luatex-callbacks.tex @@ -852,6 +852,17 @@ end This callback replaces the code that prints \LUATEX's when a file is closed like the \type {)} for regular files. +\subsection{\type {call_edit}} + +\startfunctioncall +function(filename,linenumber) +end +\stopfunctioncall + +This callback replaces the call to an external editor when \quote{E} is pressed +in reply to an error message. Processing will end immediately after the callback +returns control to the main program. + \section{PDF-related callbacks} \subsection{\type {finish_pdffile}} diff --git a/manual/luatex-math.tex b/manual/luatex-math.tex index 8e0c771196d959625cf565562157a0df21a7eb0f..b6634f840f995b71d6ee56a4b4dca90effd944ce 100644 --- a/manual/luatex-math.tex +++ b/manual/luatex-math.tex @@ -38,6 +38,99 @@ be used as numeric values, so you can write code like this: \fi \fi \stoptyping +Sometimes you won't get what you expect so a bit of explanation might help to +understand what happens. When math is parsed and expanded it gets turned into a +linked list. In a second pass the formula will be build. This has to do with the +fact that in order to determine the automatically chosen sizes (in for instance +fractions) following content can influence preceding sizes. A side effect of this +is for instance that one cannot change the definition of a font family (and +thereby reusing numbers) because the number that got used is stored and used in +the second pass (so changing \type {\fam 12} mid|-|formula spoils over to +preceding use of that family). + +The style switching primitives like \type {\textstyle} are turned into nodes so +the styles set there are frozen. The \type {\mathchoice} primitive results in +four lists being constructed of which one is used in the second pass. The fact +that some automatic styles are not yet known also means that the \type +{\mathstyle} primitive expands to the current style which can of course be +different from the one really used. It's a snapshot of the first pass state. As a +consequence in the following example you get a style number (first pass) typeset +that can actually differ from the used style (second pass). In the case of a math +choice used ungrouped, the chosen style is used after the choice too, unless you +group. + +\startbuffer[1] + [a:\mathstyle]\quad + \bgroup + \mathchoice + {\bf \scriptstyle (x:d :\mathstyle)} + {\bf \scriptscriptstyle (x:t :\mathstyle)} + {\bf \scriptscriptstyle (x:s :\mathstyle)} + {\bf \scriptscriptstyle (x:ss:\mathstyle)} + \egroup + \quad[b:\mathstyle]\quad + \mathchoice + {\bf \scriptstyle (y:d :\mathstyle)} + {\bf \scriptscriptstyle (y:t :\mathstyle)} + {\bf \scriptscriptstyle (y:s :\mathstyle)} + {\bf \scriptscriptstyle (y:ss:\mathstyle)} + \quad[c:\mathstyle]\quad + \bgroup + \mathchoice + {\bf \scriptstyle (z:d :\mathstyle)} + {\bf \scriptscriptstyle (z:t :\mathstyle)} + {\bf \scriptscriptstyle (z:s :\mathstyle)} + {\bf \scriptscriptstyle (z:ss:\mathstyle)} + \egroup + \quad[d:\mathstyle] +\stopbuffer + +\startbuffer[2] + [a:\mathstyle]\quad + \begingroup + \mathchoice + {\bf \scriptstyle (x:d :\mathstyle)} + {\bf \scriptscriptstyle (x:t :\mathstyle)} + {\bf \scriptscriptstyle (x:s :\mathstyle)} + {\bf \scriptscriptstyle (x:ss:\mathstyle)} + \endgroup + \quad[b:\mathstyle]\quad + \mathchoice + {\bf \scriptstyle (y:d :\mathstyle)} + {\bf \scriptscriptstyle (y:t :\mathstyle)} + {\bf \scriptscriptstyle (y:s :\mathstyle)} + {\bf \scriptscriptstyle (y:ss:\mathstyle)} + \quad[c:\mathstyle]\quad + \begingroup + \mathchoice + {\bf \scriptstyle (z:d :\mathstyle)} + {\bf \scriptscriptstyle (z:t :\mathstyle)} + {\bf \scriptscriptstyle (z:s :\mathstyle)} + {\bf \scriptscriptstyle (z:ss:\mathstyle)} + \endgroup + \quad[d:\mathstyle] +\stopbuffer + +\typebuffer[1] + +% \typebuffer[2] + +This gives: + +\blank $\displaystyle \getbuffer[1]$ \blank +\blank $\textstyle \getbuffer[1]$ \blank + +Using \type {\begingroup} \unknown\ \type {\endgroup} instead gives: + +\blank $\displaystyle \getbuffer[2]$ \blank +\blank $\textstyle \getbuffer[2]$ \blank + +This might look wrong but it's just a side effect of \type {\mathstyle} expanding +to the current (first pass) style and the number being injected in the list that +gets converted in the second pass. It all makes sense and it illustrates the +importance of grouping. In fact, the math choice style being effective afterwards +has advantages. It would be hard to get it otherwise. + \subsection{\type {\Ustack}} There are a few math commands in \TEX\ where the style that will be used is not @@ -469,7 +562,12 @@ math font Cambria, but were useful enough to be added. There are two extra math parameters \type {\Umathnolimitsupfactor} and \type {\Umathnolimitsubfactor} that were added to provide some control over how limits are spaced (for example the position of super and subscripts after integral -operators). They relate to an extra parameter \type {\mathnolimitsmode}. +operators). They relate to an extra parameter \type {\mathnolimitsmode}. The half +corrections are what happens when scripts are placed on above and below. The +problem with italic corrections is that officially that correction italic is used +for above|/|below placement while advanced kerns are used for placement at the +right end. The question is: how often is this implemented, and if so, does the +kerns assume correction too. Anyway, with this parameter one can control it. \starttabulate[|l|ck1|ck1|ck1|ck1|ck1|ck1|] \NC @@ -490,29 +588,30 @@ operators). They relate to an extra parameter \type {\mathnolimitsmode}. \NC \tttf 8000 \NC \NR \NC \bf superscript - \NC +ic/2 - \NC font \NC 0 + \NC font \NC 0 \NC 0 + \NC +ic/2 \NC 0 \NC \NR \NC \bf subscript - \NC -ic/2 + \NC -ic \NC font \NC 0 \NC -ic/2 - \NC -ic + \NC -ic/2 \NC 8000ic/1000 \NC \NR \stoptabulate When the mode is set to one, the math parameters are used. This way a macro package writer can decide what looks best. Given the current state of fonts in -\CONTEXT\ we currently use 0 for the superscript and 750 for the subscripts. -Positive values are used for both parameters but the subscript shifts to the -left. A \type {\mathnolimitsmode} larger that 15 is considered to be a factor -for the subscript correction. This feature can be handy when experimenting. +\CONTEXT\ we currently use mode 1 with factor 0 for the superscript and 750 for +the subscripts. Positive values are used for both parameters but the subscript +shifts to the left. A \type {\mathnolimitsmode} larger that 15 is considered to +be a factor for the subscript correction. This feature can be handy when +experimenting. \section{Math spacing setting} diff --git a/manual/luatex-nodes.tex b/manual/luatex-nodes.tex index fd0b47c7290d279c80b0c73a2b5866946dffd4a0..7495e6a61828fea2417538dab72f423b3fd5bc6c 100644 --- a/manual/luatex-nodes.tex +++ b/manual/luatex-nodes.tex @@ -739,8 +739,13 @@ Possible mode values are: \NC 0 \NC setorigin \NC \NR \NC 1 \NC page \NC \NR \NC 2 \NC direct \NC \NR +\NC 3 \NC raw \NC \NR \stoptabulate +The higher the number, the less checking and the more you can run into troubles. +Especially the \type {raw} variant can produce bad \PDF\ so you can best check +what you generate. + \subsubsubsection{pdf_refobj whatsits} \starttabulate[|lT|l|p|] diff --git a/manual/luatex.pdf b/manual/luatex.pdf index 563339d2678dc6bcef74a0ea86cb0588997d5b09..9fa91f4fc30a0cf2962f9d2eaee9e66eb19b1986 100644 Binary files a/manual/luatex.pdf and b/manual/luatex.pdf differ diff --git a/manual/luatex.tex b/manual/luatex.tex index 75e63c9bb329117930b8c449dd3fbab80ede033a..74b2a60c8fa2ca43053421f23f0e95e4d5086874 100644 --- a/manual/luatex.tex +++ b/manual/luatex.tex @@ -12,7 +12,7 @@ \dontcomplain \startdocument - [version=0.98.4, + [version=0.99, status=pre-release] \component luatex-titlepage diff --git a/source/texk/web2c/luatexdir/font/texfont.w b/source/texk/web2c/luatexdir/font/texfont.w index e68deac84ade915bc8524c89b030859fe7447355..9b6c0cd6bfeb63396c01956b3e3f9cf7c4abd029 100644 --- a/source/texk/web2c/luatexdir/font/texfont.w +++ b/source/texk/web2c/luatexdir/font/texfont.w @@ -267,18 +267,25 @@ charinfo *copy_charinfo(charinfo * ci) x = ci->top_left_math_kerns; co->top_left_math_kerns = x; if (x > 0) { - co->top_left_math_kern_array = - xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); + co->top_left_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); for (k = 0; k < co->top_left_math_kerns; k++) { co->top_left_math_kern_array[(2 * k)] = ci->top_left_math_kern_array[(2 * k)]; co->top_left_math_kern_array[(2 * k) + 1] = ci->top_left_math_kern_array[(2 * k) + 1]; } } + x = ci->bottom_left_math_kerns; + co->bottom_left_math_kerns = x; + if (x > 0) { + co->bottom_left_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); + for (k = 0; k < co->bottom_left_math_kerns; k++) { + co->bottom_left_math_kern_array[(2 * k)] = ci->bottom_left_math_kern_array[(2 * k)]; + co->bottom_left_math_kern_array[(2 * k) + 1] = ci->bottom_left_math_kern_array[(2 * k) + 1]; + } + } x = ci->top_right_math_kerns; co->top_right_math_kerns = x; if (x > 0) { - co->top_right_math_kern_array = - xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); + co->top_right_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); for (k = 0; k < co->top_right_math_kerns; k++) { co->top_right_math_kern_array[(2 * k)] = ci->top_right_math_kern_array[(2 * k)]; co->top_right_math_kern_array[(2 * k) + 1] = ci->top_right_math_kern_array[(2 * k) + 1]; @@ -287,23 +294,12 @@ charinfo *copy_charinfo(charinfo * ci) x = ci->bottom_right_math_kerns; co->bottom_right_math_kerns = x; if (x > 0) { - co->bottom_right_math_kern_array = - xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); + co->bottom_right_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); for (k = 0; k < co->bottom_right_math_kerns; k++) { co->bottom_right_math_kern_array[(2 * k)] = ci->bottom_right_math_kern_array[(2 * k)]; co->bottom_right_math_kern_array[(2 * k) + 1] = ci->bottom_right_math_kern_array[(2 * k) + 1]; } } - x = ci->bottom_left_math_kerns; - co->bottom_left_math_kerns = x; - if (x > 0) { - co->bottom_left_math_kern_array = - xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); - for (k = 0; k < co->bottom_left_math_kerns; k++) { - co->bottom_left_math_kern_array[(2 * k)] = ci->bottom_left_math_kern_array[(2 * k)]; - co->bottom_left_math_kern_array[(2 * k) + 1] = ci->bottom_left_math_kern_array[(2 * k) + 1]; - } - } return co; } @@ -652,10 +648,10 @@ int get_charinfo_math_kerns(charinfo * ci, int id) k = ci->top_left_math_kerns; } else if (id == bottom_left_kern) { k = ci->bottom_left_math_kerns; - } else if (id == bottom_right_kern) { - k = ci->bottom_right_math_kerns; } else if (id == top_right_kern) { k = ci->top_right_math_kerns; + } else if (id == bottom_right_kern) { + k = ci->bottom_right_math_kerns; } else { confusion("get_charinfo_math_kerns"); } @@ -674,25 +670,22 @@ void add_charinfo_math_kern(charinfo * ci, int id, scaled ht, scaled krn) ci->top_left_math_kerns++; } else if (id == bottom_left_kern) { k = ci->bottom_left_math_kerns; - do_realloc(ci->bottom_left_math_kern_array, ((k + 1) * 2), - sizeof(scaled)); + do_realloc(ci->bottom_left_math_kern_array, ((k + 1) * 2), sizeof(scaled)); ci->bottom_left_math_kern_array[(2 * (k))] = ht; ci->bottom_left_math_kern_array[(2 * (k)) + 1] = krn; ci->bottom_left_math_kerns++; - } else if (id == bottom_right_kern) { - k = ci->bottom_right_math_kerns; - do_realloc(ci->bottom_right_math_kern_array, ((k + 1) * 2), - sizeof(scaled)); - ci->bottom_right_math_kern_array[(2 * (k))] = ht; - ci->bottom_right_math_kern_array[(2 * (k)) + 1] = krn; - ci->bottom_right_math_kerns++; } else if (id == top_right_kern) { k = ci->top_right_math_kerns; - do_realloc(ci->top_right_math_kern_array, ((k + 1) * 2), - sizeof(scaled)); + do_realloc(ci->top_right_math_kern_array, ((k + 1) * 2), sizeof(scaled)); ci->top_right_math_kern_array[(2 * (k))] = ht; ci->top_right_math_kern_array[(2 * (k)) + 1] = krn; ci->top_right_math_kerns++; + } else if (id == bottom_right_kern) { + k = ci->bottom_right_math_kerns; + do_realloc(ci->bottom_right_math_kern_array, ((k + 1) * 2), sizeof(scaled)); + ci->bottom_right_math_kern_array[(2 * (k))] = ht; + ci->bottom_right_math_kern_array[(2 * (k)) + 1] = krn; + ci->bottom_right_math_kerns++; } else { confusion("add_charinfo_math_kern"); } @@ -715,17 +708,17 @@ static void dump_math_kerns(charinfo * ci) dump_int(ci->bottom_left_math_kern_array[(2 * k)]); dump_int(ci->bottom_left_math_kern_array[(2 * k) + 1]); } - l = ci->bottom_right_math_kerns; + l = ci->top_right_math_kerns; dump_int(l); for (k = 0; k < l; k++) { - dump_int(ci->bottom_right_math_kern_array[(2 * k)]); - dump_int(ci->bottom_right_math_kern_array[(2 * k) + 1]); + dump_int(ci->top_right_math_kern_array[(2 * k)]); + dump_int(ci->top_right_math_kern_array[(2 * k) + 1]); } - l = ci->top_right_math_kerns; + l = ci->bottom_right_math_kerns; dump_int(l); for (k = 0; k < l; k++) { - dump_int(ci->bottom_left_math_kern_array[(2 * k)]); - dump_int(ci->bottom_left_math_kern_array[(2 * k) + 1]); + dump_int(ci->bottom_right_math_kern_array[(2 * k)]); + dump_int(ci->bottom_right_math_kern_array[(2 * k) + 1]); } } @@ -737,8 +730,7 @@ static void undump_math_kerns(charinfo * ci) undump_int(x); ci->top_left_math_kerns = x; if (x > 0) - ci->top_left_math_kern_array = - xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); + ci->top_left_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); for (k = 0; k < ci->top_left_math_kerns; k++) { undump_int(x); ci->top_left_math_kern_array[(2 * k)] = (scaled) x; @@ -748,8 +740,7 @@ static void undump_math_kerns(charinfo * ci) undump_int(x); ci->bottom_left_math_kerns = x; if (x > 0) - ci->bottom_left_math_kern_array = - xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); + ci->bottom_left_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); for (k = 0; k < ci->bottom_left_math_kerns; k++) { undump_int(x); ci->bottom_left_math_kern_array[(2 * k)] = (scaled) x; @@ -757,26 +748,24 @@ static void undump_math_kerns(charinfo * ci) ci->bottom_left_math_kern_array[(2 * k) + 1] = (scaled) x; } undump_int(x); - ci->bottom_right_math_kerns = x; + ci->top_right_math_kerns = x; if (x > 0) - ci->bottom_right_math_kern_array = - xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); - for (k = 0; k < ci->bottom_right_math_kerns; k++) { + ci->top_right_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); + for (k = 0; k < ci->top_right_math_kerns; k++) { undump_int(x); - ci->bottom_right_math_kern_array[(2 * k)] = (scaled) x; + ci->top_right_math_kern_array[(2 * k)] = (scaled) x; undump_int(x); - ci->bottom_right_math_kern_array[(2 * k) + 1] = (scaled) x; + ci->top_right_math_kern_array[(2 * k) + 1] = (scaled) x; } undump_int(x); - ci->top_right_math_kerns = x; + ci->bottom_right_math_kerns = x; if (x > 0) - ci->top_right_math_kern_array = - xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); - for (k = 0; k < ci->top_right_math_kerns; k++) { + ci->bottom_right_math_kern_array = xmalloc((unsigned) (2 * (int) sizeof(scaled) * x)); + for (k = 0; k < ci->bottom_right_math_kerns; k++) { undump_int(x); - ci->top_right_math_kern_array[(2 * k)] = (scaled) x; + ci->bottom_right_math_kern_array[(2 * k)] = (scaled) x; undump_int(x); - ci->top_right_math_kern_array[(2 * k) + 1] = (scaled) x; + ci->bottom_right_math_kern_array[(2 * k) + 1] = (scaled) x; } } diff --git a/source/texk/web2c/luatexdir/lua/lcallbacklib.c b/source/texk/web2c/luatexdir/lua/lcallbacklib.c index 6bdaca016fd3215f44cadf7c9dc75b1b477fa804..812ad437b1ae50d79571da075c80d55f1cc17290 100644 --- a/source/texk/web2c/luatexdir/lua/lcallbacklib.c +++ b/source/texk/web2c/luatexdir/lua/lcallbacklib.c @@ -72,6 +72,7 @@ static const char *const callbacknames[] = { "process_rule", "insert_local_par", "contribute_filter", + "call_edit", NULL }; diff --git a/source/texk/web2c/luatexdir/lua/lpdflib.c b/source/texk/web2c/luatexdir/lua/lpdflib.c index 3b9846c0ed258bea2f86bc109ed931f81aaac6e9..82508a2a9e247335ab74978d417003fea5214efd 100644 --- a/source/texk/web2c/luatexdir/lua/lpdflib.c +++ b/source/texk/web2c/luatexdir/lua/lpdflib.c @@ -43,6 +43,8 @@ static int luapdfprint(lua_State * L) literal_mode = direct_always; else if (lua_key_eq(modestr_s,page)) literal_mode = direct_page; + else if (lua_key_eq(modestr_s,raw)) + literal_mode = direct_raw; else { luaL_error(L, "invalid first argument for print literal mode"); } @@ -64,6 +66,9 @@ static int luapdfprint(lua_State * L) case (direct_always): pdf_end_string_nl(static_pdf); break; + case (direct_raw): + pdf_end_string_nl(static_pdf); + break; default: assert(0); } @@ -1069,11 +1074,13 @@ static int newpdfcolorstack(lua_State * L) if (lua_type(L,2) == LUA_TSTRING) { l = lua_tostring(L, 2); if (lua_key_eq(l,origin)) { - literal_mode = 0; + literal_mode = set_origin; } else if (lua_key_eq(l,page)) { - literal_mode = 1; /* direct_page */ + literal_mode = direct_page; } else if (lua_key_eq(l,direct)) { - literal_mode = 2; /* direct_always */ + literal_mode = direct_always; + } else if (lua_key_eq(l,raw)) { + literal_mode = direct_raw; } else { luaL_error(L, "invalid literal mode in pdf.newcolorstack()"); } diff --git a/source/texk/web2c/luatexdir/lua/luanode.w b/source/texk/web2c/luatexdir/lua/luanode.w index f901eddbfa97a7f599511b5c7e5b1353cec905d1..af15748bacd6392a217ea520da44347505c32870 100644 --- a/source/texk/web2c/luatexdir/lua/luanode.w +++ b/source/texk/web2c/luatexdir/lua/luanode.w @@ -420,6 +420,9 @@ void show_pdf_literal(pointer p) case direct_always: tprint(" direct"); break; + case direct_raw: + tprint(" raw"); + break; default: confusion("literal2"); break; diff --git a/source/texk/web2c/luatexdir/luatex.c b/source/texk/web2c/luatexdir/luatex.c index 7e06c9388857cf10c466010c373f1ecec161b9e4..eb3f359392c8b17cde7f8df79bba2903d590f9f4 100644 --- a/source/texk/web2c/luatexdir/luatex.c +++ b/source/texk/web2c/luatexdir/luatex.c @@ -28,10 +28,10 @@ #define TeX -int luatex_version = 98; /* \.{\\luatexversion} */ -int luatex_revision = '4'; /* \.{\\luatexrevision} */ -int luatex_date_info = 2016090500; /* the compile date is now hardwired */ -const char *luatex_version_string = "0.98.4"; +int luatex_version = 99; /* \.{\\luatexversion} */ +int luatex_revision = '1'; /* \.{\\luatexrevision} */ +int luatex_date_info = 2016092300; /* the compile date is now hardwired */ +const char *luatex_version_string = "0.99.1"; const char *engine_name = my_name; /* the name of this engine */ #include <kpathsea/c-ctype.h> @@ -61,10 +61,6 @@ const char *engine_name = my_name; /* the name of this engine */ #include <signal.h> /* Catch interrupts. */ -/* {tex,mf}d.h defines TeX, MF, INI, and other such symbols. - Unfortunately there's no way to get the banner into this code, so - just repeat the text. */ -#define edit_var "TEXEDIT" /* Shell escape. diff --git a/source/texk/web2c/luatexdir/luatexcallbackids.h b/source/texk/web2c/luatexdir/luatexcallbackids.h index 4a02f05d058e785b932f610482364a3f947dfa83..cfd865b896a84d9a9e73c1ea339c3b9476850731 100644 --- a/source/texk/web2c/luatexdir/luatexcallbackids.h +++ b/source/texk/web2c/luatexdir/luatexcallbackids.h @@ -66,6 +66,7 @@ typedef enum { process_rule_callback, insert_local_par_callback, contribute_filter_callback, + call_edit_callback, total_callbacks } callback_callback_types; diff --git a/source/texk/web2c/luatexdir/pdf/pdfgen.h b/source/texk/web2c/luatexdir/pdf/pdfgen.h index 551f686e6fe245a87086a6cc9de9da5e4af59759..f2086663c70b82d05d0f921002e4167f437e1917 100644 --- a/source/texk/web2c/luatexdir/pdf/pdfgen.h +++ b/source/texk/web2c/luatexdir/pdf/pdfgen.h @@ -27,8 +27,8 @@ # define PROCSET_IMAGE_C (1 << 3) # define PROCSET_IMAGE_I (1 << 4) -# define inf_pdf_mem_size 10000 /* min size of the |mem| array */ -# define sup_pdf_mem_size 10000000 /* max size of the |mem| array */ +# define inf_pdf_mem_size 10000 /* min size of the |mem| array */ +# define sup_pdf_mem_size 100000000 /* max size of the |mem| array */ extern PDF static_pdf; @@ -43,10 +43,10 @@ be the first written bytes. */ -# define inf_pdfout_buf_size 16384 /* initial value of |pdf->buf| size */ -# define sup_pdfout_buf_size 16384 /* arbitrary upper hard limit of |pdf->buf| size */ -# define inf_objstm_buf_size 1 /* initial value of |os->buf[OBJSTM_BUF]| size */ -# define sup_objstm_buf_size 5000000 /* arbitrary upper hard limit of |os->buf[OBJSTM_BUF]| size */ +# define inf_pdfout_buf_size 16384 /* initial value of |pdf->buf| size */ +# define sup_pdfout_buf_size 8*16384 /* arbitrary upper hard limit of |pdf->buf| size */ +# define inf_objstm_buf_size 1 /* initial value of |os->buf[OBJSTM_BUF]| size */ +# define sup_objstm_buf_size 5000000 /* arbitrary upper hard limit of |os->buf[OBJSTM_BUF]| size */ # define PDF_OS_MAX_OBJS 100 /* maximum number of objects in object stream */ diff --git a/source/texk/web2c/luatexdir/pdf/pdfliteral.w b/source/texk/web2c/luatexdir/pdf/pdfliteral.w index 3c6b6f6efbfb9880ec629df0ee12bb7c897bbb58..64a36dc67bfaffa5e31aa311baa0660a058ff482 100644 --- a/source/texk/web2c/luatexdir/pdf/pdfliteral.w +++ b/source/texk/web2c/luatexdir/pdf/pdfliteral.w @@ -66,6 +66,9 @@ void pdf_out_literal(PDF pdf, halfword p) pdf_end_string_nl(pdf); ps->need_tm = true; break; + case direct_raw: + pdf_end_string_nl(pdf); + break; default: normal_error("pdf backend","bad literal mode"); break; @@ -114,6 +117,9 @@ void pdf_literal(PDF pdf, str_number s, int literal_mode, boolean warn) } else if (str_in_cstr(s, "page:", strlen("PDF:"))) { j = j + (pool_pointer) strlen("page:"); literal_mode = direct_page; + } else if (str_in_cstr(s, "raw:", strlen("PDF:"))) { + j = j + (pool_pointer) strlen("raw:"); + literal_mode = direct_raw; } else { literal_mode = set_origin; } @@ -131,6 +137,9 @@ void pdf_literal(PDF pdf, str_number s, int literal_mode, boolean warn) pdf_end_string_nl(pdf); p->need_tm = true; break; + case direct_raw: + pdf_end_string_nl(pdf); + break; default: normal_error("pdf backend","bad literal mode"); break; diff --git a/source/texk/web2c/luatexdir/pdf/pdfrule.w b/source/texk/web2c/luatexdir/pdf/pdfrule.w index 2f75b4c761e951485a6b4381d1079783c6830a96..df4979088c8242533e41eb5d98a863bae5dee3e4 100644 --- a/source/texk/web2c/luatexdir/pdf/pdfrule.w +++ b/source/texk/web2c/luatexdir/pdf/pdfrule.w @@ -30,14 +30,22 @@ void pdf_place_rule(PDF pdf, halfword q, scaledpos size, int callback_id) pdfpos dim; pdfstructure *p = pdf->pstruct; scaledpos pos = pdf->posstruct->pos; + halfword s = subtype(q); /* (void) q; */ - if (subtype(q) == box_rule) { + if (s >= math_over_rule && s <= math_radical_rule) { + if (callback_id == 0) { + s = normal_rule; + } else { + s = user_rule; + } + } + if (s == box_rule) { pdf_place_form(pdf,q); - } else if (subtype(q) == image_rule) { + } else if (s == image_rule) { pdf_place_image(pdf,q); - } else if (subtype(q) == empty_rule) { + } else if (s == empty_rule) { /* place nothing, only take space */ - } else if (subtype(q) == user_rule) { + } else if (s == user_rule) { if (callback_id != 0) { pdf_goto_pagemode(pdf); pdf_puts(pdf, "q\n"); diff --git a/source/texk/web2c/luatexdir/tex/commands.w b/source/texk/web2c/luatexdir/tex/commands.w index e4a269d93d010e4f53442f2acbc7671bd6d1fba5..b89dadffd1f4936b3d5f6292eecc0c9200edec9d 100644 --- a/source/texk/web2c/luatexdir/tex/commands.w +++ b/source/texk/web2c/luatexdir/tex/commands.w @@ -754,6 +754,8 @@ void initialize_etex_commands(void) primitive_luatex("mathdisplayskipmode", assign_int_cmd, int_base + math_display_skip_mode_code, int_base); primitive_luatex("mathscriptsmode", assign_int_cmd, int_base + math_scripts_mode_code, int_base); primitive_luatex("mathnolimitsmode", assign_int_cmd, int_base + math_nolimits_mode_code, int_base); + primitive_luatex("mathrulesmode", assign_int_cmd, int_base + math_rules_mode_code, int_base); + primitive_luatex("mathrulesfam", assign_int_cmd, int_base + math_rules_fam_code, int_base); primitive_luatex("synctex", assign_int_cmd, int_base + synctex_code, int_base); primitive_etex("currentgrouplevel", last_item_cmd, current_group_level_code, 0); diff --git a/source/texk/web2c/luatexdir/tex/dumpdata.w b/source/texk/web2c/luatexdir/tex/dumpdata.w index 85ff55f4e09915aa3f6888d4180c2f6f3426168a..c7bb4c2e87d4af8306436a06044d334d6c95055d 100644 --- a/source/texk/web2c/luatexdir/tex/dumpdata.w +++ b/source/texk/web2c/luatexdir/tex/dumpdata.w @@ -23,7 +23,7 @@ /* we start with 907: the sum of the values of the bytes of "don knuth" */ -#define FORMAT_ID (907+18) +#define FORMAT_ID (907+20) #if ((FORMAT_ID>=0) && (FORMAT_ID<=256)) #error Wrong value for FORMAT_ID. #endif diff --git a/source/texk/web2c/luatexdir/tex/equivalents.h b/source/texk/web2c/luatexdir/tex/equivalents.h index b2bda5f605bb6ed600b0080aa85c0418814aacce..27a4f96401b51faf3e86c409274cd28ac425b72a 100644 --- a/source/texk/web2c/luatexdir/tex/equivalents.h +++ b/source/texk/web2c/luatexdir/tex/equivalents.h @@ -279,20 +279,22 @@ the |number_regs| \.{\\dimen} registers. # define math_display_skip_mode_code 88 # define math_scripts_mode_code 89 # define math_nolimits_mode_code 90 -# define synctex_code 91 /* is synctex file generation enabled ? */ -# define shape_mode_code 92 -# define first_valid_language_code 93 -# define hyphenation_bounds_code 94 +# define math_rules_mode_code 91 +# define math_rules_fam_code 92 +# define synctex_code 93 /* is synctex file generation enabled ? */ +# define shape_mode_code 94 +# define first_valid_language_code 95 +# define hyphenation_bounds_code 96 -# define math_option_code 95 +# define math_option_code 97 -# define mathoption_int_base (int_base+96) /* one reserve */ -# define mathoption_int_last (int_base+104) +# define mathoption_int_base (int_base+98) /* one reserve */ +# define mathoption_int_last (int_base+106) -# define backend_int_base (int_base+105) -# define backend_int_last (int_base+129) +# define backend_int_base (int_base+107) +# define backend_int_last (int_base+131) -# define tex_int_pars (130) /* total number of integer parameters */ +# define tex_int_pars (132) /* total number of integer parameters */ # define page_direction_code (tex_int_pars) # define body_direction_code (tex_int_pars+1) @@ -639,6 +641,8 @@ extern halfword last_cs_name; #define disable_space_par int_par(disable_space_code) #define scripts_mode_par int_par(math_scripts_mode_code) #define nolimits_mode_par int_par(math_nolimits_mode_code) +#define math_rules_mode_par int_par(math_rules_mode_code) +#define math_rules_fam_par int_par(math_rules_fam_code) #define thin_mu_skip_par glue_par(thin_mu_skip_code) #define med_mu_skip_par glue_par(med_mu_skip_code) diff --git a/source/texk/web2c/luatexdir/tex/errors.w b/source/texk/web2c/luatexdir/tex/errors.w index 1af16ec58ef41ea8092cf103672927a8b4b1f6c8..cec9a144f1c3fec9bc12b945b07d46eb80e7f812 100644 --- a/source/texk/web2c/luatexdir/tex/errors.w +++ b/source/texk/web2c/luatexdir/tex/errors.w @@ -24,6 +24,7 @@ luafflib.c @ @c #include "ptexlib.h" +#define edit_var "TEXEDIT" @ When something anomalous is detected, \TeX\ typically does something like this: $$\vbox{\halign{#\hfil\cr @@ -232,6 +233,155 @@ void jump_out(void) close_files_and_terminate(); do_final_end(); } +@ Here is the function that calls the editor, if one is defined. This +is loosely based on a similar function in kpathsea, but the calling +convention is quite different. + +@c +static const_string edit_value = EDITOR; + +#if defined(WIN32) +static int +Isspace (char c) +{ + return (c == ' ' || c == '\t'); +} +#endif /* WIN32 */ + +__attribute__ ((noreturn)) +static void luatex_calledit (int baseptr, int linenumber) +{ + char *temp, *command, *fullcmd; + char c; + int sdone, ddone, i; + char *filename = makecstring(input_stack[base_ptr].name_field); + int fnlength = strlen(filename); + +#ifdef WIN32 + char *fp, *ffp, *env, editorname[256], buffer[256]; + int cnt = 0; + int dontchange = 0; +#endif + + sdone = ddone = 0; + + /* Close any open input files, since we're going to kill the job. */ + close_files_and_terminate(); + + /* Replace the default with the value of the appropriate environment + variable or config file value, if it's set. */ + temp = kpse_var_value (edit_var); + if (temp != NULL) + edit_value = temp; + + /* Construct the command string. The `11' is the maximum length an + integer might be. */ + command = xmalloc (strlen (edit_value) + fnlength + 11); + + /* So we can construct it as we go. */ + temp = command; + +#ifdef WIN32 + fp = editorname; + if ((isalpha(*edit_value) && *(edit_value + 1) == ':' + && IS_DIR_SEP (*(edit_value + 2))) + || (*edit_value == '"' && isalpha(*(edit_value + 1)) + && *(edit_value + 2) == ':' + && IS_DIR_SEP (*(edit_value + 3))) + ) + dontchange = 1; +#endif + + while ((c = *edit_value++) != 0) + { + if (c == '%') + { + switch (c = *edit_value++) + { + case 'd': + if (ddone) + FATAL1 ("call_edit: `%%d' appears twice in editor command: `%s'", edit_value); + sprintf (temp, "%ld", (long int)linenumber); + while (*temp != '\0') + temp++; + ddone = 1; + break; + + case 's': + if (sdone) + FATAL1 ("call_edit: `%%s' appears twice in editor command: `%s'", edit_value); + for (i =0; i < fnlength; i++) + *temp++ = filename[i]; + sdone = 1; + break; + + case '\0': + *temp++ = '%'; + /* Back up to the null to force termination. */ + edit_value--; + break; + + default: + *temp++ = '%'; + *temp++ = c; + break; + } + } + else { +#ifdef WIN32 + if (dontchange) + *temp++ = c; + else { if(Isspace(c) && cnt == 0) { + cnt++; + temp = command; + *temp++ = c; + *fp = '\0'; + } else if(!Isspace(c) && cnt == 0) { + *fp++ = c; + } else { + *temp++ = c; + } + } +#else + *temp++ = c; +#endif + } + } + + *temp = 0; + +#ifdef WIN32 + if (dontchange == 0) { + if(editorname[0] == '.' || + editorname[0] == '/' || + editorname[0] == '\\') { + fprintf(stderr, "%s is not allowed to execute.\n", editorname); + do_final_end(); + } + env = (char *)getenv("PATH"); + if(SearchPath(env, editorname, ".exe", 256, buffer, &ffp)==0) { + if(SearchPath(env, editorname, ".bat", 256, buffer, &ffp)==0) { + fprintf(stderr, "I cannot find %s in the PATH.\n", editorname); + do_final_end(); + } + } + fullcmd = (char *)xmalloc(strlen(buffer)+strlen(command)+5); + strcpy(fullcmd, "\""); + strcat(fullcmd, buffer); + strcat(fullcmd, "\""); + strcat(fullcmd, command); + } else +#endif + fullcmd = command; + + /* Execute the command. */ + if (system (fullcmd) != 0) + fprintf (stderr, "! Trouble executing `%s'.\n", command); + + /* Quit, since we found an error. */ + do_final_end (); +} + @ @c void error(void) @@ -325,12 +475,23 @@ void error(void) #endif case 'E': if (base_ptr > 0) { - tprint_nl("You want to edit file "); - print(input_stack[base_ptr].name_field); - tprint(" at line "); - print_int(line); - interaction = scroll_mode; - jump_out(); + int callback_id = callback_defined(call_edit_callback); + if (callback_id>0) { + (void)run_callback(callback_id, "Sd->", makecstring(input_stack[base_ptr].name_field), line); + jump_out(); /* should not be reached */ + } else { + tprint_nl("You want to edit file "); + print(input_stack[base_ptr].name_field); + tprint(" at line "); + print_int(line); + interaction = scroll_mode; + if (kpse_init) { + luatex_calledit(base_ptr, line); + } else { + tprint_nl("There is no valid callback defined."); + jump_out(); /* should not be reached */ + } + } } break; case 'H': diff --git a/source/texk/web2c/luatexdir/tex/extensions.w b/source/texk/web2c/luatexdir/tex/extensions.w index 838c6edcead900cc3651684ce1bde7f02e336d5e..f3c66d32ed294aa80bb61e064681f2d8d4ca8163 100644 --- a/source/texk/web2c/luatexdir/tex/extensions.w +++ b/source/texk/web2c/luatexdir/tex/extensions.w @@ -142,6 +142,8 @@ static void do_extension_pdf(int immediate) set_pdf_literal_mode(tail, direct_always); else if (scan_keyword("page")) set_pdf_literal_mode(tail, direct_page); + else if (scan_keyword("raw")) + set_pdf_literal_mode(tail, direct_raw); else set_pdf_literal_mode(tail, set_origin); scan_toks(false, true); diff --git a/source/texk/web2c/luatexdir/tex/mlist.w b/source/texk/web2c/luatexdir/tex/mlist.w index 753ce840cbccf897cb018a6dd44ac4510c56ec95..909128e93c6171229202310d6f3ddaa672b8d219 100644 --- a/source/texk/web2c/luatexdir/tex/mlist.w +++ b/source/texk/web2c/luatexdir/tex/mlist.w @@ -271,7 +271,7 @@ static scaled minimum_operator_size(int var) the backward compatibility code, and it means that we can't raise an error here. @c -static scaled radical_rule(int var) +static scaled radical_rule_par(int var) { scaled a = get_math_param(math_param_radical_rule, var); return a; @@ -978,10 +978,16 @@ static pointer math_clone(pointer q) that eventually contains it. @c -static pointer do_fraction_rule(scaled t, pointer att) +static pointer do_fraction_rule(scaled t, pointer att, halfword some_rule, halfword cur_size, halfword cur_fam) { pointer p; /* the new node */ - p = new_rule(normal_rule); + if (math_rules_mode_par) { + p = new_rule(some_rule); + rule_math_size(p) = cur_size; + rule_math_font(p) = fam_fnt(cur_fam, cur_size); + } else { + p = new_rule(normal_rule); + } rule_dir(p) = math_direction_par; height(p) = t; depth(p) = 0; @@ -994,13 +1000,13 @@ static pointer do_fraction_rule(scaled t, pointer att) fraction rule of thickness |t| under additional space of height |ht|. @c -static pointer overbar(pointer b, scaled k, scaled t, scaled ht, pointer att) +static pointer overbar(pointer b, scaled k, scaled t, scaled ht, pointer att, halfword index, halfword cur_size, halfword cur_fam) { pointer p, q; /* nodes being constructed */ p = new_kern(k); reset_attributes(p, att); couple_nodes(p,b); - q = do_fraction_rule(t, att); + q = do_fraction_rule(t, att, index, cur_size, cur_fam); couple_nodes(q,p); p = new_kern(ht); reset_attributes(p, att); @@ -1796,17 +1802,17 @@ illustrate the general setup of such procedures, let's begin with a couple of simple ones. @c -static void make_over(pointer q, int cur_style) +static void make_over(pointer q, int cur_style, int cur_size, int cur_fam) { pointer p; p = overbar(clean_box(nucleus(q), cramped_style(cur_style), cur_style), overbar_vgap(cur_style), overbar_rule(cur_style), - overbar_kern(cur_style), node_attr(nucleus(q))); + overbar_kern(cur_style), node_attr(nucleus(q)), math_over_rule, cur_size, cur_fam); math_list(nucleus(q)) = p; type(nucleus(q)) = sub_box_node; } -static void make_under(pointer q, int cur_style) +static void make_under(pointer q, int cur_style, int cur_size, int cur_fam) { pointer p, x, y, r; /* temporary registers for box construction */ scaled delta; /* overall height plus depth */ @@ -1814,7 +1820,7 @@ static void make_under(pointer q, int cur_style) p = new_kern(underbar_vgap(cur_style)); reset_attributes(p, node_attr(q)); couple_nodes(x,p); - r = do_fraction_rule(underbar_rule(cur_style), node_attr(q)); + r = do_fraction_rule(underbar_rule(cur_style), node_attr(q), math_under_rule, cur_size, cur_fam); couple_nodes(p,r); y = vpackage(x, 0, additional, max_dimen, math_direction_par); reset_attributes(y, node_attr(q)); @@ -1878,7 +1884,7 @@ static void make_radical(pointer q, int cur_style) scaled delta, clr, theta, h; /* dimensions involved in the calculation */ x = clean_box(nucleus(q), cramped_style(cur_style), cur_style); clr = radical_vgap(cur_style); - theta = radical_rule(cur_style); + theta = radical_rule_par(cur_style); if (theta == undefined_math_parameter) { /* a real radical */ theta = fraction_rule(cur_style); @@ -1912,7 +1918,7 @@ static void make_radical(pointer q, int cur_style) } shift_amount(y) = (height(y) - theta) - (height(x) + clr); h = depth(y) + height(y); - p = overbar(x, clr, theta, radical_kern(cur_style), node_attr(y)); + p = overbar(x, clr, theta, radical_kern(cur_style), node_attr(y), math_radical_rule, cur_size, small_fam(left_delimiter(q))); couple_nodes(y,p); if (degree(q) != null) { scaled wr, br, ar; @@ -2559,7 +2565,7 @@ static void make_fraction(pointer q, int cur_style) p = new_kern((shift_up - depth(x)) - (height(z) - shift_down)); couple_nodes(p,z); } else { - y = do_fraction_rule(thickness(q), node_attr(q)); + y = do_fraction_rule(thickness(q), node_attr(q), math_fraction_rule, cur_size, math_rules_fam_par); p = new_kern((math_axis_size(cur_size) - delta) - (height(z) - shift_down)); reset_attributes(p, node_attr(q)); couple_nodes(y,p); @@ -2656,8 +2662,9 @@ static scaled make_op(pointer q, int cur_style) math_character(nucleus(q)) = c; } delta = char_italic(cur_f, cur_c); +printf("delta %i\n",delta); x = clean_box(nucleus(q), cur_style, cur_style); - if (delta != null) { + if (delta != 0) { if (do_new_math(cur_f)) { /* we never added italic correction */ } else if ((subscr(q) != null) && (subtype(q) != op_noad_type_limits)) { @@ -2712,8 +2719,8 @@ static scaled make_op(pointer q, int cur_style) */ switch (mode) { case 0 : - /* as with limits */ - make_scripts(q, p, 0, cur_style, half(delta), -half(delta)); + /* full bottom correction */ + make_scripts(q, p, 0, cur_style, 0, -delta); break; case 1 : /* MathConstants driven */ @@ -2723,22 +2730,21 @@ static scaled make_op(pointer q, int cur_style) case 2 : /* no correction */ make_scripts(q, p, 0, cur_style, 0, 0); - break; + break ; case 3 : /* half bottom correction */ make_scripts(q, p, 0, cur_style, 0, -half(delta)); break; case 4 : - /* full bottom correction */ - make_scripts(q, p, 0, cur_style, 0, -delta); + /* half bottom and top correction */ + make_scripts(q, p, 0, cur_style, half(delta), -half(delta)); break; default : - /* half bottom and top correction */ if (mode > 15) { /* for quickly testing values */ make_scripts(q, p, 0, cur_style, 0, -round_xn_over_d(delta, mode, 1000)); } else { - make_scripts(q, p, 0, cur_style, half(delta), -half(delta)); + make_scripts(q, p, 0, cur_style, 0, 0); } break; } @@ -3913,10 +3919,10 @@ void mlist_to_hlist(pointer mlist, boolean penalties, int cur_style) } break; case over_noad_type: - make_over(q, cur_style); + make_over(q, cur_style, cur_size, math_rules_fam_par); break; case under_noad_type: - make_under(q, cur_style); + make_under(q, cur_style, cur_size, math_rules_fam_par); break; case vcenter_noad_type: make_vcenter(q); diff --git a/source/texk/web2c/luatexdir/tex/texfileio.w b/source/texk/web2c/luatexdir/tex/texfileio.w index c222eef975b8614628bff85e2b159760299a3d07..2281de12c4c858652b47a963712898c5e9ba46ec 100644 --- a/source/texk/web2c/luatexdir/tex/texfileio.w +++ b/source/texk/web2c/luatexdir/tex/texfileio.w @@ -170,12 +170,12 @@ char *luatex_find_file(const char *s, int callback_index) case find_data_file_callback: ftemp = find_in_output_directory(s); if (!ftemp) - ftemp = kpse_find_file(s, kpse_tex_format, 0); + ftemp = kpse_find_file(s, kpse_tex_format, 1); break; case find_font_file_callback: - ftemp = kpse_find_file(s, kpse_ofm_format, 0); + ftemp = kpse_find_file(s, kpse_ofm_format, 1); if (ftemp == NULL) - ftemp = kpse_find_file(s, kpse_tfm_format, 0); + ftemp = kpse_find_file(s, kpse_tfm_format, 1); break; case find_vf_file_callback: ftemp = kpse_find_file(s, kpse_ovf_format, 0); diff --git a/source/texk/web2c/luatexdir/tex/texnodes.h b/source/texk/web2c/luatexdir/tex/texnodes.h index 6650d17f41091ed70259fdaedbaeddb146e70f69..943a347554de0137370d59cc44c605f8c4392eaf 100644 --- a/source/texk/web2c/luatexdir/tex/texnodes.h +++ b/source/texk/web2c/luatexdir/tex/texnodes.h @@ -261,6 +261,10 @@ typedef enum { image_rule, empty_rule, user_rule, + math_over_rule, + math_under_rule, + math_fraction_rule, + math_radical_rule, } rule_subtypes; # define rule_node_size 8 @@ -270,6 +274,9 @@ typedef enum { # define synctex_tag_rule(a) vinfo((a)+7) # define synctex_line_rule(a) vlink((a)+7) +# define rule_math_size rule_index +# define rule_math_font rule_transform + # define mark_node_size 3 # define mark_ptr(a) vlink((a)+2) # define mark_class(a) vinfo((a)+2) @@ -716,6 +723,7 @@ typedef enum { set_origin = 0, direct_page, direct_always, + direct_raw, scan_special, } ctm_transform_modes; diff --git a/source/texk/web2c/luatexdir/tex/texnodes.w b/source/texk/web2c/luatexdir/tex/texnodes.w index c242577404f9d761543c86822a7b2e48028d9492..3a368c82336a6b5ef15692fadaea8b47506cc5b4 100644 --- a/source/texk/web2c/luatexdir/tex/texnodes.w +++ b/source/texk/web2c/luatexdir/tex/texnodes.w @@ -268,7 +268,7 @@ const char *node_subtypes_kern[] = { "fontkern", "userkern", "accentkern", "italiccorrection", NULL }; const char *node_subtypes_rule[] = { - "normal", "box", "image", "empty", "user", NULL + "normal", "box", "image", "empty", "user", "over", "under", "fraction", "radical", NULL }; const char *node_subtypes_glyph[] = { "character", "glyph", "ligature", "ghost", "left", "right", NULL diff --git a/source/texk/web2c/luatexdir/tex/textoken.w b/source/texk/web2c/luatexdir/tex/textoken.w index 8f44f686641ba0e9368fa3f9d70390324e4a174c..7b781fc082b0d39512780756e6f8a98cce92fbee 100644 --- a/source/texk/web2c/luatexdir/tex/textoken.w +++ b/source/texk/web2c/luatexdir/tex/textoken.w @@ -2437,6 +2437,8 @@ static int do_feedback_pdf(halfword c) cur_val = direct_always; else if (scan_keyword("page")) cur_val = direct_page; + else if (scan_keyword("raw")) + cur_val = direct_raw; else cur_val = set_origin; save_scanner_status = scanner_status; diff --git a/source/texk/web2c/mplibdir/mp.w b/source/texk/web2c/mplibdir/mp.w index 964c5372069c7914c9bc7cba206575a3713df57b..4977fbcefba4a9c91f939110fad8fea0d2fccbe8 100644 --- a/source/texk/web2c/mplibdir/mp.w +++ b/source/texk/web2c/mplibdir/mp.w @@ -1,4 +1,4 @@ -% $Id: mp.w 2080 2016-03-06 21:26:30Z luigi $ +% $Id: mp.w 2093 2016-09-20 10:09:14Z luigi $ % % This file is part of MetaPost; % the MetaPost program is in the public domain. @@ -140,6 +140,19 @@ typedef struct MP_instance { #endif @ @c +/*#define DEBUGENVELOPE */ +#ifdef DEBUGENVELOPE +#define dbg_n(A) printf("['%s']=%s, ", #A, number_tostring(A)) +#define dbg_in(A) printf("['%s']=%d, ", #A, (int)(A)) +#define dbg_dn(A) printf("['%s']=%.100f, ", #A, (double)(A)) +#define dbg_key(A) printf("['%s']= ", #A) +#define dbg_sp printf(" ") +#define dbg_str(A) printf("%s",#A) +#define dbg_open_t printf("{") +#define dbg_close_t printf("}") +#define dbg_comma printf(",") +#define dbg_nl printf("\n") +#endif #define KPATHSEA_DEBUG_H 1 #include <w2c/config.h> #include <stdio.h> @@ -171,6 +184,15 @@ typedef struct MP_instance { #include "mpmathdecimal.h" /* internal header */ #include "mpmathbinary.h" /* internal header */ #include "mpstrings.h" /* internal header */ +/* BEGIN PATCH */ +mp_number dx_ap; /* approximation of dx */ +mp_number dy_ap; /* approximation of dy */ +mp_number dxin_ap; /* approximation of dxin */ +mp_number dyin_ap; /* approximation of dyin */ +mp_number ueps_ap; /* epsilon for above approximations */ +/* END PATCH */ + + extern font_number mp_read_font_info (MP mp, char *fname); /* tfmin.w */ @h @<Declarations@>; @<Basic printing procedures@>; @@ -2568,18 +2590,18 @@ void mp_new_randoms (MP mp) { mp->j_random = 54; } -@ To consume a random fraction, the program below will say `|next_random|'. +@ To consume a random fraction, the program below will say `|next_random|'. Now each number system has its own implementation, true to the original as much as possibile. @c /* Unused. -static void mp_next_random (MP mp, mp_number *ret) { - if ( mp->j_random==0 ) - mp_new_randoms(mp); +static void mp\_next\_random (MP mp, mp\_number *ret) { + if ( mp->j\_random==0 ) + mp\_new\_randoms(mp); else - decr(mp->j_random); - number_clone (*ret, mp->randoms[mp->j_random]); + decr(mp->j\_random); + number\_clone (*ret, mp->randoms[mp->j\_random]); } */ @@ -2596,31 +2618,31 @@ As said before, now each number system has its own implementation. @c /*Unused. -static void mp_unif_rand (MP mp, mp_number *ret, mp_number x_orig) { - mp_number y; // trial value - mp_number x, abs_x; - mp_number u; - new_fraction (y); - new_number (x); - new_number (abs_x); - new_number (u); - number_clone (x, x_orig); - number_clone (abs_x, x); - number_abs (abs_x); - mp_next_random(mp, &u); - take_fraction (y, abs_x, u); - free_number (u); - if (number_equal(y, abs_x)) { - set_number_to_zero(*ret); - } else if (number_positive(x)) { - number_clone (*ret, y); +static void mp\_unif\_rand (MP mp, mp\_number *ret, mp\_number x\_orig) { + mp\_number y; // trial value + mp\_number x, abs\_x; + mp\_number u; + new\_fraction (y); + new\_number (x); + new\_number (abs\_x); + new\_number (u); + number\_clone (x, x\_orig); + number\_clone (abs\_x, x); + number\_abs (abs\_x); + mp\_next\_random(mp, \&u); + take\_fraction (y, abs\_x, u); + free\_number (u); + if (number\_equal(y, abs\_x)) { + set\_number\_to\_zero(*ret); + } else if (number\_positive(x)) { + number\_clone (*ret, y); } else { - number_clone (*ret, y); - number_negate (*ret); + number\_clone (*ret, y); + number\_negate (*ret); } - free_number (abs_x); - free_number (x); - free_number (y); + free\_number (abs\_x); + free\_number (x); + free\_number (y); } */ @@ -2634,43 +2656,43 @@ true to the original as much as possibile. @c /* Unused. -static void mp_norm_rand (MP mp, mp_number *ret) { - mp_number ab_vs_cd; - mp_number abs_x; - mp_number u; - mp_number r; - mp_number la, xa; - new_number (ab_vs_cd); - new_number (la); - new_number (xa); - new_number (abs_x); - new_number (u); - new_number (r); +static void mp\_norm\_rand (MP mp, mp\_number *ret) { + mp\_number ab\_vs\_cd; + mp\_number abs\_x; + mp\_number u; + mp\_number r; + mp\_number la, xa; + new\_number (ab\_vs\_cd); + new\_number (la); + new\_number (xa); + new\_number (abs\_x); + new\_number (u); + new\_number (r); do { do { - mp_number v; - new_number (v); - mp_next_random(mp, &v); - number_substract (v, fraction_half_t); - take_fraction (xa, sqrt_8_e_k, v); - free_number (v); - mp_next_random(mp, &u); - number_clone (abs_x, xa); - number_abs (abs_x); - } while (number_greaterequal (abs_x, u)); - make_fraction (r, xa, u); - number_clone (xa, r); - m_log (la, u); - set_number_from_substraction(la, twelve_ln_2_k, la); - ab_vs_cd (ab_vs_cd, one_k, la, xa, xa); - } while (number_negative(ab_vs_cd)); - number_clone (*ret, xa); - free_number (ab_vs_cd); - free_number (r); - free_number (abs_x); - free_number (la); - free_number (xa); - free_number (u); + mp\_number v; + new\_number (v); + mp\_next\_random(mp, \&v); + number\_substract (v, fraction\_half\_t); + take\_fraction (xa, sqrt\_8\_e\_k, v); + free\_number (v); + mp\_next\_random(mp, \&u); + number\_clone (abs\_x, xa); + number\_abs (abs\_x); + } while (number\_greaterequal (abs\_x, u)); + make\_fraction (r, xa, u); + number\_clone (xa, r); + m\_log (la, u); + set\_number\_from\_substraction(la, twelve\_ln\_2\_k, la); + ab\_vs\_cd (ab\_vs\_cd, one\_k, la, xa, xa); + } while (number\_negative(ab\_vs\_cd)); + number\_clone (*ret, xa); + free\_number (ab\_vs\_cd); + free\_number (r); + free\_number (abs\_x); + free\_number (la); + free\_number (xa); + free\_number (u); } */ @@ -4705,7 +4727,7 @@ static mp_sym mp_frozen_id_lookup (MP mp, char *j, size_t l, return mp_do_id_lookup (mp, mp->frozen_symbols, j, l, insert_new); } -/* see mp_print_sym (mp_sym sym) */ +/* see mp\_print\_sym (mp\_sym sym) */ @ Get a numeric value from \MP\ is not easy. We have to consider the macro and the loops, as also the internal type (this is a first attempt, and more work is needed). If we are inside @@ -13144,6 +13166,92 @@ Since an envelope spec only determines relative changes in pen offsets, @<Glob...@>= integer spec_offset; /* number of pen edges between |h| and the initial offset */ +@ The next function calculates $1/3 B'(t) = (-p + (3c_1 + (-3c_2 + q)))*t^2 + (2p + (-4c_1 + 2*c_2))t + (-p + c_1)$, +for cubic curve |B(t)| given by |p|,|c1|,|c2|,|q| +and it's used for |t| near 0 and |t| near 1. We use double mode, otherwise we have to +take care of overflow. + +@<Declarations@>= +static void mp_dx_dy_approx(MP mp, mp_number *dx_ap, mp_number *dy_ap,mp_knot p, mp_knot q,mp_number t); + +@ @c +static void mp_dx_dy_approx(MP mp, mp_number *dx_ap, mp_number *dy_ap,mp_knot kp, mp_knot kq,mp_number t) { /* find dx dy at |t| */ + + /* 1/3 B'(t) = (-p + (3c1 + (-3c2 + q)))t^2 + (2p + (-4c1 + 2c2))t + (-p + c1) */ + /* 1/3 B'(u) = (p + (-3*c1 + (3c2 - q)))*u^2 + (2c1 + (-4c2 + 2q))u + (c2 - q) */ + + mp_number absval; + mp_number max_coef; /* used while scaling */ + mp_number small_nr, big_nr; + mp_number abs_dx, abs_dy; + + double p,c1,c2,q,dt,s1; + new_number (absval); + new_number(max_coef); + new_number(small_nr); + new_number(big_nr); + new_number(abs_dx); + new_number(abs_dy); + + set_number_from_double(small_nr,0.001); + set_number_from_double(big_nr,1000); + + dt = number_to_double(t); + + p = number_to_double(kp->x_coord); + c1 = number_to_double(kp->right_x); + c2 = number_to_double(kq->left_x); + q = number_to_double(kq->x_coord); + + s1 = (-p + (3*c1 + (-3*c2 + q)))*(dt*dt) + (2*p + (-4*c1 + 2*c2))*dt + (-p + c1); + set_number_from_double(*dx_ap,s1); + + + p = number_to_double(kp->y_coord); + c1 = number_to_double(kp->right_y); + c2 = number_to_double(kq->left_y); + q = number_to_double(kq->y_coord); + + s1 = (-p + (3*c1 + (-3*c2 + q)))*(dt*dt) + (2*p + (-4*c1 + 2*c2))*dt + (-p + c1); + set_number_from_double(*dy_ap,s1); + + + if (!number_zero(*dx_ap) || !number_zero(*dy_ap)) { + number_clone(absval, *dx_ap); + number_abs(absval); + number_clone(max_coef, *dy_ap); + number_abs (max_coef); + if (number_greater(absval, max_coef)) { + number_clone(max_coef, absval); + } + while (number_less(max_coef, fraction_half_t)) { + number_double (max_coef); + number_double (*dx_ap); + number_double (*dy_ap); + } + number_clone(abs_dx,*dx_ap); + number_clone(abs_dy,*dy_ap); + number_abs(abs_dx); + number_abs(abs_dy); + /* This is an experimental approximation */ + if (number_greaterequal(abs_dy,big_nr) && number_lessequal(abs_dx,small_nr)) { + set_number_to_zero(*dx_ap); + } + if (number_greaterequal(abs_dx,big_nr) && number_lessequal(abs_dy,small_nr)) { + set_number_to_zero(*dy_ap); + } + } + + free_number(absval); + free_number(max_coef); + free_number(small_nr); + free_number(big_nr); + free_number(abs_dx); + free_number(abs_dy); + +} + + @ @c static mp_knot mp_offset_prep (MP mp, mp_knot c, mp_knot h) { int n; /* the number of vertices in the pen polygon */ @@ -13183,6 +13291,13 @@ static mp_knot mp_offset_prep (MP mp, mp_knot c, mp_knot h) { new_number(u1); new_number(v0); new_number(v1); + new_number(dx_m); + new_number(dxin_m); + new_number(dx_ap); + new_number(dy_ap); + new_number(dxin_ap); + new_number(dyin_ap); + new_number(ueps_ap); new_fraction (ss); new_fraction (s); new_fraction (t); @@ -13191,17 +13306,39 @@ static mp_knot mp_offset_prep (MP mp, mp_knot c, mp_knot h) { p = c; c0 = c; k_needed = 0; - do { +#ifdef DEBUGENVELOPE +dbg_nl;dbg_str(--[==[BEGIN]==]);dbg_nl; +#endif + do { q = mp_next_knot (p); +#ifdef DEBUGENVELOPE +dbg_nl;dbg_open_t;dbg_str(--[==[begin loop]==]);dbg_nl; +dbg_n(p->x_coord);dbg_n(p->y_coord); +dbg_n(p->right_x);dbg_n(p->right_y); +dbg_n(q->left_x);dbg_n(q->left_y); +dbg_n(q->x_coord);dbg_n(q->y_coord); +#endif @<Split the cubic between |p| and |q|, if necessary, into cubics associated with single offsets, after which |q| should point to the end of the final such cubic@>; NOT_FOUND: @<Advance |p| to node |q|, removing any ``dead'' cubics that might have been introduced by the splitting process@>; +#ifdef DEBUGENVELOPE +dbg_str(--[==[end loop]==]);dbg_nl; dbg_close_t;dbg_comma;dbg_nl; +#endif } while (q != c); +#ifdef DEBUGENVELOPE + dbg_key(Fix the offset change);dbg_open_t;dbg_nl; + dbg_in(mp_knot_info(p));dbg_close_t;dbg_comma;dbg_nl; +#endif @<Fix the offset change in |mp_knot_info(c)| and set |c| to the return value of |offset_prep|@>; +#ifdef DEBUGENVELOPE +dbg_in(mp_knot_info(p)); +dbg_close_t;dbg_comma;dbg_nl; +dbg_nl;dbg_str(--[==[END]==]);dbg_nl; +#endif free_number (ss); free_number (s); free_number (dxin); @@ -13232,6 +13369,13 @@ static mp_knot mp_offset_prep (MP mp, mp_knot c, mp_knot h) { free_number (u1); free_number (v0); free_number (v1); + free_number(dx_m); + free_number(dxin_m); + free_number(dx_ap); + free_number(dy_ap); + free_number(dxin_ap); + free_number(dyin_ap); + free_number(ueps_ap); free_number (t); return c; } @@ -13447,6 +13591,9 @@ mp_number dx0, dy0; /* initial direction for the first cubic in the curve mp_number x0a, x1a, x2a, y0a, y1a, y2a; /* intermediate values */ mp_number t; /* where the derivative passes through zero */ mp_number s; /* a temporary value */ +mp_number dx_m; /* signal a pertubation of dx */ +mp_number dxin_m; /* signal a pertubation of dxin */ + @ @<Prepare for derivative computations...@>= set_number_from_substraction(x0, p->right_x, p->x_coord); @@ -13455,6 +13602,11 @@ set_number_from_substraction(x1, q->left_x, p->right_x); set_number_from_substraction(y0, p->right_y, p->y_coord); set_number_from_substraction(y2, q->y_coord, q->left_y); set_number_from_substraction(y1, q->left_y, p->right_y); +#ifdef DEBUGENVELOPE +dbg_key(Prepare for derivative computations);dbg_open_t;dbg_nl; +dbg_n(x0);dbg_n(y0);dbg_n(x1);dbg_n(y1);dbg_n(x2);dbg_n(y2); +dbg_close_t;dbg_comma;dbg_nl; +#endif { mp_number absval; new_number (absval); @@ -13698,6 +13850,7 @@ the true initial direction for the given cubic, even if it is almost degenerate. @<Find the initial direction |(dx,dy)|@>= +number_clone(dx_m, zero_t); number_clone(dx, x0); number_clone(dy, y0); if (number_zero(dx) && number_zero(dy)) { @@ -13712,8 +13865,72 @@ if (p == c) { number_clone(dx0, dx); number_clone(dy0, dy); } +/* BEGIN PATCH */ +set_number_from_substraction(ueps_ap,unity_t,epsilon_t); /* |1-eps| */ +#ifdef DEBUGENVELOPE +dbg_nl;dbg_key(mp_dx_dy_approx_t_1);dbg_open_t;dbg_nl; +dbg_n(ueps_ap); +dbg_n(p->x_coord);dbg_n(p->y_coord); +dbg_n(p->right_x);dbg_n(p->right_y); +dbg_n(q->left_x);dbg_n(q->left_y); +dbg_n(q->x_coord);dbg_n(q->y_coord); +#endif +mp_dx_dy_approx(mp,&dxin_ap,&dyin_ap,p,q,ueps_ap); +#ifdef DEBUGENVELOPE +dbg_n(dxin_ap);dbg_n(dyin_ap); +dbg_close_t;dbg_comma;dbg_nl; +#endif +/**/ +number_clone(ueps_ap,epsilon_t); +#ifdef DEBUGENVELOPE +dbg_nl;dbg_key(mp_dx_dy_approx_t_0);dbg_open_t;dbg_nl; +dbg_n(ueps_ap); +dbg_n(p->x_coord);dbg_n(p->y_coord); +dbg_n(p->right_x);dbg_n(p->right_y); +dbg_n(q->left_x);dbg_n(q->left_y); +dbg_n(q->x_coord);dbg_n(q->y_coord); +#endif +mp_dx_dy_approx(mp,&dx_ap,&dy_ap,p,q,ueps_ap); /*|eps|*/ +#ifdef DEBUGENVELOPE +dbg_n(dx_ap);dbg_n(dy_ap); +dbg_close_t;dbg_comma;dbg_nl; +dbg_key(derivatives);dbg_open_t;dbg_nl; +dbg_n(dx);dbg_n(dy);dbg_n(dx_ap);dbg_n(dy_ap);dbg_close_t;dbg_comma;dbg_nl; +#endif +/* BEGIN PATCH */ +if (number_zero(dx) && !(number_zero(dy)) && number_zero(x0) && number_zero(x2) && !number_zero(dxin) ){ + number_clone(dx_m, epsilon_t); + if (number_positive(x1)){ + set_number_from_addition (dx, dx, epsilon_t); + } else if (number_negative(x1)) { + set_number_from_substraction (dx, dx, epsilon_t); + } +} +/* this patch can conflict with the previous one */ +/* hm what about dx=dy=0 ? */ +if (number_zero(dx_ap) && !number_zero(dx)){ + set_number_to_zero(dx); + if (p == c) { + set_number_to_zero(dx0); + } + mp_warn(mp,"x component of derivative at t=0 approximated to zero."); + } +if (number_zero(dy_ap) && !number_zero(dy)){ + set_number_to_zero(dy); + if (p == c) { + set_number_to_zero(dy0); + } + mp_warn(mp,"y component of derivative at t=0 approximated to zero."); + } +#ifdef DEBUGENVELOPE +dbg_key(derivatives patched);dbg_open_t;dbg_nl; +dbg_n(dx);dbg_n(dy);dbg_n(dx_ap);dbg_n(dy_ap);dbg_close_t;dbg_comma;dbg_nl; +#endif +/* END PATCH */ + @ @<Find the final direction |(dxin,dyin)|@>= +number_clone(dxin_m, zero_t); number_clone(dxin, x2); number_clone(dyin, y2); if (number_zero(dxin) && number_zero(dyin)) { @@ -13724,6 +13941,45 @@ if (number_zero(dxin) && number_zero(dyin)) { number_clone(dyin, y0); } } +if (number_zero(dxin_ap) && !number_zero(dxin)){ + set_number_to_zero(dxin); + mp_warn(mp,"x component of derivative at t=1 approximated at zero"); + } +if (number_zero(dyin_ap) && !number_zero(dyin)){ + set_number_to_zero(dyin); + mp_warn(mp,"y component of derivative at t=1 approximated at zero"); + } +#ifdef DEBUGENVELOPE +dbg_key(dxin dyin);dbg_open_t;dbg_nl; +dbg_n(dxin);dbg_n(dyin); +dbg_close_t;dbg_comma; +#endif +/* BEGIN PATCH \par +$ 1/3 B'(t,X_0,X_1,X_2) = (1-t)^2X_0+2(1-t)tX_1+3t^2X_2 $ \par +$ 1/3 B'(t,X_0,X_1,X_2) = (X_0 + (-2X_1 + X_2))t^2 + (-2X_0 + 2X_1)t + X_0 $ \par +$ 1/3 B'(s,0,X_1,0) = (-2s^2 + 2s)X_1 \approx 2sX_1 $ for $s\rightarrow 0$ \par +$ 1/3 B'(1-s,0,X_1,0) = (-2s^2 + 2s)X_1 \approx 2sX_1 $ for $s\rightarrow 0$ $\par +*/ +/* Of course the same should be done for dy and dyin */ +if ( ((number_zero(dx)||number_positive(dx_m)) && number_positive(dy)) && + (number_zero(dxin) && number_positive(dyin)) ){ + number_clone(dx_m, epsilon_t); + number_clone(dxin_m, epsilon_t); + if (number_positive(x1)){ + set_number_from_addition (dxin, dxin, epsilon_t); + set_number_from_addition (dx, dx, epsilon_t); + } else if (number_negative(x1)) { + set_number_from_substraction (dxin, dxin, epsilon_t); + set_number_from_substraction (dx, dx, epsilon_t); + } else if (number_positive(x0)) { + set_number_from_addition (dxin, dxin, epsilon_t); + set_number_from_addition (dx, dx, epsilon_t); + } else if (number_negative(x0)) { + set_number_from_substraction (dxin, dxin, epsilon_t); + set_number_from_substraction (dx, dx, epsilon_t); + } +} +/* END PATCH ****/ @ The next step is to bracket the initial direction between consecutive edges of the pen polygon. We must be careful to turn clockwise only if @@ -13737,11 +13993,35 @@ right.) This code depends on |w0| being the offset for |(dxin,dyin)|. mp_number ab_vs_cd; new_number (ab_vs_cd); ab_vs_cd (ab_vs_cd, dy, dxin, dx, dyin); - turn_amt = mp_get_turn_amt (mp, w0, dx, dy, number_nonnegative(ab_vs_cd)); +#ifdef DEBUGENVELOPE +dbg_nl; +dbg_key(mp_get_turn_amt_dx_dy);dbg_open_t;dbg_str(--[==[call mp_get_turn_amt]==]);dbg_nl; +dbg_n(w0->x_coord);dbg_n(w0->y_coord);dbg_n(dx);dbg_n(dy);dbg_in(number_nonnegative(ab_vs_cd)); +#endif + turn_amt = mp_get_turn_amt (mp, w0, dx, dy, number_nonnegative(ab_vs_cd)); +#ifdef DEBUGENVELOPE +dbg_dn(turn_amt); +dbg_close_t;dbg_comma; +dbg_nl; +#endif free_number (ab_vs_cd); +#ifdef DEBUGENVELOPE +dbg_key(w0 before walk);dbg_open_t;dbg_nl; +dbg_n(w0->x_coord);dbg_n(w0->y_coord); +dbg_close_t;dbg_comma; +#endif w = mp_pen_walk (mp, w0, turn_amt); w0 = w; +#ifdef DEBUGENVELOPE +dbg_key(w0 after walk);dbg_open_t;dbg_nl; +dbg_n(w0->x_coord);dbg_n(w0->y_coord); +dbg_close_t;dbg_comma; +dbg_open_t;dbg_in(mp_knot_info(p)); +#endif mp_knot_info (p) = mp_knot_info (p) + turn_amt; +#ifdef DEBUGENVELOPE + dbg_in(mp_knot_info(p));dbg_close_t;dbg_comma; +#endif } @ Decide how many pen offsets to go away from |w| in order to find the offset @@ -13762,18 +14042,42 @@ integer mp_get_turn_amt (MP mp, mp_knot w, mp_number dx, mp_number dy, boolean c mp_knot ww; /* a neighbor of knot~|w| */ integer s; /* turn amount so far */ mp_number t; /* |ab_vs_cd| result */ + mp_number t_ap; /* |ab_vs_cd| approx. result */ mp_number arg1, arg2; s = 0; new_number (arg1); new_number (arg2); new_number (t); + new_number (t_ap); if (ccw) { ww = mp_next_knot (w); do { set_number_from_substraction (arg1, ww->x_coord, w->x_coord); set_number_from_substraction (arg2, ww->y_coord, w->y_coord); ab_vs_cd (t, dy, arg1, dx, arg2); - if (number_negative(t)) +#ifdef DEBUGENVELOPE + dbg_sp; + dbg_open_t;dbg_str(--[==[inside mp_get_turn_amt do loop ]==]);dbg_nl; + dbg_n(w->x_coord);dbg_n(w->y_coord);dbg_n(ww->x_coord);dbg_n(ww->y_coord); + dbg_n(t);dbg_n(dy);dbg_n(arg1);dbg_n(dx);dbg_n(arg2); + dbg_n(t_ap);dbg_n(dy_ap);dbg_n(dx_ap); + dbg_close_t;dbg_comma; + dbg_nl; +#endif + /* BEGIN PATCH */ + if (number_zero(dx) && number_zero(arg1) && number_positive(dy) && number_positive(arg2)) + break; + if (number_zero(dx) && number_zero(arg1) && number_negative(dy) && number_negative(arg2)) + break; + if (number_zero(dy) && number_zero(arg2) && number_negative(dx) && number_negative(arg1)) + break; + if (number_zero(dx) && number_zero(arg1) && number_negative(dy) && number_positive(arg2)) + set_number_to_unity(t); + if (number_zero(dy) && number_zero(arg2) && number_positive(dx) && number_negative(arg1)) + set_number_to_unity(t); + + /* END PATCH */ + if (number_negative(t)) break; incr (s); w = ww; @@ -13794,6 +14098,7 @@ integer mp_get_turn_amt (MP mp, mp_knot w, mp_number dx, mp_number dy, boolean c } } free_number (t); + free_number (t_ap); free_number (arg1); free_number (arg2); return s; @@ -13950,8 +14255,18 @@ the path should always change the sign of |turn_amt|. @<Decide on the net change in pen offsets and set |turn_amt|@>= { mp_number ab_vs_cd; + mp_number t_ap; + new_number (t_ap); new_number (ab_vs_cd); +#ifdef DEBUGENVELOPE +dbg_sp; +dbg_key(Decide on the net change in pen offsets and set turn_amt);dbg_open_t;dbg_nl; +#endif ab_vs_cd (ab_vs_cd, dx, dyin, dxin, dy); +#ifdef DEBUGENVELOPE +dbg_n(ab_vs_cd);dbg_n(dx);dbg_n(dyin);dbg_n(dxin);dbg_n(dy); +dbg_close_t;dbg_comma;dbg_nl; +#endif if (number_negative (ab_vs_cd)) d_sign = -1; else if (number_zero (ab_vs_cd)) @@ -13959,6 +14274,7 @@ the path should always change the sign of |turn_amt|. else d_sign = 1; free_number (ab_vs_cd); + free_number (t_ap); } if (d_sign == 0) { @<Check rotation direction based on node position@> @@ -13978,7 +14294,16 @@ if (d_sign == 0) { } @<Make |ss| negative if and only if the total change in direction is more than $180^\circ$@>; +#ifdef DEBUGENVELOPE +dbg_nl; +dbg_key(mp_get_turn_amt_dxin_dyin);dbg_open_t;dbg_str(--[==[call mp_get_turn_amt]==]);dbg_nl; ; +dbg_n(w->x_coord);dbg_n(w->y_coord);dbg_n(dxin);dbg_n(dyin);dbg_in((d_sign > 0)); +#endif turn_amt = mp_get_turn_amt (mp, w, dxin, dyin, (d_sign > 0)); +#ifdef DEBUGENVELOPE +dbg_dn(turn_amt); +dbg_close_t;dbg_nl;dbg_nl; +#endif if (number_negative(ss)) turn_amt = turn_amt - d_sign * n @@ -14024,13 +14349,18 @@ then swapped with |(x2,y2)|. We make use of the identities new_fraction (r2); take_fraction (r1, x0, y2); take_fraction (r2, x2, y0); +#ifdef DEBUGENVELOPE +dbg_sp; +dbg_open_t;dbg_dn(d_sign);dbg_close_t;dbg_comma;dbg_nl; +#endif number_half (r1); number_half (r2); set_number_from_substraction(t0, r1, r2); set_number_from_addition (arg1, y0, y2); take_fraction (r1, x1, arg1); set_number_from_addition (arg1, x0, x2); - take_fraction (r1, y1, arg1); + /*%take_fraction (r1, y1, arg1);*//* The old one, is it correct ?*/ + take_fraction (r2, y1, arg1); number_half (r1); number_half (r2); set_number_from_substraction(t1, r1, r2); @@ -14065,6 +14395,7 @@ if (number_positive(t0)) { } { mp_number tmp1, tmp2, r1, r2, arg1; + mp_number abs_ss, eps_ss; new_fraction (r1); new_fraction (r2); new_number(arg1); @@ -14077,6 +14408,28 @@ if (number_positive(t0)) { set_number_from_addition(arg1, y0, y2); take_fraction (r2, arg1, tmp2); set_number_from_addition (ss, r1, r2); + /* BEGIN PATCH */ +#ifdef DEBUGENVELOPE +dbg_key(patch ss before);dbg_open_t;dbg_nl; +dbg_n(ss); +dbg_close_t;dbg_comma;dbg_nl; +#endif + new_number(abs_ss); + new_number(eps_ss); + set_number_from_double(eps_ss,1e-6); + number_clone(abs_ss,ss); + number_abs(abs_ss); + if (number_greaterequal(eps_ss,abs_ss)) { + set_number_to_zero(ss);/* a warning here ? */ + } +#ifdef DEBUGENVELOPE +dbg_key(patch ss after);dbg_open_t;dbg_nl; +dbg_n(ss); +dbg_close_t;dbg_comma;dbg_nl; +#endif + free_number(abs_ss); + free_number(eps_ss); + /* END PATCH */ free_number (arg1); free_number (r1); free_number (r2); @@ -15915,8 +16268,8 @@ static mp_value_node mp_p_plus_fq (MP mp, mp_value_node p, mp_number f, } else { if (number_greaterequal (absv, coef_bound_k) && mp->watch_coefs) { mp_type (qq) = independent_needing_fix; - /* If we set this , then we can drop (mp_type(pp) == independent_needing_fix && mp->fix_needed) later */ - /* set_number_from_scaled (value_number (qq), indep_value(qq)); */ + /* If we set this , then we can drop |(mp_type(pp) == independent_needing_fix && mp->fix_needed)| later */ + /* |set_number_from_scaled (value_number (qq), indep_value(qq));| */ mp->fix_needed = true; } set_mp_link (r, (mp_node) s); @@ -16060,8 +16413,8 @@ static mp_value_node mp_p_plus_q (MP mp, mp_value_node p, mp_value_node q, } else { if (number_greaterequal(test, coef_bound_k) && mp->watch_coefs) { mp_type (qq) = independent_needing_fix; - /* If we set this , then we can drop (mp_type(pp) == independent_needing_fix && mp->fix_needed) later */ - /* set_number_from_scaled (value_number (qq), indep_value(qq)); */ + /* If we set this , then we can drop |(mp_type(pp) == independent_needing_fix && mp->fix_needed)| later */ + /* |set_number_from_scaled (value_number (qq), indep_value(qq));| */ mp->fix_needed = true; } set_mp_link (r, (mp_node) s); @@ -24675,7 +25028,7 @@ static void mp_do_nullary (MP mp, quarterword c) { { mp_number r; new_number (r); - /*mp_norm_rand (mp, &r);*/ + /*|mp_norm_rand (mp, &r)|;*/ m_norm_rand (r); mp->cur_exp.type = mp_known; set_cur_exp_value_number (r); @@ -24872,7 +25225,7 @@ static void mp_do_unary (MP mp, quarterword c) { { mp_number vvx; new_number (vvx); - /*mp_unif_rand (mp, &vvx, cur_exp_value_number ());*/ + /*|mp_unif_rand (mp, &vvx, cur_exp_value_number ());|*/ m_unif_rand (vvx, cur_exp_value_number ()); set_cur_exp_value_number (vvx); free_number (vvx); diff --git a/source/texk/web2c/mplibdir/mpmathbinary.w b/source/texk/web2c/mplibdir/mpmathbinary.w index f0d134a58e1f77c72de32f48dd907ee7a35c0a42..287243c6d26f9dafdfbdad31de8c7919eb6099dd 100644 --- a/source/texk/web2c/mplibdir/mpmathbinary.w +++ b/source/texk/web2c/mplibdir/mpmathbinary.w @@ -1100,6 +1100,24 @@ void mp_ab_vs_cd (MP mp, mp_number *ret, mp_number a_orig, mp_number b_orig, mp_ mpfr_set(b, (mpfr_ptr )b_orig.data.num, ROUNDING); mpfr_set(c, (mpfr_ptr )c_orig.data.num, ROUNDING); mpfr_set(d, (mpfr_ptr )d_orig.data.num, ROUNDING); + + mpfr_mul(q,a,b,ROUNDING); + mpfr_mul(r,c,d,ROUNDING); + cmp = mpfr_cmp(q,r); + if (cmp==0) { + mpfr_set(ret->data.num, zero, ROUNDING); + goto RETURN; + } + if (cmp>0) { + mpfr_set(ret->data.num, one, ROUNDING); + goto RETURN; + } + if (cmp<0) { + mpfr_set(ret->data.num, minusone, ROUNDING); + goto RETURN; + } + + /*TODO: remove this part of the code until RETURN */ @<Reduce to the case that |a,c>=0|, |b,d>0|@>; while (1) { mpfr_div(q,a,d, ROUNDING); diff --git a/source/texk/web2c/mplibdir/mpmathdecimal.w b/source/texk/web2c/mplibdir/mpmathdecimal.w index d0550c51a80c9c5d2bb109a2a1d4bd9b6061445c..6394372c5c7332c9d46ffde08762091996f15725 100644 --- a/source/texk/web2c/mplibdir/mpmathdecimal.w +++ b/source/texk/web2c/mplibdir/mpmathdecimal.w @@ -1213,11 +1213,21 @@ The result is $+1$, 0, or~$-1$ in the three respective cases. void mp_ab_vs_cd (MP mp, mp_number *ret, mp_number a_orig, mp_number b_orig, mp_number c_orig, mp_number d_orig) { decNumber q, r, test; /* temporary registers */ decNumber a, b, c, d; + decNumber ab, cd; (void)mp; decNumberCopy(&a, (decNumber *)a_orig.data.num); decNumberCopy(&b, (decNumber *)b_orig.data.num); decNumberCopy(&c, (decNumber *)c_orig.data.num); decNumberCopy(&d, (decNumber *)d_orig.data.num); + + decNumberMultiply (&ab, (decNumber *)a_orig.data.num, (decNumber *)b_orig.data.num, &set); + decNumberMultiply (&cd, (decNumber *)c_orig.data.num, (decNumber *)d_orig.data.num, &set); + decNumberCompare(ret->data.num, &ab, &cd, &set); + mp_check_decNumber(mp, ret->data.num, &set); + if (1>0) + return; + + @<Reduce to the case that |a,c>=0|, |b,d>0|@>; while (1) { decNumberDivide(&q,&a,&d, &set); @@ -1699,13 +1709,13 @@ static void sinecosine(decNumber *theangle, decNumber *c, decNumber *s) @c void mp_decimal_sin_cos (MP mp, mp_number z_orig, mp_number *n_cos, mp_number *n_sin) { decNumber rad; + double tmp; decNumber one_eighty; - decNumberFromInt32(&one_eighty, 180 * 16); + tmp = mp_number_to_double(z_orig)/16.0; + #if DEBUG fprintf(stdout, "\nsin_cos(%f)", mp_number_to_double(z_orig)); #endif - decNumberMultiply(&rad, z_orig.data.num, &PI_decNumber, &set); - decNumberDivide(&rad, &rad, &one_eighty, &set); #if 0 if (decNumberIsNegative(&rad)) { while (decNumberLess(&rad,&PI_decNumber)) @@ -1715,9 +1725,23 @@ void mp_decimal_sin_cos (MP mp, mp_number z_orig, mp_number *n_cos, mp_number *n decNumberSubtract(&rad, &rad, &PI_decNumber, &set); } #endif - sinecosine(&rad, n_sin->data.num, n_cos->data.num); - decNumberMultiply(n_cos->data.num,n_cos->data.num,&fraction_multiplier_decNumber, &set); - decNumberMultiply(n_sin->data.num,n_sin->data.num,&fraction_multiplier_decNumber, &set); + if ((tmp == 90.0)||(tmp == -270)){ + decNumberZero(n_cos->data.num); + decNumberCopy(n_sin->data.num,&fraction_multiplier_decNumber); + } else if ((tmp == -90.0)||(tmp == 270.0)) { + decNumberZero(n_cos->data.num); + decNumberCopyNegate(n_sin->data.num,&fraction_multiplier_decNumber); + } else if ((tmp == 180.0) || (tmp == -180.0)) { + decNumberCopyNegate(n_cos->data.num,&fraction_multiplier_decNumber); + decNumberZero(n_sin->data.num); + } else { + decNumberFromInt32(&one_eighty, 180 * 16); + decNumberMultiply(&rad, z_orig.data.num, &PI_decNumber, &set); + decNumberDivide(&rad, &rad, &one_eighty, &set); + sinecosine(&rad, n_sin->data.num, n_cos->data.num); + decNumberMultiply(n_cos->data.num,n_cos->data.num,&fraction_multiplier_decNumber, &set); + decNumberMultiply(n_sin->data.num,n_sin->data.num,&fraction_multiplier_decNumber, &set); + } #if DEBUG fprintf(stdout, "\nsin_cos(%f,%f,%f)", decNumberToDouble(&rad), mp_number_to_double(*n_cos), mp_number_to_double(*n_sin)); diff --git a/source/texk/web2c/mplibdir/mpmathdouble.w b/source/texk/web2c/mplibdir/mpmathdouble.w index d5663b2df97d56a8f943d83cc457288cf0c4abf5..75bd1e712c27a0b713f6e95cc0442235c3d552d9 100644 --- a/source/texk/web2c/mplibdir/mpmathdouble.w +++ b/source/texk/web2c/mplibdir/mpmathdouble.w @@ -814,6 +814,11 @@ void mp_ab_vs_cd (MP mp, mp_number *ret, mp_number a_orig, mp_number b_orig, mp_ integer q, r; /* temporary registers */ integer a, b, c, d; (void)mp; + + mp_double_ab_vs_cd(mp,ret, a_orig, b_orig, c_orig, d_orig); + if (1>0) + return ; + /* TODO: remove this code until the end */ a = a_orig.data.dval; b = b_orig.data.dval; c = c_orig.data.dval; @@ -1208,9 +1213,21 @@ any loss of accuracy. Then |x| and~|y| are divided by~|r|. @c void mp_double_sin_cos (MP mp, mp_number z_orig, mp_number *n_cos, mp_number *n_sin) { double rad; - rad = (z_orig.data.dval / angle_multiplier) * PI/180.0; - n_cos->data.dval = cos(rad) * fraction_multiplier; - n_sin->data.dval = sin(rad) * fraction_multiplier; + rad = (z_orig.data.dval / angle_multiplier); /* still degrees */ + if ((rad == 90.0)||(rad == -270)){ + n_cos->data.dval = 0.0; + n_sin->data.dval = fraction_multiplier; + } else if ((rad == -90.0)||(rad == 270.0)) { + n_cos->data.dval = 0.0; + n_sin->data.dval = -fraction_multiplier; + } else if ((rad == 180.0) || (rad == -180.0)) { + n_cos->data.dval = -fraction_multiplier; + n_sin->data.dval = 0.0; + } else { + rad = rad * PI/180.0; + n_cos->data.dval = cos(rad) * fraction_multiplier; + n_sin->data.dval = sin(rad) * fraction_multiplier; + } #if DEBUG fprintf(stdout, "\nsin_cos(%f,%f,%f)", mp_number_to_double(z_orig), mp_number_to_double(*n_cos), mp_number_to_double(*n_sin));