# HG changeset patch # User Michael Goffioul # Date 1376858206 14400 # Node ID 8ce6cdd272eb05f484470947dc09b26daedb9e42 # Parent cb7233cfbf4335163ec4090b8501ddcf55c4841d Support TeX elements in FreeType renderer. * libinterp/corefcn/txt-eng.cc: New file. Contains mapping from symbol name to character code, in Unicode and MS symbol. * libinterp/corefcn/modules.mk (COREFCN_SRC): Add txt-eng.cc. * libinterp/corefcn/oct-tex-lexer.ll: Add "\n" to rules applicable to ".", as the latter does not include new line characters. * libinterp/corefcn/oct-tex-parser.yy: Remove debug statements. * libinterp/corefcn/txt-eng.ft.cc (gripe_missing_glyph, gripe_glyph_render): Change signature from char to FT_ULong. (ft_render::ft_render): Adapt to new/removed members. (ft_render::~ft_render): Remove use of fonts member. (ft_render::set_font): Likewise. Use font instead. (ft_render::push_new_line): Likewise. Change meaning of yoffset and initialize line_yoffset. (ft_render::update_line_bbox): New method. (ft_render::set_mode): Change meaning of yoffset and initialize line_yoffset. (ft_render::process_character): New method. (ft_render::visit(text_element_string)): Use it. (ft_render::visit(text_element_list), ft_render::visit(text_element_subscript), ft_render::visit(text_element_superscript), ft_render::visit(text_element_color), ft_render::visit(text_element_fontsize), ft_render::visit(text_element_fontname), ft_render::visit(text_element_fontstyle), ft_render::visit(text_element_symbol)): New methods. (ft_render::set_color): Use color member instead of red/green/blue. * libinterp/corefcn/txt-eng-ft.h (ft_render::visit(text_element_list), ft_render::visit(text_element_subscript), ft_render::visit(text_element_superscript), ft_render::visit(text_element_color), ft_render::visit(text_element_fontsize), ft_render::visit(text_element_fontname), ft_render::visit(text_element_fontstyle), ft_render::visit(text_element_symbol)): New methods. (ft_render::update_line_bbox, ft_render::process_character): New methods. (ft_render::current_face): Removed method.i (ft_render::font): New member, replaces obsolete ft_render::fonts. (ft_render::line_yoffset): New member. (ft_render::color): New member, replaces obsolete red, green and blue. (ft_render::ft_font::ft_font()): Implement default constructor. (ft_render::ft_font::operator=): Fix incorrect use of FT_Reference_Face return value. (ft_render::ft_font::is_valid): New method. * libinterp/corefcn/txt-eng.h (class text_element_symbol, class text_element_fontname, class text_element_fontsize, class text_element_fontname, class text_element_fontstyle, class text_element_color): Add forward definition. (text_element_symbol::invalid_code): New enum. (text_element_symbol::code): New member. (text_element_symbol::text_element_symbol): Initialize it. (text_element_symbol::get_symbol_code): New method. (text_element_fontstyle::get_fontstyle): New method. (text_element_fontname::get_fontname): Renamed from fontname. (text_element_fontsize::get_fontsize): Renamed from fontsize. diff -r cb7233cfbf43 -r 8ce6cdd272eb libinterp/corefcn/module.mk --- a/libinterp/corefcn/module.mk Sun Aug 18 16:36:44 2013 -0400 +++ b/libinterp/corefcn/module.mk Sun Aug 18 16:36:46 2013 -0400 @@ -242,6 +242,7 @@ corefcn/time.cc \ corefcn/toplev.cc \ corefcn/tril.cc \ + corefcn/txt-eng.cc \ corefcn/txt-eng-ft.cc \ corefcn/typecast.cc \ corefcn/unwind-prot.cc \ diff -r cb7233cfbf43 -r 8ce6cdd272eb libinterp/corefcn/oct-tex-lexer.ll --- a/libinterp/corefcn/oct-tex-lexer.ll Sun Aug 18 16:36:44 2013 -0400 +++ b/libinterp/corefcn/oct-tex-lexer.ll Sun Aug 18 16:36:46 2013 -0400 @@ -56,10 +56,10 @@ return NUM; } [ \t]+ { } -. { yyless (0); BEGIN (INITIAL); } +"\n"|. { yyless (0); BEGIN (INITIAL); } "{" { BEGIN (NUM_MODE); return START; } -. { yyless (0); BEGIN (INITIAL); } +"\n"|. { yyless (0); BEGIN (INITIAL); } %{ // Simple commands @@ -100,7 +100,7 @@ "\\" { BEGIN(COMMAND); return CMD; } {ID} { yylval->ch = yytext[0]; return ID; } -. { BEGIN(INITIAL); yyless (0); } +"\n"|. { BEGIN(INITIAL); yyless (0); } %{ // Generic character diff -r cb7233cfbf43 -r 8ce6cdd272eb libinterp/corefcn/oct-tex-parser.yy --- a/libinterp/corefcn/oct-tex-parser.yy Sun Aug 18 16:36:44 2013 -0400 +++ b/libinterp/corefcn/oct-tex-parser.yy Sun Aug 18 16:36:46 2013 -0400 @@ -94,7 +94,6 @@ symbol_element : CMD identifier { - printf ("symbol: %s\n", $2->c_str ()); $$ = new text_element_symbol (*$2); delete $2; } @@ -116,7 +115,6 @@ fontname_element : FONTNAME START simple_string END { - printf ("fontname: %s\n", $3->c_str ()); $$ = new text_element_fontname (*$3); delete $3; } @@ -124,20 +122,17 @@ color_element : COLOR START simple_string END { - printf ("color: %s\n", $3->c_str ()); $$ = new text_element_color (*$3); delete $3; } | COLOR_RGB START NUM NUM NUM END { - printf ("color: %g %g %g\n", $3, $4, $5); $$ = new text_element_color ($3, $4, $5); } ; string_element : simple_string %prec STR { - printf ("string: \"%s\"\n", $1->c_str ()); $$ = new text_element_string (*$1); delete $1; } @@ -202,5 +197,5 @@ static void yyerror (text_parser_tex&, const char *s) { - fprintf (stderr, "parse error: %s\n", s); + fprintf (stderr, "TeX parse error: %s\n", s); } diff -r cb7233cfbf43 -r 8ce6cdd272eb libinterp/corefcn/txt-eng-ft.cc --- a/libinterp/corefcn/txt-eng-ft.cc Sun Aug 18 16:36:44 2013 -0400 +++ b/libinterp/corefcn/txt-eng-ft.cc Sun Aug 18 16:36:46 2013 -0400 @@ -44,18 +44,18 @@ // combination. static void -gripe_missing_glyph (char c) +gripe_missing_glyph (FT_ULong c) { warning_with_id ("Octave:missing-glyph", - "ft_render: skipping missing glyph for character '%c'", + "ft_render: skipping missing glyph for character '%x'", c); } static void -gripe_glyph_render (char c) +gripe_glyph_render (FT_ULong c) { warning_with_id ("Octave:glyph-render", - "ft_render: unable to render glyph for character '%c'", + "ft_render: unable to render glyph for character '%x'", c); } @@ -302,40 +302,29 @@ // --------------------------------------------------------------------------- ft_render::ft_render (void) - : text_processor (), fonts (), bbox (1, 4, 0.0), halign (0), xoffset (0), - yoffset (0), mode (MODE_BBOX), red (0), green (0), blue (0) + : text_processor (), font (), bbox (1, 4, 0.0), halign (0), xoffset (0), + line_yoffset (0), yoffset (0), mode (MODE_BBOX), + color (dim_vector (1, 3), 0) { } ft_render::~ft_render (void) { - fonts.clear (); } void ft_render::set_font (const std::string& name, const std::string& weight, const std::string& angle, double size) { - if (fonts.size () > 1) - ::warning ("ft_render: resetting font parameters while the font stack " - "contains more than 1 element."); - - // In all cases, we only replace the first/bottom font in the stack, if any. - // Calling this method while there's more than 1 font in the stack does - // not make sense: we're not gonna reconstruct the entire font stack. - - if (fonts.size ()) - fonts.pop_front (); - // FIXME: take "fontunits" into account FT_Face face = ft_manager::get_font (name, weight, angle, size); if (face) { if (FT_Set_Char_Size (face, 0, size*64, 0, 0)) - ::warning ("ft_render: unable to set font size to %d", size); + ::warning ("ft_render: unable to set font size to %g", size); - fonts.push_front (ft_font (name, weight, angle, size, face)); + font = ft_font (name, weight, angle, size, face); } else ::warning ("ft_render: unable to load appropriate font"); @@ -350,7 +339,7 @@ { // Create a new bbox entry based on the current font. - FT_Face face = current_face (); + FT_Face face = font.face; if (face) { @@ -379,7 +368,8 @@ Matrix new_bbox = line_bbox.front (); xoffset = compute_line_xoffset (new_bbox); - yoffset += (old_bbox(1) - (new_bbox(1) + new_bbox(3))); + line_yoffset += (old_bbox(1) - (new_bbox(1) + new_bbox(3))); + yoffset = 0; } break; } @@ -437,6 +427,42 @@ } void +ft_render::update_line_bbox (void) +{ + // Called after a font change, when in MODE_BBOX mode, to update the + // current line bbox with the new font metrics. This also includes the + // current yoffset, that is the offset of the current glyph's baseline + // the line's baseline. + + if (mode == MODE_BBOX) + { + int asc = font.face->size->metrics.ascender >> 6; + int desc = font.face->size->metrics.descender >> 6; + + Matrix& bb = line_bbox.front (); + + if ((yoffset + desc) < bb(1)) + { + // The new font goes below the bottom of the current bbox. + + int delta = bb(1) - (yoffset + desc); + + bb(1) -= delta; + bb(3) += delta; + } + + if ((yoffset + asc) > (bb(1) + bb(3))) + { + // The new font goes above the top of the current bbox. + + int delta = (yoffset + asc) - (bb(1) + bb(3)); + + bb(3) += delta; + } + } +} + +void ft_render::set_mode (int m) { mode = m; @@ -444,7 +470,7 @@ switch (mode) { case MODE_BBOX: - xoffset = yoffset = 0; + xoffset = line_yoffset = yoffset = 0; bbox = Matrix (1, 4, 0.0); line_bbox.clear (); push_new_line (); @@ -454,7 +480,7 @@ { ::warning ("ft_render: invalid bounding box, cannot render"); - xoffset = yoffset = 0; + xoffset = line_yoffset = yoffset = 0; pixels = uint8NDArray (); } else @@ -462,7 +488,8 @@ pixels = uint8NDArray (dim_vector (4, bbox(2), bbox(3)), static_cast (0)); xoffset = compute_line_xoffset (line_bbox.front ()); - yoffset = -bbox(1)-1; + line_yoffset = -bbox(1)-1; + yoffset = 0; } break; default: @@ -471,135 +498,289 @@ } } +FT_UInt +ft_render::process_character (FT_ULong code, FT_UInt previous) +{ + FT_Face face = font.face; + FT_UInt glyph_index = 0; + + if (face) + { + glyph_index = FT_Get_Char_Index (face, code); + + if (code != '\n' + && (! glyph_index + || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))) + { + glyph_index = 0; + gripe_missing_glyph (code); + } + else + { + switch (mode) + { + case MODE_RENDER: + if (code == '\n') + { + glyph_index = FT_Get_Char_Index (face, ' '); + if (!glyph_index || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT)) + { + glyph_index = 0; + gripe_missing_glyph (' '); + } + else + push_new_line (); + } + else if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL)) + { + glyph_index = 0; + gripe_glyph_render (code); + } + else + { + FT_Bitmap& bitmap = face->glyph->bitmap; + int x0, y0; + + if (previous) + { + FT_Vector delta; + + FT_Get_Kerning (face, previous, glyph_index, FT_KERNING_DEFAULT, &delta); + xoffset += (delta.x >> 6); + } + + x0 = xoffset + face->glyph->bitmap_left; + y0 = line_yoffset + yoffset + face->glyph->bitmap_top; + + // 'w' seems to have a negative -1 + // face->glyph->bitmap_left, this is so we don't + // index out of bound, and assumes we we allocated + // the right amount of horizontal space in the bbox. + if (x0 < 0) + x0 = 0; + + for (int r = 0; r < bitmap.rows; r++) + for (int c = 0; c < bitmap.width; c++) + { + unsigned char pix = bitmap.buffer[r*bitmap.width+c]; + if (x0+c < 0 || x0+c >= pixels.dim2 () + || y0-r < 0 || y0-r >= pixels.dim3 ()) + { + //::warning ("ft_render: pixel out of bound (char=%d, (x,y)=(%d,%d), (w,h)=(%d,%d)", + // str[i], x0+c, y0-r, pixels.dim2 (), pixels.dim3 ()); + } + else if (pixels(3, x0+c, y0-r).value () == 0) + { + pixels(0, x0+c, y0-r) = color(0); + pixels(1, x0+c, y0-r) = color(1); + pixels(2, x0+c, y0-r) = color(2); + pixels(3, x0+c, y0-r) = pix; + } + } + + xoffset += (face->glyph->advance.x >> 6); + } + break; + + case MODE_BBOX: + if (code == '\n') + { + glyph_index = FT_Get_Char_Index (face, ' '); + if (! glyph_index + || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT)) + { + glyph_index = 0; + gripe_missing_glyph (' '); + } + else + push_new_line (); + } + else + { + Matrix& bb = line_bbox.back (); + + // If we have a previous glyph, use kerning information. + // This usually means moving a bit backward before adding + // the next glyph. That is, "delta.x" is usually < 0. + if (previous) + { + FT_Vector delta; + + FT_Get_Kerning (face, previous, glyph_index, + FT_KERNING_DEFAULT, &delta); + + bb(2) += (delta.x >> 6); + } + + // Extend current line bounding box by the width of the + // current glyph. + bb(2) += (face->glyph->advance.x >> 6); + } + break; + } + } + } + + return glyph_index; +} + void ft_render::visit (text_element_string& e) { - FT_Face face = current_face (); - - if (face) + if (font.is_valid ()) { std::string str = e.string_value (); FT_UInt glyph_index, previous = 0; for (size_t i = 0; i < str.length (); i++) { - glyph_index = FT_Get_Char_Index (face, str[i]); - - if (str[i] != '\n' - && (! glyph_index - || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))) - gripe_missing_glyph (str[i]); - else - { - switch (mode) - { - case MODE_RENDER: - if (str[i] == '\n') - { - glyph_index = FT_Get_Char_Index (face, ' '); - if (!glyph_index || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT)) - { - gripe_missing_glyph (' '); - } - else - push_new_line (); - } - else if (FT_Render_Glyph (face->glyph, FT_RENDER_MODE_NORMAL)) - { - gripe_glyph_render (str[i]); - } - else - { - FT_Bitmap& bitmap = face->glyph->bitmap; - int x0, y0; - - if (previous) - { - FT_Vector delta; - - FT_Get_Kerning (face, previous, glyph_index, FT_KERNING_DEFAULT, &delta); - xoffset += (delta.x >> 6); - } - - x0 = xoffset+face->glyph->bitmap_left; - y0 = yoffset+face->glyph->bitmap_top; - - // 'w' seems to have a negative -1 - // face->glyph->bitmap_left, this is so we don't - // index out of bound, and assumes we we allocated - // the right amount of horizontal space in the bbox. - if (x0 < 0) - x0 = 0; + glyph_index = process_character (str[i], previous); - for (int r = 0; r < bitmap.rows; r++) - for (int c = 0; c < bitmap.width; c++) - { - unsigned char pix = bitmap.buffer[r*bitmap.width+c]; - if (x0+c < 0 || x0+c >= pixels.dim2 () - || y0-r < 0 || y0-r >= pixels.dim3 ()) - { - //::warning ("ft_render: pixel out of bound (char=%d, (x,y)=(%d,%d), (w,h)=(%d,%d)", - // str[i], x0+c, y0-r, pixels.dim2 (), pixels.dim3 ()); - } - else if (pixels(3, x0+c, y0-r).value () == 0) - { - pixels(0, x0+c, y0-r) = red; - pixels(1, x0+c, y0-r) = green; - pixels(2, x0+c, y0-r) = blue; - pixels(3, x0+c, y0-r) = pix; - } - } - - xoffset += (face->glyph->advance.x >> 6); - } - break; - - case MODE_BBOX: - if (str[i] == '\n') - { - glyph_index = FT_Get_Char_Index (face, ' '); - if (! glyph_index - || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT)) - { - gripe_missing_glyph (' '); - } - else - push_new_line (); - } - else - { - Matrix& bb = line_bbox.back (); - - // If we have a previous glyph, use kerning information. - // This usually means moving a bit backward before adding - // the next glyph. That is, "delta.x" is usually < 0. - if (previous) - { - FT_Vector delta; - - FT_Get_Kerning (face, previous, glyph_index, - FT_KERNING_DEFAULT, &delta); - - bb(2) += (delta.x >> 6); - } - - // Extend current line bounding box by the width of the - // current glyph. - bb(2) += (face->glyph->advance.x >> 6); - } - break; - } - - if (str[i] == '\n') - previous = 0; - else - previous = glyph_index; - } + if (str[i] == '\n') + previous = 0; + else + previous = glyph_index; } } } void +ft_render::visit (text_element_list& e) +{ + // Save and restore (after processing the list) the current font and color. + + ft_font saved_font (font); + uint8NDArray saved_color (color); + + text_processor::visit (e); + + font = saved_font; + color = saved_color; +} + +void +ft_render::visit (text_element_subscript& e) +{ + ft_font saved_font (font); + int saved_line_yoffset = line_yoffset; + int saved_yoffset = yoffset; + + set_font (font.name, font.weight, font.angle, font.size - 2); + if (font.is_valid ()) + { + int h = font.face->size->metrics.height >> 6; + + // Shifting the baseline by 2/3 the font height seems to produce + // decent result. + yoffset -= (h * 2) / 3; + + if (mode == MODE_BBOX) + update_line_bbox (); + } + + text_processor::visit (e); + + font = saved_font; + // If line_yoffset changed, this means we moved to a new line; hence yoffset + // cannot be restored, because the saved value is not relevant anymore. + if (line_yoffset == saved_line_yoffset) + yoffset = saved_yoffset; +} + +void +ft_render::visit (text_element_superscript& e) +{ + ft_font saved_font (font); + int saved_line_yoffset = line_yoffset; + int saved_yoffset = yoffset; + + set_font (font.name, font.weight, font.angle, font.size - 2); + if (saved_font.is_valid () && font.is_valid ()) + { + int s_asc = saved_font.face->size->metrics.ascender >> 6; + + // Shifting the baseline by 2/3 base font ascender seems to produce + // decent result. + yoffset += (s_asc * 2) / 3; + + if (mode == MODE_BBOX) + update_line_bbox (); + } + + text_processor::visit (e); + + font = saved_font; + // If line_yoffset changed, this means we moved to a new line; hence yoffset + // cannot be restored, because the saved value is not relevant anymore. + if (line_yoffset == saved_line_yoffset) + yoffset = saved_yoffset; +} + +void +ft_render::visit (text_element_color& e) +{ + if (mode == MODE_RENDER) + set_color (e.get_color ()); +} + +void +ft_render::visit (text_element_fontsize& e) +{ + double sz = e.get_fontsize (); + + // FIXME: Matlab documentation says that the font size is expressed + // in the text object FontUnit. + + set_font (font.name, font.weight, font.angle, sz); + + if (mode == MODE_BBOX) + update_line_bbox (); +} + +void +ft_render::visit (text_element_fontname& e) +{ + set_font (e.get_fontname (), font.weight, font.angle, font.size); + + if (mode == MODE_BBOX) + update_line_bbox (); +} + +void +ft_render::visit (text_element_fontstyle& e) +{ + switch (e.get_fontstyle ()) + { + case text_element_fontstyle::normal: + set_font (font.name, "normal", "normal", font.size); + break; + case text_element_fontstyle::bold: + set_font (font.name, "bold", "normal", font.size); + break; + case text_element_fontstyle::italic: + set_font (font.name, "normal", "italic", font.size); + break; + case text_element_fontstyle::oblique: + set_font (font.name, "normal", "oblique", font.size); + break; + } + + if (mode == MODE_BBOX) + update_line_bbox (); +} + +void +ft_render::visit (text_element_symbol& e) +{ + uint32_t code = e.get_symbol_code (); + + if (code != text_element_symbol::invalid_code && font.is_valid ()) + process_character (code); + else if (font.is_valid ()) + ::warning ("ignoring unknown symbol: %s", e.string_value ().c_str ()); +} + +void ft_render::reset (void) { set_mode (MODE_BBOX); @@ -611,9 +792,9 @@ { if (c.numel () == 3) { - red = static_cast (c(0)*255); - green = static_cast (c(1)*255); - blue = static_cast (c(2)*255); + color(0) = static_cast (c(0)*255); + color(1) = static_cast (c(1)*255); + color(2) = static_cast (c(2)*255); } else ::warning ("ft_render::set_color: invalid color"); diff -r cb7233cfbf43 -r 8ce6cdd272eb libinterp/corefcn/txt-eng-ft.h --- a/libinterp/corefcn/txt-eng-ft.h Sun Aug 18 16:36:44 2013 -0400 +++ b/libinterp/corefcn/txt-eng-ft.h Sun Aug 18 16:36:46 2013 -0400 @@ -59,6 +59,22 @@ void visit (text_element_string& e); + void visit (text_element_list& e); + + void visit (text_element_subscript& e); + + void visit (text_element_superscript& e); + + void visit (text_element_color& e); + + void visit (text_element_fontsize& e); + + void visit (text_element_fontname& e); + + void visit (text_element_fontstyle& e); + + void visit (text_element_symbol& e); + void reset (void); uint8NDArray get_pixels (void) const { return pixels; } @@ -104,12 +120,16 @@ double size; FT_Face face; + ft_font (void) + : name (), weight (), angle (), size (0), face (0) { } + ft_font (const std::string& nm, const std::string& wt, const std::string& ang, double sz, FT_Face f) : name (nm), weight (wt), angle (ang), size (sz), face (f) { } ft_font (const ft_font& ft) - : name (ft.name), weight (ft.weight), angle (ft.angle), size (ft.size) + : name (ft.name), weight (ft.weight), angle (ft.angle), + size (ft.size), face (0) { if (FT_Reference_Face (ft.face) == 0) face = ft.face; @@ -130,7 +150,7 @@ angle = ft.angle; size = ft.size; FT_Done_Face (face); - if (FT_Reference_Face (ft.face)) + if (FT_Reference_Face (ft.face) == 0) face = ft.face; else face = 0; @@ -139,22 +159,22 @@ return *this; } - private: - ft_font (void); + bool is_valid (void) const { return face; } }; - FT_Face current_face (void) - { return fonts.size () ? fonts.back ().face : 0; } + void push_new_line (void); - void push_new_line (void); + void update_line_bbox (void); void compute_bbox (void); int compute_line_xoffset (const Matrix& lb) const; + FT_UInt process_character (FT_ULong code, FT_UInt previous = 0); + private: - // The stack of fonts currently used by the renderer. - std::list fonts; + // The current font used by the renderer. + ft_font font; // Used to stored the bounding box corresponding to the rendered text. // The bounding box has the form [x, y, w, h] where x and y represent the @@ -174,17 +194,22 @@ // The current horizontal alignment. This is used to align multi-line text. int halign; - // The current X offset for the next glyph. + // The X offset for the next glyph. int xoffset; - // The current Y offset for the next glyph. + // The Y offset of the baseline for the current line. + int line_yoffset; + + // The Y offset of the baseline for the next glyph. The offset is relative + // to line_yoffset. The total Y offset is computed with: + // line_yoffset + yoffset. int yoffset; // The current mode of the rendering process (box computing or rendering). int mode; // The base color of the rendered text. - uint8_t red, green, blue; + uint8NDArray color; }; #endif // HAVE_FREETYPE diff -r cb7233cfbf43 -r 8ce6cdd272eb libinterp/corefcn/txt-eng.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/corefcn/txt-eng.cc Sun Aug 18 16:36:46 2013 -0400 @@ -0,0 +1,259 @@ +/* + +Copyright (C) 2013 Michael Goffioul + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "txt-eng.h" + +static const char* symbol_names[] = { + "alpha", + "beta", + "gamma", + "delta", + "epsilon", + "zeta", + "eta", + "theta", + "vartheta", + "iota", + "kappa", + "lambda", + "mu", + "nu", + "xi", + "pi", + "rho", + "sigma", + "varsigma", + "tau", + "equiv", + "Im", + "otimes", + "cap", + "supset", + "int", + "rfloor", + "lfloor", + "perp", + "wedge", + "rceil", + "vee", + "langle", + + "upsilon", + "phi", + "chi", + "psi", + "omega", + "Gamma", + "Delta", + "Theta", + "Lambda", + "Xi", + "Pi", + "Sigma", + "Upsilon", + "Phi", + "Psi", + "Omega", + "forall", + "exists", + "ni", + "cong", + "approx", + "Re", + "oplus", + "cup", + "subseteq", + "in", + "lceil", + "cdot", + "neg", + "times", + "surd", + "varpi", + "rangle", + + "leq", + "infty", + "clubsuit", + "diamondsuit", + "heartsuit", + "spadesuit", + "leftrightarrow", + "leftarrow", + "uparrow", + "rightarrow", + "downarrow", + "circ", + "pm", + "geq", + "propto", + "partial", + "bullet", + "div", + "neq", + "aleph", + "wp", + "oslash", + "supseteq", + "subset", + "o", + "nabla", + "ldots", + "prime", + "0", + "mid", + "copyright", + + 0 +}; + +// Maps the symbol names (using index from symbol_names array) to +// character codes, using 2 mapping: +// - Unicode +// - MS symbol (using Private Use Area) +static uint32_t symbol_codes[][2] = { + { 0x03B1, 0xF061 }, // alpha + { 0x03B2, 0xF062 }, // beta + { 0x03B3, 0xF067 }, // gamma + { 0x03B4, 0xF064 }, // delta + { 0x03B5, 0xF065 }, // epsilon + { 0x03B6, 0xF07A }, // zeta + { 0x03B7, 0xF068 }, // eta + { 0x03B8, 0xF071 }, // theta + { 0x03D1, 0xF04A }, // vartheta + { 0x03B9, 0xF069 }, // iota + { 0x03BA, 0xF06B }, // kappa + { 0x03BB, 0xF06C }, // lambda + { 0x03BC, 0xF06D }, // mu + { 0x03BD, 0xF06E }, // nu + { 0x03BE, 0xF078 }, // xi + { 0x03C0, 0xF070 }, // pi + { 0x03C1, 0xF072 }, // rho + { 0x03C3, 0xF073 }, // sigma + { 0x03C2, 0xF056 }, // varsigma + { 0x03C4, 0xF074 }, // tau + { 0x2261, 0xF0BA }, // equiv + { 0x2111, 0xF0C1 }, // Im + { 0x2297, 0xF0C4 }, // otimes + { 0x2229, 0xF0C7 }, // cap + { 0x2283, 0xF0C9 }, // supset + { 0x222B, 0xF0F2 }, // int + { 0x230B, 0xF0FB }, // rfloor + { 0x230A, 0xF0EB }, // lfloor + { 0x22A5, 0xF05E }, // perp + { 0x2227, 0xF0D9 }, // wedge + { 0x2309, 0xF0F9 }, // rceil + { 0x2228, 0xF0DA }, // vee + { 0x2220, 0xF0E1 }, // langle + + { 0x03C5, 0xF075 }, // upsilon + { 0x03C6, 0xF066 }, // phi + { 0x03C7, 0xF063 }, // chi + { 0x03C8, 0xF079 }, // psi + { 0x03C9, 0xF077 }, // omega + { 0x0393, 0xF047 }, // Gamma + { 0x0394, 0xF044 }, // Delta + { 0x0398, 0xF051 }, // Theta + { 0x039B, 0xF04C }, // Lambda + { 0x039E, 0xF058 }, // Xi + { 0x03A0, 0xF050 }, // Pi + { 0x03A3, 0xF053 }, // Sigma + { 0x03D2, 0xF055 }, // Upsilon + { 0x03A6, 0xF046 }, // Phi + { 0x03A8, 0xF059 }, // Psi + { 0x03A9, 0xF057 }, // Omega + { 0x2200, 0xF022 }, // forall + { 0x2203, 0xF024 }, // exists + { 0x220B, 0xF027 }, // ni + { 0x2245, 0xF040 }, // cong + { 0x2248, 0xF0BB }, // approx + { 0x211C, 0xF0C2 }, // Re + { 0x2295, 0xF0C5 }, // oplus + { 0x222A, 0xF0C8 }, // cup + { 0x2286, 0xF0CD }, // subseteq + { 0x2208, 0xF0CE }, // in + { 0x2308, 0xF0E9 }, // lceil + { 0x22C5, 0xF0D7 }, // cdot + { 0x00AC, 0xF0D8 }, // neg + { 0x00D7, 0xF0B4 }, // times + { 0x221A, 0xF0D6 }, // surd + { 0x03D6, 0xF076 }, // varpi + { 0x232A, 0xF0F1 }, // rangle + + { 0x2264, 0xF0A3 }, // leq + { 0x221E, 0xF0A5 }, // infty + { 0x2663, 0xF0A7 }, // clubsuit + { 0x2666, 0xF0A8 }, // diamondsuit + { 0x2665, 0xF0A9 }, // heartsuit + { 0x2660, 0xF0AA }, // spadesuit + { 0x2194, 0xF0AB }, // leftrightarrow + { 0x2190, 0xF0AC }, // leftarrow + { 0x2191, 0xF0AD }, // uparrow + { 0x2192, 0xF0AE }, // rightarrow + { 0x2193, 0xF0AF }, // downarrow + { 0x25CB, 0xF0B0 }, // circ + { 0x00B1, 0xF0B1 }, // pm + { 0x2265, 0xF0B3 }, // geq + { 0x221D, 0xF0B5 }, // propto + { 0x2202, 0xF0B6 }, // partial + { 0x2022, 0xF0B7 }, // bullet + { 0x00F7, 0xF0B8 }, // div + { 0x2260, 0xF0B9 }, // neq + { 0x2135, 0xF0C0 }, // aleph + { 0x2118, 0xF0C3 }, // wp + { 0x2298, 0xF0C6 }, // oslash + { 0x2287, 0xF0CA }, // supseteq + { 0x2282, 0xF0CC }, // subset + { 0x03BF, 0xF0B0 }, // o + { 0x2207, 0xF0D1 }, // nabla + { 0x2026, 0xF0BC }, // ldots + { 0x2032, 0xF0A2 }, // prime + { 0x2205, 0xF0C6 }, // 0 + { 0x2223, 0xF0BD }, // mid + { 0x00A9, 0xF0E3 }, // copyright + + { 0, 0 } +}; + +uint32_t +text_element_symbol::get_symbol_code (void) +{ + if (code == invalid_code) + { + std::string sym = string_value (); + + for (int i = 0; symbol_names[i]; i++) + { + if (symbol_names[i] == sym) + { + code = symbol_codes[i][0]; + break; + } + } + } + + return code; +} diff -r cb7233cfbf43 -r 8ce6cdd272eb libinterp/corefcn/txt-eng.h --- a/libinterp/corefcn/txt-eng.h Sun Aug 18 16:36:44 2013 -0400 +++ b/libinterp/corefcn/txt-eng.h Sun Aug 18 16:36:46 2013 -0400 @@ -32,9 +32,14 @@ class text_element; class text_element_string; +class text_element_symbol; class text_element_list; class text_element_subscript; class text_element_superscript; +class text_element_fontname; +class text_element_fontsize; +class text_element_fontstyle; +class text_element_color; class text_processor; @@ -79,12 +84,20 @@ text_element_symbol : public text_element_string { public: + enum { invalid_code = 0xFFFFFFFFU }; + +public: text_element_symbol (const std::string& sym) - : text_element_string (sym) { } + : text_element_string (sym), code (invalid_code) { } ~text_element_symbol (void) { } + uint32_t get_symbol_code (void); + void accept (text_processor& p); + +private: + uint32_t code; }; class @@ -184,6 +197,8 @@ ~text_element_fontstyle (void) { } + fontstyle get_fontstyle (void) const { return style; } + void accept (text_processor& p); private: @@ -203,7 +218,7 @@ ~text_element_fontname (void) { } - const std::string& fontname (void) const { return name; } + const std::string& get_fontname (void) const { return name; } void accept (text_processor& p); @@ -224,7 +239,7 @@ ~text_element_fontsize (void) { } - double fontsize (void) const { return size; } + double get_fontsize (void) const { return size; } void accept (text_processor& p);