"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/Graphics/Fonts/smart_font.cpp" between
TeXmacs-1.99.4-src.tar.gz and TeXmacs-1.99.5-src.tar.gz

About: GNU TeXmacs is a what-you-see-is-what-you-get scientific text editor, which was both inspired by TeX and GNU Emacs.

smart_font.cpp  (TeXmacs-1.99.4-src):smart_font.cpp  (TeXmacs-1.99.5-src)
skipping to change at line 18 skipping to change at line 18
* It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
* in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>. * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
******************************************************************************/ ******************************************************************************/
#include "font.hpp" #include "font.hpp"
#include "convert.hpp" #include "convert.hpp"
#include "converter.hpp" #include "converter.hpp"
#include "Freetype/tt_tools.hpp" #include "Freetype/tt_tools.hpp"
#include "translator.hpp" #include "translator.hpp"
bool virtually_defined (string c, string name);
font smart_font_bis (string f, string v, string s, string sh, int sz, int d);
/****************************************************************************** /******************************************************************************
* Efficient computation of the appropriate subfont * Efficient computation of the appropriate subfont
******************************************************************************/ ******************************************************************************/
RESOURCE(smart_map); RESOURCE(smart_map);
#define SUBFONT_MAIN 0 #define SUBFONT_MAIN 0
#define SUBFONT_ERROR 1 #define SUBFONT_ERROR 1
#define REWRITE_NONE 0 #define REWRITE_NONE 0
#define REWRITE_MATH 1 #define REWRITE_MATH 1
#define REWRITE_CYRILLIC 2 #define REWRITE_CYRILLIC 2
#define REWRITE_LETTERS 3 #define REWRITE_LETTERS 3
#define REWRITE_SPECIAL 4 #define REWRITE_SPECIAL 4
#define REWRITE_POOR_BBB 5
#define REWRITE_ITALIC_GREEK 6
#define REWRITE_UPRIGHT_GREEK 7
struct smart_map_rep: rep<smart_map> { struct smart_map_rep: rep<smart_map> {
int chv[256]; int chv[256];
hashmap<string,int> cht; hashmap<string,int> cht;
hashmap<tree,int> fn_nr; hashmap<tree,int> fn_nr;
array<tree> fn_spec; array<tree> fn_spec;
array<int> fn_rewr; array<int> fn_rewr;
public: public:
smart_map_rep (string name, tree fn): smart_map_rep (string name, tree fn):
rep<smart_map> (name), cht (-1), fn_nr (-1), fn_spec (2), fn_rewr (2) rep<smart_map> (name), cht (-1), fn_nr (-1), fn_spec (2), fn_rewr (2)
{ {
(void) fn;
for (int i=0; i<256; i++) chv[i]= -1; for (int i=0; i<256; i++) chv[i]= -1;
fn_nr (tuple ("main" ))= SUBFONT_MAIN; fn_nr (tuple ("main" ))= SUBFONT_MAIN;
fn_nr (tuple ("error"))= SUBFONT_ERROR; fn_nr (tuple ("error"))= SUBFONT_ERROR;
fn_spec[SUBFONT_MAIN ]= tuple ("main"); fn_spec[SUBFONT_MAIN ]= tuple ("main");
fn_spec[SUBFONT_ERROR]= tuple ("error"); fn_spec[SUBFONT_ERROR]= tuple ("error");
fn_rewr[SUBFONT_MAIN ]= REWRITE_NONE; fn_rewr[SUBFONT_MAIN ]= REWRITE_NONE;
fn_rewr[SUBFONT_ERROR]= REWRITE_NONE; fn_rewr[SUBFONT_ERROR]= REWRITE_NONE;
} }
int int
skipping to change at line 97 skipping to change at line 104
* Virtual font handling * Virtual font handling
******************************************************************************/ ******************************************************************************/
static bool virt_initialized= false; static bool virt_initialized= false;
static array<string> std_virt; static array<string> std_virt;
static array<translator> std_trl; static array<translator> std_trl;
static void static void
initialize_virtual () { initialize_virtual () {
if (virt_initialized) return; if (virt_initialized) return;
std_virt << string ("long") << string ("negate") << string ("misc"); std_virt << string ("tradi-long")
<< string ("tradi-negate")
<< string ("tradi-misc");
for (int i=0; i<N(std_virt); i++) for (int i=0; i<N(std_virt); i++)
std_trl << load_translator (std_virt[i]); std_trl << load_translator (std_virt[i]);
virt_initialized= true; virt_initialized= true;
} }
static string static string
find_in_virtual (string c) { find_in_virtual (string c) {
initialize_virtual (); initialize_virtual ();
for (int i=0; i<N(std_virt); i++) for (int i=0; i<N(std_virt); i++)
if (std_trl[i]->dict->contains (c)) if (std_trl[i]->dict->contains (c))
return std_virt[i]; return std_virt[i];
return ""; return "";
} }
static bool gen_initialized= false;
static translator gen_trl;
static bool
find_in_emu_bracket (string c) {
if (!gen_initialized) {
gen_trl= load_translator ("emu-bracket");
gen_initialized= true;
}
return gen_trl->dict->contains (c);
}
static array<string>
emu_font_names () {
array<string> a;
a << string ("emu-fundamental")
<< string ("emu-greek")
<< string ("emu-operators")
<< string ("emu-relations")
<< string ("emu-orderings")
<< string ("emu-setrels")
<< string ("emu-arrows");
return a;
}
/****************************************************************************** /******************************************************************************
* Special characters in mathematical fonts * Special characters in mathematical fonts
******************************************************************************/ ******************************************************************************/
static string rewrite_math (string s); static string rewrite_math (string s);
static bool static bool
is_math_family (string f) { is_math_family (string f) {
return return
f == "roman" || f == "roman" ||
skipping to change at line 137 skipping to change at line 171
inline bool inline bool
is_letter (char c) { is_letter (char c) {
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
} }
static bool static bool
is_greek (string c) { is_greek (string c) {
static hashmap<string,bool> t (false); static hashmap<string,bool> t (false);
if (N(t) == 0) { if (N(t) == 0) {
array<int> a; array<int> a;
//for (int i= 0x391; i<0x3a9; i++) if (i != 0x3a2) a << i; //for (int i= 0x391; i<=0x3a9; i++) if (i != 0x3a2) a << i;
for (int i= 0x3b1; i<0x3c9; i++) a << i; for (int i= 0x3b1; i <= 0x3c9; i++) a << i;
a << 0x3d1 << 0x3d5 << 0x3d6 << 0x3f0 << 0x3f1 << 0x3f5;
for (int i= 0; i<N(a); i++) { for (int i= 0; i<N(a); i++) {
string s= upcase_all ("<#" * as_hexadecimal (a[i]) * ">"); string s= upcase_all ("<#" * as_hexadecimal (a[i]) * ">");
t (s)= true; t (s)= true;
t (locase_all (s))= true; t (locase_all (s))= true;
t (rewrite_math (s))= true; t (rewrite_math (s))= true;
} }
} }
return t[c]; return t[c];
} }
static bool
is_rubber (string c) {
return (starts (c, "<large-") ||
starts (c, "<left-") ||
starts (c, "<right-") ||
starts (c, "<mid-")) && ends (c, ">");
}
static hashmap<string,string> special_table (""); static hashmap<string,string> special_table ("");
static bool static bool
unicode_provides (string s) { unicode_provides (string s) {
return cork_to_utf8 (s) != s; return strict_cork_to_utf8 (s) != s;
} }
static bool static bool
is_special (string s) { is_special (string s) {
if (N (special_table) == 0) { if (N (special_table) == 0) {
special_table ("*")= ""; special_table ("*")= "";
special_table ("<noplus>")= ""; special_table ("<noplus>")= "";
special_table ("<nocomma>")= ""; special_table ("<nocomma>")= "";
special_table ("<nospace>")= ""; special_table ("<nospace>")= "";
special_table ("<nobracket>")= ""; special_table ("<nobracket>")= "";
special_table ("<nosymbol>")= ""; special_table ("<nosymbol>")= "";
special_table ("-")= "<minus>"; special_table ("-")= "<minus>";
special_table ("|")= "<mid>"; special_table ("|")= "<mid>";
special_table ("'")= "<#2B9>"; special_table ("'")= "<#2B9>";
special_table ("`")= "<backprime>"; special_table ("`")= "<backprime>";
special_table ("<hat>")= "<#2C6>";
special_table ("<tilde>")= "<#2DC>";
} }
if (starts (s, "<big-.")) if (starts (s, "<big-."))
special_table (s)= ""; special_table (s)= "";
if (starts (s, "<big-") && (ends (s, "-1>") || ends (s, "-2>"))) { if (starts (s, "<big-") && (ends (s, "-1>") || ends (s, "-2>"))) {
string ss= s (0, N(s)-3) * ">"; string ss= s (0, N(s)-3) * ">";
//cout << "Search " << ss << "\n"; //cout << "Search " << ss << "\n";
if (unicode_provides (ss)) if (unicode_provides (ss))
special_table (s)= ss; special_table (s)= ss;
ss= "<big" * s (5, N(s)-3) * ">"; ss= "<big" * s (5, N(s)-3) * ">";
//cout << "Search " << ss << "\n"; //cout << "Search " << ss << "\n";
skipping to change at line 230 skipping to change at line 275
static void static void
unicode_greek (int start, string fn) { unicode_greek (int start, string fn) {
unicode_subst (start, 0x391, 25, fn); // FIXME: attention to 0x3a2 unicode_subst (start, 0x391, 25, fn); // FIXME: attention to 0x3a2
unicode_subst (start + 25, 0x2207, 1, fn); unicode_subst (start + 25, 0x2207, 1, fn);
unicode_subst (start + 26, 0x3b1, 25, fn); unicode_subst (start + 26, 0x3b1, 25, fn);
unicode_subst (start + 51, 0x2202, 1, fn); unicode_subst (start + 51, 0x2202, 1, fn);
unicode_subst (start + 52, 0x3f5, 1, fn); unicode_subst (start + 52, 0x3f5, 1, fn);
unicode_subst (start + 53, 0x3d1, 1, fn); unicode_subst (start + 53, 0x3d1, 1, fn);
unicode_subst (start + 54, 0x3f0, 1, fn); unicode_subst (start + 54, 0x3f0, 1, fn);
unicode_subst (start + 55, 0x3d5, 1, fn); unicode_subst (start + 55, 0x3d5, 1, fn);
unicode_subst (start + 56, 0x3f1, 1, fn);
unicode_subst (start + 57, 0x3d6, 1, fn);
} }
static void static void
unicode_digits (int start, string fn) { unicode_digits (int start, string fn) {
unicode_subst (start, 0x30, 10, fn); unicode_subst (start, 0x30, 10, fn);
} }
static void static void
init_unicode_substitution () { init_unicode_substitution () {
if (N (substitution_char) != 0) return; if (N (substitution_char) != 0) return;
skipping to change at line 290 skipping to change at line 337
unicode_subst (0x210d, 0x48, 1, "bbb"); unicode_subst (0x210d, 0x48, 1, "bbb");
unicode_subst (0x2115, 0x4e, 1, "bbb"); unicode_subst (0x2115, 0x4e, 1, "bbb");
unicode_subst (0x2119, 0x50, 1, "bbb"); unicode_subst (0x2119, 0x50, 1, "bbb");
unicode_subst (0x211a, 0x51, 1, "bbb"); unicode_subst (0x211a, 0x51, 1, "bbb");
unicode_subst (0x211d, 0x52, 1, "bbb"); unicode_subst (0x211d, 0x52, 1, "bbb");
unicode_subst (0x2124, 0x5a, 1, "bbb"); unicode_subst (0x2124, 0x5a, 1, "bbb");
} }
int int
get_utf8_code (string c) { get_utf8_code (string c) {
string uc= cork_to_utf8 (c); string uc= strict_cork_to_utf8 (c);
int pos= 0; int pos= 0;
int code= decode_from_utf8 (uc, pos); int code= decode_from_utf8 (uc, pos);
if (pos == N(uc)) return code; if (pos == N(uc)) return code;
else return -1; else return -1;
} }
string string
substitute_math_letter (string c, int math_kind) { substitute_math_letter (string c, int math_kind) {
if (math_kind == 0) return ""; if (math_kind == 0) return "";
int code= get_utf8_code (c); int code= get_utf8_code (c);
skipping to change at line 317 skipping to change at line 364
//cout << c << " (" << nc << ") -> " << sc << ", " << sf << "\n"; //cout << c << " (" << nc << ") -> " << sc << ", " << sf << "\n";
if (sc != "" && sc != c) { if (sc != "" && sc != c) {
bool flag= ends (sf, "cal") || ends (sf, "frak") || ends (sf, "bbb"); bool flag= ends (sf, "cal") || ends (sf, "frak") || ends (sf, "bbb");
if (!flag || math_kind == 2) return sf; if (!flag || math_kind == 2) return sf;
} }
} }
return ""; return "";
} }
/****************************************************************************** /******************************************************************************
* Getting mathematical characters from unicode planes
******************************************************************************/
static hashmap<string,string> italic_greek ("");
static void
unicode_subst_back (int dest, int src, int nr, hashmap<string,string>& h) {
for (int i=0; i<nr; i++) {
string csrc = upcase_all ("<#" * as_hexadecimal (src + i) * ">");
string cdest= upcase_all ("<#" * as_hexadecimal (dest + i) * ">");
if (src + i < 128) csrc = string ((char) (src + i));
if (dest + i < 128) cdest= string ((char) (dest + i));
h (csrc)= cdest;
csrc= locase_all (csrc);
h (csrc)= cdest;
csrc= rewrite_math (csrc);
h (csrc)= cdest;
}
}
string
substitute_italic_greek (string c) {
hashmap<string,string>& h (italic_greek);
if (N (h) == 0) {
int start= 0x1d6e2;
unicode_subst_back (start, 0x391, 25, h); // FIXME: attention to 0x3a2
unicode_subst_back (start + 25, 0x2207, 1, h);
unicode_subst_back (start + 26, 0x3b1, 25, h);
unicode_subst_back (start + 51, 0x2202, 1, h);
unicode_subst_back (start + 52, 0x3f5, 1, h);
unicode_subst_back (start + 53, 0x3d1, 1, h);
unicode_subst_back (start + 54, 0x3f0, 1, h);
unicode_subst_back (start + 55, 0x3d5, 1, h);
unicode_subst_back (start + 56, 0x3f1, 1, h);
unicode_subst_back (start + 57, 0x3d6, 1, h);
}
if (!italic_greek->contains (c)) return "";
return italic_greek[c];
}
string
substitute_upright_greek (string c) {
if (!starts (c, "<up")) return "";
if (starts (c, "<up-")) c= "<" * c (4, N(c));
else if (starts (c, "<up")) c= "<" * c (3, N(c));
if (!is_greek (c)) return "";
return c;
}
/******************************************************************************
* Font sequences * Font sequences
******************************************************************************/ ******************************************************************************/
array<string> array<string>
trimmed_tokenize (string s, string sep) { trimmed_tokenize (string s, string sep) {
return trim_spaces (tokenize (s, sep)); return trim_spaces (tokenize (s, sep));
} }
string string
main_family (string f) { main_family (string f) {
skipping to change at line 338 skipping to change at line 435
for (int i=0; i<N(a); i++) for (int i=0; i<N(a); i++)
if (N (trimmed_tokenize (a[i], "=")) <= 1) if (N (trimmed_tokenize (a[i], "=")) <= 1)
return a[i]; return a[i];
if (N(a) == 0) return f; if (N(a) == 0) return f;
a= trimmed_tokenize (f, "="); a= trimmed_tokenize (f, "=");
return a[1]; return a[1];
} }
string string
get_unicode_range (string c) { get_unicode_range (string c) {
string uc= cork_to_utf8 (c); string uc= strict_cork_to_utf8 (c);
if (N(uc) == 0) return "";
int pos= 0; int pos= 0;
int code= decode_from_utf8 (uc, pos); int code= decode_from_utf8 (uc, pos);
string range= ""; string range= "";
if (code <= 0x7f) range= "ascii"; if (code <= 0x7f) range= "ascii";
else if (code >= 0x80 && code <= 0x37f) range= "latin"; else if (code >= 0x80 && code <= 0x37f) range= "latin";
else if (code >= 0x380 && code <= 0x3ff) range= "greek"; else if (code >= 0x380 && code <= 0x3ff) range= "greek";
else if (code >= 0x400 && code <= 0x4ff) range= "cyrillic"; else if (code >= 0x400 && code <= 0x4ff) range= "cyrillic";
else if (code >= 0x3000 && code <= 0x303f) range= "cjk"; else if (code >= 0x3000 && code <= 0x303f) range= "cjk";
else if (code >= 0x4e00 && code <= 0x9fcc) range= "cjk"; else if (code >= 0x4e00 && code <= 0x9fcc) range= "cjk";
else if (code >= 0xff00 && code <= 0xffef) range= "cjk"; else if (code >= 0xff00 && code <= 0xffef) range= "cjk";
else if (code >= 0xac00 && code <= 0xd7af) range= "hangul"; else if (code >= 0xac00 && code <= 0xd7af) range= "hangul";
else if (code >= 0x2000 && code <= 0x23ff) range= "mathsymbols"; else if (code >= 0x2000 && code <= 0x23ff) range= "mathsymbols";
else if (code >= 0x2900 && code <= 0x2e7f) range= "mathextra"; else if (code >= 0x2900 && code <= 0x2e7f) range= "mathextra";
else if (code >= 0x1d400 && code <= 0x1d7ff) range= "mathletters"; else if (code >= 0x1d400 && code <= 0x1d7ff) range= "mathletters";
if (pos == N(uc)) return range; if (pos == N(uc)) return range;
return ""; return "";
} }
/****************************************************************************** /******************************************************************************
* Font substitutions
******************************************************************************/
string
tex_gyre_fix (string family, string series, string shape) {
if (family == "bonum") family= "TeX Gyre Bonum";
if (family == "pagella") family= "TeX Gyre Pagella";
if (family == "schola") family= "TeX Gyre Schola";
if (family == "termes") family= "TeX Gyre Termes";
if (starts (family, "TeX Gyre")) {
if (starts (family, "TeX Gyre Bonum") ||
starts (family, "TeX Gyre Pagella") ||
starts (family, "TeX Gyre Schola") ||
starts (family, "TeX Gyre Termes")) {
if (shape == "mathitalic" && series == "medium") {
if (!ends (family, " Math")) family= family * " Math";
}
else if (ends (family, " Math"))
family= family (0, N(family) - 5);
}
}
return family;
}
string
stix_fix (string family, string series, string shape) {
if (family == "stix") family= "Stix";
if (starts (family, "Stix")) {
if (shape == "mathitalic" && series == "medium") {
if (!ends (family, " Math")) family= family * " Math";
}
else if (ends (family, " Math"))
family= family (0, N(family) - 5);
}
return family;
}
string
math_fix (string family, string series, string shape) {
if (starts (shape, "math")) {
array<string> a= trimmed_tokenize (family, ","), b;
for (int i=0; i<N(a); i++)
if (starts (a[i], "math=")) {
string mathfn= a[i] (5, N(a[i]));
mathfn= tex_gyre_fix (mathfn, series, shape);
//mathfn= stix_fix (mathfn, series, shape);
b << mathfn;
}
else b << a[i];
family= recompose (b, ",");
}
return family;
}
/******************************************************************************
* The smart font class * The smart font class
******************************************************************************/ ******************************************************************************/
typedef int int_vector[256]; typedef int int_vector[256];
typedef hashmap<string,int> int_table; typedef hashmap<string,int> int_table;
struct smart_font_rep: font_rep { struct smart_font_rep: font_rep {
string mfam; string mfam;
string family; string family;
string variant; string variant;
skipping to change at line 388 skipping to change at line 541
smart_font_rep (string name, font base_fn, font err_fn, smart_font_rep (string name, font base_fn, font err_fn,
string family, string variant, string family, string variant,
string series, string shape, int sz, int dpi); string series, string shape, int sz, int dpi);
font get_math_font (string fam, string var, string ser, string sh); font get_math_font (string fam, string var, string ser, string sh);
font get_cyrillic_font (string fam, string var, string ser, string sh); font get_cyrillic_font (string fam, string var, string ser, string sh);
font get_greek_font (string fam, string var, string ser, string sh); font get_greek_font (string fam, string var, string ser, string sh);
void advance (string s, int& pos, string& r, int& nr); void advance (string s, int& pos, string& r, int& nr);
int resolve (string c, string fam, int attempt); int resolve (string c, string fam, int attempt);
bool is_italic_prime (string c);
int resolve_rubber (string c, string fam, int attempt);
int resolve (string c); int resolve (string c);
void initialize_font (int nr); void initialize_font (int nr);
int adjusted_dpi (string fam, string var, string ser, string sh, int att); int adjusted_dpi (string fam, string var, string ser, string sh, int att);
bool supports (string c); bool supports (string c);
void get_extents (string s, metric& ex); void get_extents (string s, metric& ex);
void get_xpositions (string s, SI* xpos); void get_xpositions (string s, SI* xpos);
void get_xpositions (string s, SI* xpos, SI xk); void get_xpositions (string s, SI* xpos, SI xk);
void draw_fixed (renderer ren, string s, SI x, SI y); void draw_fixed (renderer ren, string s, SI x, SI y);
void draw_fixed (renderer ren, string s, SI x, SI y, SI xk); void draw_fixed (renderer ren, string s, SI x, SI y, SI xk);
font magnify (double zoom); font magnify (double zoomx, double zoomy);
void advance_glyph (string s, int& pos);
glyph get_glyph (string s); glyph get_glyph (string s);
int index_glyph (string s, font_metric& fnm, font_glyphs& fng);
double get_left_slope (string s); double get_left_slope (string s);
double get_right_slope (string s); double get_right_slope (string s);
SI get_left_correction (string s); SI get_left_correction (string s);
SI get_right_correction (string s); SI get_right_correction (string s);
}; };
smart_font_rep::smart_font_rep ( smart_font_rep::smart_font_rep (
string name, font base_fn, font err_fn, string family2, string variant2, string name, font base_fn, font err_fn, string family2, string variant2,
string series2, string shape2, int sz2, int dpi2): string series2, string shape2, int sz2, int dpi2):
font_rep (name, base_fn), mfam (main_family (family2)), font_rep (name, base_fn), mfam (main_family (family2)),
skipping to change at line 496 skipping to change at line 653
} }
static string static string
rewrite_math (string s) { rewrite_math (string s) {
string r; string r;
int i= 0, n= N(s); int i= 0, n= N(s);
while (i < n) { while (i < n) {
int start= i; int start= i;
tm_char_forwards (s, i); tm_char_forwards (s, i);
if (s[start] == '<' && start+1 < n && s[start+1] == '#' && s[i-1] == '>') if (s[start] == '<' && start+1 < n && s[start+1] == '#' && s[i-1] == '>')
r << utf8_to_cork (cork_to_utf8 (s (start, i))); r << utf8_to_cork (strict_cork_to_utf8 (s (start, i)));
else r << s (start, i); else r << s (start, i);
} }
return r; return r;
} }
static string static string
rewrite_letters (string s) { rewrite_letters (string s) {
init_unicode_substitution (); init_unicode_substitution ();
string r; string r;
int i= 0, n= N(s); int i= 0, n= N(s);
skipping to change at line 530 skipping to change at line 687
case REWRITE_NONE: case REWRITE_NONE:
return s; return s;
case REWRITE_MATH: case REWRITE_MATH:
return rewrite_math (s); return rewrite_math (s);
case REWRITE_CYRILLIC: case REWRITE_CYRILLIC:
return code_point_to_cyrillic_subset_in_t2a (s); return code_point_to_cyrillic_subset_in_t2a (s);
case REWRITE_LETTERS: case REWRITE_LETTERS:
return rewrite_letters (s); return rewrite_letters (s);
case REWRITE_SPECIAL: case REWRITE_SPECIAL:
return special_table [s]; return special_table [s];
case REWRITE_POOR_BBB:
return s (N(s)-2, N(s)-1);
case REWRITE_ITALIC_GREEK:
return substitute_italic_greek (s);
case REWRITE_UPRIGHT_GREEK:
return substitute_upright_greek (s);
default: default:
return s; return s;
} }
} }
/****************************************************************************** /******************************************************************************
* Smart font resolution * Smart font resolution
******************************************************************************/ ******************************************************************************/
void void
smart_font_rep::advance (string s, int& pos, string& r, int& nr) { smart_font_rep::advance (string s, int& pos, string& r, int& nr) {
int* chv= sm->chv; int* chv= sm->chv;
hashmap<string,int>& cht (sm->cht); hashmap<string,int>& cht (sm->cht);
int count= 0;
int start= pos; int start= pos;
nr= -1; nr= -1;
while (pos < N(s)) { while (pos < N(s)) {
if (s[pos] != '<') { if (s[pos] != '<') {
int c= (int) (unsigned char) s[pos]; int c= (int) (unsigned char) s[pos];
int next= chv[c]; int next= chv[c];
if (math_kind != 0 && math_kind != 2 && is_letter (c) && if (math_kind != 0 && math_kind != 2 && is_letter (c) &&
(pos == 0 || !is_letter (s[pos-1])) && (pos == 0 || !is_letter (s[pos-1])) &&
(pos+1 == N(s) || !is_letter (s[pos+1]))) (pos+1 == N(s) || !is_letter (s[pos+1])))
next= italic_nr; next= italic_nr;
else if (chv[c] == -1) next= resolve (s (pos, pos+1)); else if (chv[c] == -1) next= resolve (s (pos, pos+1));
if (next == nr) pos++; if (next == nr) pos++;
else if (nr == -1) { pos++; nr= next; } else if (nr == -1) { pos++; nr= next; }
else break; else break;
} }
else { else {
int end= pos; int end= pos;
tm_char_forwards (s, end); tm_char_forwards (s, end);
int next= cht[s (pos, end)]; int next= cht[s (pos, end)];
if (next == -1) next= resolve (s (pos, end)); if (next == -1) next= resolve (s (pos, end));
if (next == nr) pos= end; if (count == 1 && nr != -1 && next == nr) {
if (N(fn) <= nr || is_nil (fn[nr])) initialize_font (nr);
if (!fn[nr]->supports (s (start, end))) break;
pos= end;
}
else if (next == nr) pos= end;
else if (nr == -1) { pos= end; nr= next; } else if (nr == -1) { pos= end; nr= next; }
else break; else break;
} }
count++;
} }
r= s (start, pos); r= s (start, pos);
if (nr < 0) return; if (nr < 0) return;
if (N(fn) <= nr || is_nil (fn[nr])) initialize_font (nr); if (N(fn) <= nr || is_nil (fn[nr])) initialize_font (nr);
if (sm->fn_rewr[nr] != REWRITE_NONE) if (sm->fn_rewr[nr] != REWRITE_NONE)
r= rewrite (r, sm->fn_rewr[nr]); r= rewrite (r, sm->fn_rewr[nr]);
//cout << "Got " << r << " in " << fn[nr]->res_name << "\n"; //cout << "Got " << r << " in " << fn[nr]->res_name << "\n";
} }
bool
is_italic_font (string master) {
return contains (string ("italic"), master_features (master));
}
int int
smart_font_rep::resolve (string c, string fam, int attempt) { smart_font_rep::resolve (string c, string fam, int attempt) {
//cout << "Resolve " << c << " in " << fam << ", attempt " << attempt << "\n"; //cout << "Resolve " << c << " in " << fam << ", attempt " << attempt << "\n";
array<string> a= trimmed_tokenize (fam, "="); array<string> a= trimmed_tokenize (fam, "=");
if (N(a) >= 2) { if (N(a) >= 2) {
array<string> given= logical_font (family, variant, series, rshape); array<string> given= logical_font (family, variant, series, rshape);
fam= a[1]; fam= a[1];
array<string> b= tokenize (a[0], " "); array<string> b= tokenize (a[0], " ");
for (int i=0; i<N(b); i++) { for (int i=0; i<N(b); i++) {
if (b[i] == "") continue; if (b[i] == "") continue;
skipping to change at line 608 skipping to change at line 783
if (N(w) == 2) { if (N(w) == 2) {
int code = get_utf8_code (c); int code = get_utf8_code (c);
int start= get_utf8_code (w[0]); int start= get_utf8_code (w[0]);
int end = get_utf8_code (w[1]); int end = get_utf8_code (w[1]);
if (code != -1 && code >= start && code <= end) ok= true; if (code != -1 && code >= start && code <= end) ok= true;
} }
} }
} }
if (!ok) return -1; if (!ok) return -1;
} }
fam= tex_gyre_fix (fam, series, shape);
//fam= stix_fix (fam, series, shape);
} }
if (attempt == 1) { if (attempt == 1) {
bool ok= true; bool ok= true;
if (fam == "cal" || fam == "cal*" || if (fam == "cal" || fam == "cal*" ||
fam == "Bbb" || fam == "Bbb****") fam == "Bbb" || fam == "Bbb****")
ok= ok && is_alpha (c) && upcase_all (c) == c; ok= ok && is_alpha (c) && upcase_all (c) == c;
if (fam == "cal**" || fam == "Bbb*") if (fam == "cal**" || fam == "Bbb*")
ok= ok && is_alpha (c); ok= ok && is_alpha (c);
if (!ok) return -1; if (!ok) return -1;
if (fam == mfam) { if (fam == mfam) {
if (fn[SUBFONT_MAIN]->supports (c)) if (fn[SUBFONT_MAIN]->supports (c))
return sm->add_char (tuple ("main"), c); return sm->add_char (tuple ("main"), c);
} }
else { else {
font cfn= closest_font (fam, variant, series, rshape, sz, dpi, 1); font cfn= closest_font (fam, variant, series, rshape, sz, dpi, 1);
if (cfn->supports (c)) { if (cfn->supports (c)) {
tree key= tuple (fam, variant, series, rshape, "1"); tree key= tuple (fam, variant, series, rshape, "1");
int nr= sm->add_font (key, REWRITE_NONE);
initialize_font (nr);
return sm->add_char (key, c); return sm->add_char (key, c);
} }
} }
if (fam == "roman" && get_unicode_range (c) == "greek") { if (fam == "roman" && get_unicode_range (c) == "greek") {
tree key= tuple ("greek", fam, variant, series, rshape); tree key= tuple ("greek", fam, variant, series, rshape);
int nr= sm->add_font (key, REWRITE_NONE); int nr= sm->add_font (key, REWRITE_NONE);
initialize_font (nr); initialize_font (nr);
return sm->add_char (key, c); return sm->add_char (key, c);
} }
skipping to change at line 651 skipping to change at line 830
if (fn[nr]->supports (rewrite (c, REWRITE_MATH))) if (fn[nr]->supports (rewrite (c, REWRITE_MATH)))
return sm->add_char (key, c); return sm->add_char (key, c);
} }
if (fam == "roman" && N(c) > 1) { if (fam == "roman" && N(c) > 1) {
tree key= tuple ("cyrillic", fam, variant, series, rshape); tree key= tuple ("cyrillic", fam, variant, series, rshape);
int nr= sm->add_font (key, REWRITE_CYRILLIC); int nr= sm->add_font (key, REWRITE_CYRILLIC);
initialize_font (nr); initialize_font (nr);
if (fn[nr]->supports (rewrite (c, REWRITE_CYRILLIC))) if (fn[nr]->supports (rewrite (c, REWRITE_CYRILLIC)))
return sm->add_char (key, c); return sm->add_char (key, c);
} }
if (N(c) == 7 && starts (c, "<bbb-") && !occurs ("TeX Gyre", mfam)) {
font cfn= closest_font (fam, variant, series, rshape, sz, dpi, 1);
if (cfn->supports (c (N(c)-2, N(c)-1))) {
array<string> lfn= logical_font (fam, variant, series, rshape);
lfn= apply_substitutions (lfn);
array<string> pfn= search_font (lfn, 1);
array<string> ch = font_database_characteristics (pfn[0], pfn[1]);
double rat= ((double) cfn->yx) / ((double) cfn->wfn);
double hw = rat * get_up_pen_width (ch);
double vw = rat * get_up_pen_height (ch);
double lw = ((double) cfn->wline) / ((double) cfn->wfn);
hw= max (hw, 0.25 * lw);
vw= max (vw, 0.25 * lw);
tree key= tuple ("poor-bbb", as_string (hw), as_string (vw));
int nr= sm->add_font (key, REWRITE_POOR_BBB);
initialize_font (nr);
return sm->add_char (key, c);
}
}
if (fam == mfam && !is_italic_font (mfam)) {
array<string> emu_names= emu_font_names ();
for (int i=0; i<N(emu_names); i++)
if (virtually_defined (c, emu_names[i])) {
tree key= tuple ("emulate", emu_names[i]);
int nr= sm->add_font (key, REWRITE_NONE);
initialize_font (nr);
if (fn[nr]->supports (c))
return sm->add_char (key, c);
}
}
} }
if (attempt > 1) { if (attempt > 1) {
string range= get_unicode_range (c); string range= get_unicode_range (c);
if (range != "") { if (true) {
int a= attempt - 1; int a= attempt - 1;
string v= variant; string v;
if (v == "rm") v= range; if (range == "") v= variant;
else v= v * "-" * range; else if (v == "rm") v= range;
else v= variant * "-" * range;
font cfn= closest_font (fam, v, series, rshape, sz, dpi, a); font cfn= closest_font (fam, v, series, rshape, sz, dpi, a);
//cout << "Trying " << c << " in " << cfn->res_name << "\n"; //cout << "Trying " << c << " in " << cfn->res_name << "\n";
if (cfn->supports (c)) { if (cfn->supports (c)) {
tree key= tuple (fam, v, series, rshape, as_string (a)); tree key= tuple (fam, v, series, rshape, as_string (a));
int nr= sm->add_font (key, REWRITE_NONE);
initialize_font (nr);
return sm->add_char (key, c); return sm->add_char (key, c);
} }
} }
} }
return -1; return -1;
} }
bool
smart_font_rep::is_italic_prime (string c) {
if (c != "'" && c != "`") return false;
array<string> a= trimmed_tokenize (family, ",");
string s= "<#2B9>";
if (c == "`") s= "<backprime>";
for (int i= 0; i < N(a); i++)
if (resolve (s, a[i], 1) >= 0)
return false;
return true;
}
extern bool has_poor_rubber;
int
smart_font_rep::resolve_rubber (string c, string fam, int attempt) {
//cout << "Rubber " << c << ", " << fam << ", " << attempt << LF;
if (is_italic_font (mfam)) return -1;
int l= search_forwards ("-", 0, c) + 1;
int r= search_forwards ("-", l, c);
if (r == -1) r= N(c) - 1;
string ss= c (l, r);
string goal= ss;
if (N(goal) != 1) goal= "<" * goal * ">";
if (has_poor_rubber) {
if (goal == "<||>" || goal == "<interleave>") goal= "|";
if (goal == "<lfloor>" || goal == "<lceil>" ||
goal == "<llbracket>" || goal == "<dlfloor>" || goal == "<dlceil>" ||
goal == "<tlbracket>" || goal == "<tlfloor>" || goal == "<tlceil>")
goal= "[";
if (goal == "<rfloor>" || goal == "<rceil>" ||
goal == "<rrbracket>" || goal == "<drfloor>" || goal == "<drceil>" ||
goal == "<trbracket>" || goal == "<trfloor>" || goal == "<trceil>")
goal= "]";
}
int bnr= resolve (goal, fam, attempt);
if (bnr >= 0 && bnr < N(fn) && !is_nil (fn[bnr])) {
tree key= tuple ("rubber", as_string (bnr));
int nr= sm->add_font (key, REWRITE_NONE);
initialize_font (nr);
//cout << fn[nr]->res_name << " supports " << c
// << "? " << fn[nr]->supports (c) << LF;
if (fn[nr]->supports (c))
return sm->add_char (key, c);
}
return -1;
}
int int
smart_font_rep::resolve (string c) { smart_font_rep::resolve (string c) {
//cout << "Resolving " << c
// << " for " << mfam << ", " << family << ", " << variant
// << ", " << series << ", " << shape << ", " << rshape
// << "; " << fn[SUBFONT_MAIN]->res_name << "\n";
if (math_kind != 0) { if (math_kind != 0) {
if (is_greek (c)) string ugc= substitute_upright_greek (c);
if (ugc != "" && fn[SUBFONT_MAIN]->supports (ugc)) {
tree key= tuple ("upright-greek");
int nr= sm->add_font (key, REWRITE_UPRIGHT_GREEK);
initialize_font (nr);
return sm->add_char (key, c);
}
if (is_greek (c)) {
string gc= substitute_italic_greek (c);
if (gc != "" && fn[SUBFONT_MAIN]->supports (gc)) {
tree key= tuple ("italic-greek");
int nr= sm->add_font (key, REWRITE_ITALIC_GREEK);
initialize_font (nr);
return sm->add_char (key, c);
}
//cout << "Found " << c << " in greek\n";
return sm->add_char (tuple ("italic-math"), c); return sm->add_char (tuple ("italic-math"), c);
if (is_special (c)) }
if (is_italic_prime (c)) {
//cout << "Found " << c << " in italic prime\n";
return sm->add_char (tuple ("italic-math"), c);
}
if (is_special (c) && (c != "*" || !ends (variant, "-tt"))) {
//cout << "Found " << c << " in special\n";
return sm->add_char (tuple ("special"), c); return sm->add_char (tuple ("special"), c);
}
if (find_in_emu_bracket (c) && !is_italic_font (mfam)) {
//cout << "Found " << c << " in emu-bracket\n";
return sm->add_char (tuple ("virtual", "emu-bracket"), c);
}
} }
array<string> a= trimmed_tokenize (family, ","); array<string> a= trimmed_tokenize (family, ",");
for (int attempt= 1; attempt <= 20; attempt++) { for (int attempt= 1; attempt <= FONT_ATTEMPTS; attempt++) {
if (attempt > 1 && substitute_math_letter (c, math_kind) != "") break; if (attempt > 1 && substitute_math_letter (c, math_kind) != "") break;
for (int i= 0; i < N(a); i++) { for (int i= 0; i < N(a); i++) {
int nr= resolve (c, a[i], attempt); int nr= resolve (c, a[i], attempt);
if (nr >= 0) return nr; if (nr >= 0) {
//initialize_font (nr);
//cout << "Found " << c << " in " << fn[nr]->res_name << "\n";
return nr;
}
if (is_rubber (c)) nr= resolve_rubber (c, a[i], attempt);
if (nr >= 0) {
//cout << "Found " << c << " in poor-rubber\n";
return nr;
}
} }
} }
string sf= substitute_math_letter (c, math_kind); string sf= substitute_math_letter (c, math_kind);
if (sf != "") return sm->add_char (tuple (sf), c); if (sf != "") {
//cout << "Found " << c << " in " << sf << " (math-letter)\n";
return sm->add_char (tuple (sf), c);
}
string virt= find_in_virtual (c); string virt= find_in_virtual (c);
if (math_kind != 0 && !unicode_provides (c) && virt == "") if (math_kind != 0 && !unicode_provides (c) && virt == "") {
//cout << "Found " << c << " in other\n";
return sm->add_char (tuple ("other"), c); return sm->add_char (tuple ("other"), c);
}
if (virt != "") { if (virt != "") {
//cout << "Found " << c << " in " << virt << "\n"; //cout << "Found " << c << " in " << virt << "\n";
return sm->add_char (tuple ("virtual", virt), c); return sm->add_char (tuple ("virtual", virt), c);
} }
return sm->add_char (tuple ("error"), c); return sm->add_char (tuple ("error"), c);
} }
void void
skipping to change at line 717 skipping to change at line 1021
if (N(fn) <= nr) fn->resize (nr+1); if (N(fn) <= nr) fn->resize (nr+1);
if (!is_nil (fn[nr])) return; if (!is_nil (fn[nr])) return;
array<string> a= tuple_as_array (sm->fn_spec[nr]); array<string> a= tuple_as_array (sm->fn_spec[nr]);
if (a[0] == "math") if (a[0] == "math")
fn[nr]= get_math_font (a[1], a[2], a[3], a[4]); fn[nr]= get_math_font (a[1], a[2], a[3], a[4]);
else if (a[0] == "cyrillic") else if (a[0] == "cyrillic")
fn[nr]= get_cyrillic_font (a[1], a[2], a[3], a[4]); fn[nr]= get_cyrillic_font (a[1], a[2], a[3], a[4]);
else if (a[0] == "greek") else if (a[0] == "greek")
fn[nr]= get_greek_font (a[1], a[2], a[3], a[4]); fn[nr]= get_greek_font (a[1], a[2], a[3], a[4]);
else if (a[0] == "special") else if (a[0] == "special")
fn[nr]= smart_font (family, variant, series, "right", sz, dpi); fn[nr]= smart_font_bis (family, variant, series, "right", sz, dpi);
else if (a[0] == "other") { else if (a[0] == "other") {
int ndpi= adjusted_dpi ("roman", variant, series, "mathitalic", 1); int ndpi= adjusted_dpi ("roman", variant, series, "mathitalic", 1);
fn[nr]= smart_font ("roman", variant, series, "mathitalic", sz, ndpi); fn[nr]= smart_font_bis ("roman", variant, series, "mathitalic", sz, ndpi);
} }
else if (a[0] == "bold-math") else if (a[0] == "bold-math")
fn[nr]= smart_font (family, variant, "bold", "right", sz, dpi); fn[nr]= smart_font_bis (family, variant, "bold", "right", sz, dpi);
else if (a[0] == "fast-italic") else if (a[0] == "fast-italic")
fn[nr]= smart_font (family, variant, series, "italic", sz, dpi); fn[nr]= smart_font_bis (family, variant, series, "italic", sz, dpi);
else if (a[0] == "italic-math") else if (a[0] == "italic-math")
fn[nr]= smart_font (family, variant, series, "italic", sz, dpi); fn[nr]= smart_font_bis (family, variant, series, "italic", sz, dpi);
else if (a[0] == "bold-italic-math") else if (a[0] == "bold-italic-math")
fn[nr]= smart_font (family, variant, "bold", "italic", sz, dpi); fn[nr]= smart_font_bis (family, variant, "bold", "italic", sz, dpi);
else if (a[0] == "italic-greek")
fn[nr]= fn[SUBFONT_MAIN];
else if (a[0] == "upright-greek")
fn[nr]= fn[SUBFONT_MAIN];
else if (a[0] == "tt") else if (a[0] == "tt")
fn[nr]= smart_font (family, "tt", series, "right", sz, dpi); fn[nr]= smart_font_bis (family, "tt", series, "right", sz, dpi);
else if (a[0] == "ss") else if (a[0] == "ss")
fn[nr]= smart_font (family, "tt", series, "right", sz, dpi); fn[nr]= smart_font_bis (family, "tt", series, "right", sz, dpi);
else if (a[0] == "bold-ss") else if (a[0] == "bold-ss")
fn[nr]= smart_font (family, "tt", "bold", "right", sz, dpi); fn[nr]= smart_font_bis (family, "tt", "bold", "right", sz, dpi);
else if (a[0] == "italic-ss") else if (a[0] == "italic-ss")
fn[nr]= smart_font (family, "tt", series, "italic", sz, dpi); fn[nr]= smart_font_bis (family, "tt", series, "italic", sz, dpi);
else if (a[0] == "bold-italic-ss") else if (a[0] == "bold-italic-ss")
fn[nr]= smart_font (family, "tt", "bold", "italic", sz, dpi); fn[nr]= smart_font_bis (family, "tt", "bold", "italic", sz, dpi);
else if (a[0] == "cal" && N(a) == 1) else if (a[0] == "cal" && N(a) == 1)
fn[nr]= smart_font (family, "calligraphic", series, "italic", sz, dpi); fn[nr]= smart_font_bis (family, "calligraphic", series, "italic", sz, dpi);
else if (a[0] == "bold-cal") else if (a[0] == "bold-cal")
fn[nr]= smart_font (family, "calligraphic", "bold", "italic", sz, dpi); fn[nr]= smart_font_bis (family, "calligraphic", "bold", "italic", sz, dpi);
else if (a[0] == "frak") else if (a[0] == "frak")
fn[nr]= smart_font (family, "gothic", series, "right", sz, dpi); fn[nr]= smart_font_bis (family, "gothic", series, "right", sz, dpi);
else if (a[0] == "bold-frak") else if (a[0] == "bold-frak")
fn[nr]= smart_font (family, "gothic", "bold", "right", sz, dpi); fn[nr]= smart_font_bis (family, "gothic", "bold", "right", sz, dpi);
else if (a[0] == "bbb" && N(a) == 1) else if (a[0] == "bbb" && N(a) == 1)
fn[nr]= smart_font (family, "outline", series, "right", sz, dpi); fn[nr]= smart_font_bis (family, "outline", series, "right", sz, dpi);
else if (a[0] == "virtual") else if (a[0] == "virtual")
fn[nr]= virtual_font (this, a[1], sz, dpi); fn[nr]= virtual_font (this, a[1], sz, dpi, dpi, false);
else if (a[0] == "emulate") {
font vfn= fn[SUBFONT_MAIN];
if (a[1] != "emu-fundamental")
vfn= virtual_font (vfn, "emu-fundamental", sz, dpi, dpi, true);
fn[nr]= virtual_font (vfn, a[1], sz, dpi, dpi, true);
}
else if (a[0] == "poor-bbb" && N(a) == 3) {
double pw= as_double (a[1]);
double ph= as_double (a[2]);
font sfn= smart_font_bis (family, variant, series, "right", sz, dpi);
fn[nr]= poor_bbb_font (sfn, pw, ph, 1.5*pw); }
else if (a[0] == "rubber" && N(a) == 2 && is_int (a[1])) {
initialize_font (as_int (a[1]));
fn[nr]= rubber_font (fn[as_int (a[1])]);
//fn[nr]= rubber_unicode_font (fn[as_int (a[1])]);
}
else { else {
int ndpi= adjusted_dpi (a[0], a[1], a[2], a[3], as_int (a[4])); int ndpi= adjusted_dpi (a[0], a[1], a[2], a[3], as_int (a[4]));
fn[nr]= closest_font (a[0], a[1], a[2], a[3], sz, ndpi, as_int (a[4])); fn[nr]= closest_font (a[0], a[1], a[2], a[3], sz, ndpi, as_int (a[4]));
} }
//cout << "Font " << nr << ", " << a << " -> " << fn[nr]->res_name << "\n"; //cout << "Font " << nr << ", " << a << " -> " << fn[nr]->res_name << "\n";
if (fn[nr]->res_name == res_name) { if (fn[nr]->res_name == res_name) {
failed_error << "Font " << nr << ", " << a failed_error << "Font " << nr << ", " << a
<< " -> " << fn[nr]->res_name << "\n"; << " -> " << fn[nr]->res_name << "\n";
FAILED ("substitution font loop detected"); FAILED ("substitution font loop detected");
} }
skipping to change at line 933 skipping to change at line 1257
fn[nr]->draw_fixed (ren, r, x, y, xk); fn[nr]->draw_fixed (ren, r, x, y, xk);
if (i < n) { if (i < n) {
fn[nr]->get_extents (r, ey, xk); fn[nr]->get_extents (r, ey, xk);
x += ey->x2; x += ey->x2;
} }
} }
} }
} }
font font
smart_font_rep::magnify (double zoom) { smart_font_rep::magnify (double zoomx, double zoomy) {
return smart_font (family, variant, series, shape, sz, if (zoomx != zoomy) return poor_magnify (zoomx, zoomy);
(int) tm_round (dpi * zoom)); return smart_font_bis (family, variant, series, shape, sz,
(int) tm_round (dpi * zoomx));
} }
/****************************************************************************** /******************************************************************************
* Other routines for fonts * Other routines for fonts
******************************************************************************/ ******************************************************************************/
void
smart_font_rep::advance_glyph (string s, int& pos) {
if (pos >= N(s)) return;
int i= pos, nr;
string r= s;
advance (s, i, r, nr);
if (nr < 0) { tm_char_forwards (s, pos); return; }
int pos2= 0;
fn[nr]->advance_glyph (r, pos2);
if (pos + pos2 <= N(s) && r (0, pos2) == s (pos, pos+pos2)) pos += pos2;
else tm_char_forwards (s, pos);
}
glyph glyph
smart_font_rep::get_glyph (string s) { smart_font_rep::get_glyph (string s) {
int i=0, n= N(s), nr; int i=0, n= N(s), nr;
if (n == 0) return fn[0]->get_glyph (s); if (n == 0) return fn[0]->get_glyph (s);
string r= s; string r= s;
advance (s, i, r, nr); advance (s, i, r, nr);
if (nr<0) return glyph (); if (nr < 0) return glyph ();
return fn[nr]->get_glyph (r); return fn[nr]->get_glyph (r);
} }
int
smart_font_rep::index_glyph (string s, font_metric& fnm, font_glyphs& fng) {
int i=0, n= N(s), nr;
if (n == 0) return -1;
string r= s;
advance (s, i, r, nr);
if (nr < 0) return -1;
return fn[nr]->index_glyph (r, fnm, fng);
}
double double
smart_font_rep::get_left_slope (string s) { smart_font_rep::get_left_slope (string s) {
int i=0, n= N(s), nr; int i=0, n= N(s), nr;
if (n == 0) return fn[0]->get_left_slope (s); if (n == 0) return fn[0]->get_left_slope (s);
string r= s; string r= s;
advance (s, i, r, nr); advance (s, i, r, nr);
nr= max (nr, 0); nr= max (nr, 0);
return fn[nr]->get_left_slope (r); return fn[nr]->get_left_slope (r);
} }
skipping to change at line 997 skipping to change at line 1345
while (i<n) advance (s, i, r, nr); while (i<n) advance (s, i, r, nr);
nr= max (nr, 0); nr= max (nr, 0);
return fn[nr]->get_right_correction (r); return fn[nr]->get_right_correction (r);
} }
/****************************************************************************** /******************************************************************************
* User interface * User interface
******************************************************************************/ ******************************************************************************/
font font
smart_font (string family, string variant, string series, string shape, smart_font_bis (string family, string variant, string series, string shape,
int sz, int dpi) { int sz, int dpi) {
if (!new_fonts) return find_font (family, variant, series, shape, sz, dpi); if (!new_fonts) return find_font (family, variant, series, shape, sz, dpi);
string name=
family * "-" * variant * "-" *
series * "-" * shape * "-" *
as_string (sz) * "-" * as_string (dpi) * "-smart";
if (font::instances->contains (name)) return font (name);
if (starts (family, "tc")) if (starts (family, "tc"))
// FIXME: temporary hack for symbols from std-symbol.ts // FIXME: temporary hack for symbols from std-symbol.ts
return find_font (family, variant, series, shape, sz, dpi); return find_font (family, variant, series, shape, sz, dpi);
if (starts (family, "sys-")) { if (starts (family, "sys-")) {
if (family == "sys-chinese") { if (family == "sys-chinese") {
string name= default_chinese_font_name (); string name= default_chinese_font_name ();
family= "cjk=" * name * ",roman"; family= "cjk=" * name * ",roman";
} }
if (family == "sys-japanese") { if (family == "sys-japanese") {
string name= default_japanese_font_name (); string name= default_japanese_font_name ();
family= "cjk=" * name * ",roman"; family= "cjk=" * name * ",roman";
} }
if (family == "sys-korean") { if (family == "sys-korean") {
string name= default_korean_font_name (); string name= default_korean_font_name ();
family= "cjk=" * name * ",roman"; family= "cjk=" * name * ",roman";
} }
} }
family= tex_gyre_fix (family, series, shape);
string name= //family= stix_fix (family, series, shape);
family * "-" * variant * "-" * family= math_fix (family, series, shape);
series * "-" * shape * "-" *
as_string (sz) * "-" * as_string (dpi) * "-smart";
if (font::instances->contains (name)) return font (name);
if (starts (shape, "math")) {
array<string> a= trimmed_tokenize (family, ","), b;
for (int i=0; i<N(a); i++)
if (starts (a[i], "math=")) b << a[i] (5, N(a[i]));
else b << a[i];
family= recompose (b, ",");
}
string sh= shape; string sh= shape;
if (shape == "mathitalic" || shape == "mathshape") sh= "right"; if (shape == "mathitalic" || shape == "mathshape") sh= "right";
string mfam= main_family (family); string mfam= main_family (family);
font base_fn= closest_font (mfam, variant, series, sh, sz, dpi); font base_fn= closest_font (mfam, variant, series, sh, sz, dpi);
if (is_nil (base_fn)) return font (); if (is_nil (base_fn)) return font ();
font sec_fn= closest_font ("roman", "ss", "medium", "right", sz, dpi); font sec_fn= closest_font ("roman", "ss", "medium", "right", sz, dpi);
font err_fn= error_font (sec_fn); font err_fn= error_font (sec_fn);
return make (font, name, return make (font, name,
tm_new<smart_font_rep> (name, base_fn, err_fn, family, variant, tm_new<smart_font_rep> (name, base_fn, err_fn, family, variant,
series, shape, sz, dpi)); series, shape, sz, dpi));
} }
font font
smart_font (string family, string variant, string series, string shape, smart_font (string family, string variant, string series, string shape,
int sz, int dpi) {
if (variant == "rm")
return smart_font_bis (family, variant, series, shape, sz, dpi);
array<string> lfn1= logical_font (family, "rm", series, shape);
array<string> lfn2= logical_font (family, variant, series, shape);
array<string> pfn1= search_font (lfn1, 1);
array<string> pfn2= search_font (lfn2, 1);
if (N(pfn1) > 0 && N(pfn2) > 0 && pfn1[0] == pfn2[0])
return smart_font_bis (family, variant, series, shape, sz, dpi);
font fn1= smart_font_bis (family, "rm", series, shape, sz, dpi);
font fn2= smart_font_bis (family, variant, series, shape, sz, dpi);
double zoom= ((double) fn1->yx) / max (((double) fn2->yx), 1.0);
if (fn1->yx < PIXEL || fn2->yx < PIXEL) zoom= 1.0;
if (zoom > 0.975 && zoom < 1.025) return fn2;
return fn2->magnify (zoom);
}
font
smart_font (string family, string variant, string series, string shape,
string tfam, string tvar, string tser, string tsh, string tfam, string tvar, string tser, string tsh,
int sz, int dpi) { int sz, int dpi) {
if (!new_fonts) return find_font (family, variant, series, shape, sz, dpi); if (!new_fonts) return find_font (family, variant, series, shape, sz, dpi);
if (tfam == "roman") tfam= family; if (tfam == "roman") tfam= family;
if (variant != "mr") { if (variant != "mr") {
if (variant == "ms") tvar= "ss"; if (variant == "ms") tvar= "ss";
if (variant == "mt") tvar= "tt"; if (variant == "mt") tvar= "tt";
} }
if (shape == "right") tsh= "mathupright"; if (shape == "right") tsh= "mathupright";
return smart_font (tfam, tvar, tser, tsh, sz, dpi); return smart_font (tfam, tvar, tser, tsh, sz, dpi);
} }
static double
get_parameter (string val, int i, double def) {
array<string> a= trimmed_tokenize (val, ";");
if (i < N(a) && is_double (a[i])) return as_double (a[i]);
return def;
}
font
apply_effects (font fn, string effects) {
if (N(effects) == 0) return fn;
array<string> a= trimmed_tokenize (effects, ",");
for (int i=0; i<N(a); i++) {
array<string> b= trimmed_tokenize (a[i], "=");
if (N(b) == 2) {
if (b[0] == "bold" && is_double (b[1])) {
double emb= as_double (b[1]);
if (emb < 1.0) emb= 1.0;
if (emb > 5.0) emb= 5.0;
double fat= ((emb - 1.0) * fn->wline) / fn->wfn;
fn= poor_bold_font (fn, fat, fat);
}
else if (b[0] == "bbb" && is_double (b[1])) {
double emb= as_double (b[1]);
if (emb < 1.0) emb= 1.0;
if (emb > 5.0) emb= 5.0;
double penw= ((double) fn->wline) / ((double) fn->wfn);
double penh= ((double) fn->wline) / ((double) fn->wfn);
double fat = ((emb - 1.0) * fn->wline) / fn->wfn;
fn= poor_bbb_font (fn, penw, penh, fat);
}
else if (b[0] == "slant" && is_double (b[1])) {
double slant= as_double (b[1]);
if (slant < -2.0) slant= -2.0;
if (slant > 2.0) slant= 2.0;
fn= poor_italic_font (fn, slant);
}
else if (b[0] == "hmagnify" && is_double (b[1])) {
double xmag= as_double (b[1]);
if (xmag < 0.1) xmag= 0.1;
if (xmag > 10.0) xmag= 10.0;
fn= poor_stretched_font (fn, xmag, 1.0);
}
else if (b[0] == "vmagnify" && is_double (b[1])) {
double ymag= as_double (b[1]);
if (ymag < 0.1) ymag= 0.1;
if (ymag > 10.0) ymag= 10.0;
fn= poor_stretched_font (fn, 1.0, ymag);
}
else if (b[0] == "hextended" && is_double (b[1])) {
double xf= as_double (b[1]);
if (xf < 0.1) xf= 0.1;
if (xf > 10.0) xf= 10.0;
fn= poor_extended_font (fn, xf);
}
/*
else if (b[0] == "vextended" && is_double (b[1])) {
double yf= as_double (b[1]);
if (yf < 0.1) yf= 0.1;
if (yf > 10.0) yf= 10.0;
fn= poor_vextended_font (fn, yf);
}
*/
else if (b[0] == "degraded") {
double threshold= get_parameter (b[1], 0, 0.666);
double freq = get_parameter (b[1], 1, 1.0);
if (threshold < 0.01) threshold= 0.01;
if (threshold > 0.99) threshold= 0.99;
if (freq < 0.10) freq= 0.10;
if (freq > 10.0) freq= 10.0;
tree kind= tuple ("degraded", as_string (threshold), as_string (freq));
fn= poor_distorted_font (fn, kind);
}
else if (b[0] == "distorted") {
double strength= get_parameter (b[1], 0, 1.0);
double freq = get_parameter (b[1], 1, 1.0);
if (strength < 0.1) strength= 0.1;
if (strength > 9.9) strength= 9.9;
if (freq < 0.10) freq= 0.10;
if (freq > 10.0) freq= 10.0;
tree kind= tuple ("distorted", as_string (strength), as_string (freq));
fn= poor_distorted_font (fn, kind);
}
else if (b[0] == "gnawed") {
double strength= get_parameter (b[1], 0, 1.0);
double freq = get_parameter (b[1], 1, 1.0);
if (strength < 0.1) strength= 0.1;
if (strength > 9.9) strength= 9.9;
if (freq < 0.10) freq= 0.10;
if (freq > 10.0) freq= 10.0;
tree kind= tuple ("gnawed", as_string (strength), as_string (freq));
fn= poor_distorted_font (fn, kind);
}
}
}
return fn;
}
 End of changes. 65 change blocks. 
60 lines changed or deleted 422 lines changed or added

Home  |  About  |  All  |  Newest  |  Fossies Dox  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTPS