[Top] [Contents] [Index] [ ? ]

GtkMathView Reference Manual

1. Overview  General information about GtkMathView.
2. Usage  Compiling and installation instructions.
3. Interactivity Support  
4. Sample Application  
5. C++ Interface  Summary of the C++ interface.
6. GTK+ Interface  Summary of the GTK+ interface.
7. Tools  Tools coming along the widget.
8. Bugs and Contributions  How to report a bug.

 -- The Detailed Node Listing ---

Usage

2.1 Download  Where the source code is
2.2 Requirements  Auxiliary packages to compile and run GtkMathView.
2.3 Installing  How to compile the source code of the widget.
2.4 Compile and Link  How to link against your source code.
2.5 Configuration  How to fine-tune the widget

Configuration

2.5.1 Main Configuration File  Basic configuration
2.5.2 Operator Dictionary  Setting the default value for operator attributes
2.5.3 Font Setup  How the widget maps Unicode characters into glyphs

Interactivity Support

3.1 Selection  Highlighting sub-expressions
3.2 Point-and-click Functionalities  Handling of basic mouse events
3.3 Editing  Changind the source document tree

C++ Interface

5.1 Lengths  About Lengths
5.2 Boxes and Rectangles  
5.3 The MathMLRenderingEngine Class  

Boxes and Rectangles

5.2.1 Rectangles  
5.2.2 Bounding Boxes  

Tools

7.1 mathmlviewer  A simple viewer application.
7.2 mathml2ps  A MathML => PostScript conversion utility.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1. Overview

GtkMathView is a C++ rendering engine for MathML (see http://www.w3.org/Math) documents. Although GtkMathView is, by its own definition, related to the GTK+ framework (we eventually had to commit to a development platform that was convenient for our purposes), its internal architecture is designed as to isolate as much as possible platform dependencies. A large part of GtkMathView, the one dealing with proper formula layout, is completely platform independent. On top of this internal, hidden library of C++ classes are two different interfaces, one for GTK+ and another one that allows to render MathML documents to PostScript. The implementation of a new interface is a relatively easy and straightforward task.

For questions, comments, suggestions, bug reports, contributions, please contact the author at the following email address: luca.padovani@cs.unibo.it


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2. Usage

2.1 Download  Where the source code is
2.2 Requirements  Auxiliary packages to compile and run GtkMathView.
2.3 Installing  How to compile the source code of the widget.
2.4 Compile and Link  How to link against your source code.
2.5 Configuration  How to fine-tune the widget


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.1 Download

The latest version of the source code of the GtkMathView widget, along with this documentation, can be obtained directly from http://helm.cs.unibo.it/mml-widget/.

In the same page you will find unofficial RedHat packages and official Debian packages for the widget and related tools.

The source code is also available from the GNOME CVS repository, which can be accesses anonymously via CVS at the following address :pserver:anonymous@anoncvs.gnome.org:/cvs/gnome

The module name is gtkmathview. The CVS repository can also be browsed online at the address http://cvs.gnome.org/lxr/source/gtkmathview/.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.2 Requirements

To compile and use the widget you need the following packages installed on your system:


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.3 Installing

Keep in mind that the widget will not compile if GMetaDOM is not installed. See the INSTALL file included in the source distribution for detailed compilation and installation instructions. After installation you will have the following files:


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.4 Compile and Link

To compile a source file which uses the widget use the command

gcc -c filename.c -l... -I... `gtkmathview-config --cflags`

The widget is compiled by default to generate both static and shared object file. It can be linked dynamically against your applications with the command:

gcc -o appname *.o `gtkmathview-config --libs`


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.5 Configuration

The widget can be partly configured after instantiation by using the provided methods described in 6. GTK+ Interface. However, most of the configuration is specified in an external file whose path can be set in the environment variable MATHENGINECONF. In case the environment variable is not set, the widget will try to read the configuration file from the default location, which typically is /usr/local/share/gtkmathview.

2.5.1 Main Configuration File  Basic configuration
2.5.2 Operator Dictionary  Setting the default value for operator attributes
2.5.3 Font Setup  How the widget maps Unicode characters into glyphs


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.5.1 Main Configuration File

The main configuration file is an XML document whose root element must be math-engine-configuration. The children of the root element determine the value of a number of parameter that are described below:


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.5.2 Operator Dictionary

The operator dictionary defines the default value of a number of attributes that applies to mo elements. The exact definition of the operator dictionary along with the attributes that can be set is described in the MathML specification(1)}

The dictionary XML file is made of a dictionary element with an arbitrary number of operator children. For each operator the following attributes can be used: name (this is required), form (this is also required and can be one of prefix, infix, or postfix), fence, separator, lspace, rspace, stretchy, symmetric, maxsize, minsize, largeop, movablelimits, accent. The syntax for the attributes is the same as the one specified in the MathML recommendation.

In addition, two extension attributes tspace and bspace can be defined. They represent the amount of space respectively at the top and at the bottom of an operator. They are usually ignored, unless the widget has been configured with the --enable-extensions flag set.

A sample entry for the operator dictionary is the following, describing the default attributes for an open parenthesis when it is in prefix position (that is, the parenthesis is the first child of a (possibly inferred) mrow element):

 
  <operator name="(" form="prefix" fence="true"
            stretchy="true" lspace="0em" rspace="0em"/>


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

2.5.3 Font Setup

Font configuration defines the mapping from Unicode(2) characters to glyph indexes inside system fonts. Although font configuration should be done once and for all, and the widget already comes with a sensible configuration for most math fonts, we will describe the font configuration format so that users know how to extend their configuration, or to correct the existing one in case of errors.

The font configuration XML file is made of a font-configuration element with an arbitrary number of font and map children. font children define how abstract font descriptions are mapped into system font descriptions, whereas map children define an actual mapping of Unicode characters into glyph indexes for a particular font. Every font abstract description must have a reference to a map element. The reason why font abstract descriptions and maps are kept separate is that many different font abstract descriptions may share the same font map, hence it is convenient to use an indirection instead of replicating the map each time it is needed.

Each font element has the following attributes:

Font Classification.

Font Description:

Specific Font Data. The set of valid attributes depends on the type attribute. For X fonts, the attributes are x-foundry, x-family, x-weight, x-slant, x-width, x-style, x-pixels, x-points, x-hres, x-vres, x-spacing, x-avgwidth, x-registry, x-encoding. Their syntax follows the syntax for X font specifications.

For PostScript (or Type1) fonts, the attributes are ps-name and ps-file specifying the PostScript name of the font and the file name that contains the font, respectively.

Each map element has an id attribute that font abstract specifications can refer to and has an arbitrary list of single, range, multi, or stretchy children. Whenever Unicode characters or glyph indexes need to be referenced from the maps, they can be given in hexadecimal (with 0x prefix), octal (with 0 prefix), or decimal (in all the other cases). Unicode characters can also be specified by simply inserting the character (or a character reference) into the attribute.

A single child specifies the mapping for a single Unicode character. The Unicode character is specified in the code attribute, its index in the index attribute.

A range child specifies the mapping for a range of Unicode characters. The first and last characters (inclusive) in the range are specified in the first and last attributes, respectively. The attribute offset specifies the index of the glyph corresponding to the first character.

A multi child specifies the mapping for a range of Unicode characters whose glyph indexes do not follow the same order, or are not all available. In this case the index attribute is a space separated list of glyph indexes, each related to the corresponding Unicode character in the range. If there is no glyph corresponding to a given Unicode character, the constant -1 must be used.

A stretchy child specifies the mapping of a stretchable Unicode character, that is a character that can be formatted in different sizes, depending on the context. The code attribute specifies the Unicode character, and the direction attribute specifies whether the character can be stretched horizontally (horizontal), vertically (vertical), or in both directions (both). A stretchy character has a mandatory simple child optionally followed by a compound child. The simple child has an index attribute that specifies the glyph indexes (separated by spaces) corresponding to the character as a whole, in increasing order of size. The compound child has an index attribute that specifies the glyph indexes (separated by spaces) corresponding to the dismantled pieces that can be combined to build up the character. There must be 4 entries corresponding to the leftmost (or bottommost) piece, the middle piece, the rightmost (or topmost) piece, and the piece that can be repeated at will to make the symbol as hight (or wide) as required.

For example, a specification like

 
<stretchy code="(" direction="vertical">
  <simple index="0000 0020 0022 0040"/>
  <compound index="0060 -1 0100 0102"/>
</stretchy>

says that the open round parenthesis is available as simple glyphs at the positions 0000, 0020, 0022, 0040. Those glyphs are listed in increasing order of size. In case there is the need of an even bigger parenthesis, it can be combined by using the 0060 glyph for the bottommost piece, 0100 glyph for the topmost piece, and 0102 as the glyph that can be repeated at will.

A special note about True Type fonts: recent X servers can render a wide variety of fonts, including True Type fonts usually shipped with Microsoft Windows. These fonts have more flexible scaling capabilities and you could find the final rendering really improved by their use. Since their handling is almost completely hidden inside the X font server, the widget needs not any special configuration to use them, apart from a proper setting of the font configuration file (`font-configuration.xml').

Type1 fonts and the t1lib library: starting from version 0.2.0, the rendering engine can use the t1lib library to render Type1 fonts. It is known that t1lib has some bugs that can cause the widget to crash, especially in version 0.4.1 or later. Here are some tips to configure the engine so that you can use Type1 fonts (please, consult the t1lib documentation at library's home page for firther details).

First of all, you have to setup a little configuration file for the t1lib library. Call this file `t1.config' and place it somewhere in your home directory. Here is a sample file (also provided with the standard distribution):

 
#
#
ENCODING=.
AFM=/usr/share/texmf/fonts/afm/
TYPE1=/usr/share/texmf/fonts/type1/bluesky/cm/:.

In particular, you have to specify where your Type1 fonts reside (TYPE1) along with their metrics (AFM). Metric information in optional, since it can be (mostly) recovered from the font file itself. However, metrics from the AFM file can be more precise than that automatically inferred. A sample configuration file for t1lib is included in the standard distribution of gtkmathview and is installed in `/usr/local/share/gtkmathview/'.

Next, you have to setup an environment variable T1LIB_CONFIG with the full path to this configuration file. For example, if you use bash:

export T1LIB_CONFIG=./config/t1.config

And, if you use tcsh:

setenv T1LIB_CONFIG ./config/t1.config

Now you are ready to use Type1 fonts.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3. Interactivity Support

GtkMathView's support for interaction support can be summarized in three aspects, selection, point-and-click, and editing, which we will define more precisely in the sections that follows.

Interactivity support often implies re-rendering of the displayed MathML document. As this can be an expensive operation, especially when several actions take place in rapid succession, GtkMathView provides for two methods (gtk_math_view_freeze and gtk_math_view_thaw) that delay any re-computation and update of the displaying window until the application has terminated the action.

As a matter of fact, due to the current design of GtkMathView's architecture, the use of these two methods is mandatory in that the displayed window is guaranteed to be updated correctly only if the two methods are properly used. Although we perceive this as a limitation, the points in favor are the following:

It is safe to nest calls to gtk_math_view_freeze and gtk_math_view_thaw methods at any level.

3.1 Selection  Highlighting sub-expressions
3.2 Point-and-click Functionalities  Handling of basic mouse events
3.3 Editing  Changind the source document tree


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.1 Selection

By selection we mean the possibility for the user to distinguish one or more DOM elements from the others in a MathML document. The typical visual feedback for selected elements is that of displaying them with a different background color.

Selection support in GtkMathView consists of three methods and four signals. The methods are needed to set and query about the selection status of a particular MathML element, as this information is hidden within the internal data structures of GtkMathView and is not available as part of the MathML document itself. Selection is a boolean property: an element can be either selected or not, there are no multiple levels of selection.

Both gtk_math_view_select and gtk_math_view_unselect operate recursively on the given MathML element and also on all its descendants, but the gtk_math_view_unselect method can be used to perforate a previously selected element thus leaving a "hole" within a selection. This mechanism can be exploited for representing patterns of elements within the MathML documents.

The signals related to selection are select_begin, select_end, select_over, and select_abort. The first three signals have two arguments, the MathML element on which the signal has been emitted and the status of control keys on the keyboard. The four signals are fired in disjoint sequences matching the following regular expression:
 
select_begin select_over* (select_end | select_abort)

which is to be read as follows: selection begins when the user presses the first mouse button and moves it a bit from the original position. As the user moves the mouse with the button pressed, an arbitrary number of select_over signals is emitted. Selection can terminate in two cases: either the user releases the button (select_end) or he/she presses another mouse button, hence aborting the selection (select_abort).

An interface for which multiple selections are required can check the status of control keys on the keyboard in order to determine whether a new selection sequence replaces a previous selection or adds a new selection to it.

Support for semantic selection. The widget does not highlight automatically the parts of the document on which the user is dragging the mouse. It is complete responsibility of the application to handle the selection signals and to invoke the gtk_math_view_select method appropriately. Although this puts some burden on the application side, it also enables the maximum flexibility, as selection may be constrained in ways that, in the most general case, are infeasible to hard code within GtkMathView.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.2 Point-and-click Functionalities

Point-and-click is supported by the click signal, which is emitted when the users clicks on the MathML document. The two arguments of the signal are the deepest MathML element on which the mouse was placed at the time of the click or NULL if there is no such element, and the status of the control keys on the keyboard.

Among the possible usages for this signal are the activation of hyperlinks and the management of maction elements. When the user clicks on the document, the event handler can look for a MathML element that has a xlink:href attribute set, and render that document. The search is typically done by starting from the element provided by the signal, and possibly climbing up the chain of elements until one with the required attribute is found, or the root element is reached, or any other application-specific condition applies.

Activation of maction elements works in the same way. Currently only the toggle action is supported by GtkMathView. In particular, once the maction element is found, it is possible to increase the number found in the selection attribute, which determines which of the maction's children is displayed. If the selection is increased beyond the actual number of children, GtkMathView will recast it into a valid range via a modulo operation. This way the application code for handling maction does not have to know the exact number of children, and is thus simplified. Note however that this behavior is not mandated by the MathML recommendation, and can differ in other MathML rendering engines. Once the selection attribute is set with the new value, GtkMathView will recompute automatically the document's layout.

Possible conflicts in case the xlink:href is set on an maction element must be resolved by the signal handler.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.3 Editing

The notion of editing in the context of GtkMathView is very limited. It simply refers to the fact that GtkMathView reacts automatically as the source MathML document changes, but GtkMathView itself does not enforce any constraints on how and when the document can change. The management of maction can be seen as a very particular kind of editing, as it involves a modification of the source document tree.

GtkMathView implements a number of internal mechanisms that try to optimize rendering, in the sense of minimizing the amount of computation that is needed to re-render a document after a modification has occurred.

Note also that in some cases local modifications may have non-local effects. For instance, modifying the content of a table cell may cause the re-computation of the whole table layout, as MathML attributes for table can specify constraints among cells in different columns or rows.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4. Sample Application

In this section we show a minimal GTK+ application that uses GtkMathView for displaying a MathML document. The application is intentionally small and only shows a small subset of GtkMathView capabilities. More complex examples, including sophisticated selections and maction handling, can be found in the GtkMathView source distribution.

The application begins, as usual, with some #include directives that load the necessary .h files. Note in particular that the gtkmathview.h header file must be included in order to use the widget.

 
#include <stdio.h>
#include <gtk/gtk.h>
#include <gtkmathview.h>

Next we declare a number of global variables that represent the main components of the graphical interface. The reason why these variables are global is that we may need to reference them from outside the main function, where they are initialized.

 
static GtkWidget* window = NULL;
static GtkWidget* main_vbox = NULL;
static GtkWidget* main_area = NULL;
static GtkWidget* scrolled_area = NULL;

We also need two global variables to support selection:

 
static GdomeElement* first_selected = NULL;
static GdomeElement* root_selected = NULL;

The following is an auxiliary function that loads the MathML document whose URI is specified in name inside the widget.

 
static int
load_document(const char* name)
{
  GtkMathView* math_view = GTK_MATH_VIEW(main_area);

  g_return_val_if_fail(name != NULL, -1);
  g_return_val_if_fail(math_view != NULL, -1);

  return gtk_math_view_load_uri(math_view, name);
}

The click function will be responsible for handling click signals as they are emitted. Note that the function takes three arguments: the GtkMathView widget that has generated the signal (math_view), the MathML element on which the user has clicked (elem), and finally the status of control keys.

 
static void
click(GtkMathView* math_view, GdomeElement* elem, gint state)
{
  g_return_if_fail(math_view != NULL);

  printf("*** click signal: %p %x\n", elem, state);

  if (elem != NULL)
    {
      /* do something with the element */
    }
}

The implementation of the selection mechanism is slightly more complicated as it involves handling at least two different signals. Upon receiving the select_begin signal the current selection, if present, is deleted, and the two global variables first_selected and root_selected are initialized with the element elem under the mouse pointer at the time selection was initiated. The element, if not NULL, is highlighted.

Note that the whole body of the signal handler begins with a gtk_math_view_freeze operation and ends with a gtk_math_view_thaw operation. This means that the display window is not updated until the signal handler terminates, with two advantages: the method is more efficient as GtkMathView updates only once, after two operations have been completed, and also we avoid the problem of flickering in case the previously selected area overlaps with the new one.

 
static void
select_begin(GtkMathView* math_view, GdomeElement* elem, gint state)
{
  gtk_math_view_freeze(math_view);

  if (root_selected != NULL)
    gtk_math_view_unselect(math_view, root_selected);

  first_selected = root_selected = elem;

  if (root_selected != NULL)
    gtk_math_view_select(math_view, elem);

  gtk_math_view_thaw(math_view);
}

Next we have to handle the signal emitted as the user drags the mouse keeping the button pressed. The idea is that first_selected remembers the element on which selection was initiated. As the mouse pointer is moved over the document, it crosses other elements. From first_selected and the current element elem it is possible to compute the smallest DOM subtree selected. In the sample code this operation is accomplished by the common_ancestor, which is left unspecified here.

 
static void
select_over(GtkMathView* math_view, GdomeElement* elem, gint state)
{
  gtk_math_view_freeze(math_view);

  if (root_selected != NULL)
    gtk_math_view_unselect(math_view, root_selected);

  root_selected = common_ancestor(first_selected, elem);

  if (root_selected != NULL)
    gtk_math_view_select(math_view, elem);

  gtk_math_view_thaw(math_view);
}

Note that the sample code does not implement any mechanism for semantic selection, but the idea is that the two signal handlers (as well as the remaining ones not shown here for simplicity), can be made as complex as the application needs. In particular, the computation of the selected root (common_ancestor) can be specialized so to search the smallest DOM subtree that meets the desired requirements as the application needs.

In order to complete the application, let us examine the main function, which creates the graphical interface, along with an instance of the GtkMathView widget, attaches the delete_event to the closing button of the window so that the window is automatically destroyed when the user closes it, and connects the signal handlers. Then the document whose URI is passed on the command line of the application is loaded into GtkMathView, and the control is finally transferred to GTK+.

 
main(int argc, char *argv[])
{
  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_signal_connect(GTK_OBJECT(window), "delete_event",
                     (GtkSignalFunc) gtk_main_quit, NULL);
  gtk_widget_show(window);

  main_vbox = gtk_vbox_new(FALSE, 1);
  gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
  gtk_container_add(GTK_CONTAINER(window), main_vbox);
  gtk_widget_show(main_vbox);

  main_area = gtk_math_view_new(NULL, NULL);
  gtk_widget_show(main_area);

  gtk_signal_connect_object (GTK_OBJECT (main_area), 
                             "click", GTK_SIGNAL_FUNC(click),
                             (gpointer) main_area);

  gtk_signal_connect_object (GTK_OBJECT (main_area), 
                             "select_begin", GTK_SIGNAL_FUNC(select_begin),
                             (gpointer) main_area);

  gtk_signal_connect_object (GTK_OBJECT (main_area), 
                             "select_over", GTK_SIGNAL_FUNC(select_over),
                             (gpointer) main_area);

  scrolled_area = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_area),
                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
  gtk_widget_show(scrolled_area);
  gtk_container_add(GTK_CONTAINER(scrolled_area), main_area);
  gtk_box_pack_start(GTK_BOX(main_vbox), scrolled_area, TRUE, TRUE, 0);

  load_document(argv[1]);

  gtk_main();
}

A note on memory management. It is important to mention that the objects of the DOM implementation (\code{Gdome2}) used in the sample code are subject to a memory management system that is based on reference counting. This means that every time a pointer to a DOM object (like a GdomeElement* in the example) is stored in some variable, the application has to explicitly increment its reference counter so that the object is not deallocated. For the sake of brevity every operation involving the reference counting mechanism has been omitted, but it is crucial to use it correctly in every application, no matter how simple the operations are. In this respect, the use of the corresponding C++ library (GMetaDOM) simplifies significantly the work of the programmer, as the DOM objects are accessed by means of smart pointers that take care of the reference counter automatically, without explicit intervention from the programmer's side.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5. C++ Interface

In this chapter we will describe the C++ class MathMLRenderingEngine which provides access to all the functionalities of the rendering engine from a C++ program. The GTK+ widget is just a wrapper of this class with particular support for GTK.

5.1 Lengths  About Lengths
5.2 Boxes and Rectangles  
5.3 The MathMLRenderingEngine Class  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.1 Lengths

A brief introduction is devoted to lengths, since they are a fundamental concept in the engine. From the user point of view, lengths can be expressed in many ways. For example, one might prefer using decimal units such as centimeters of millimeters, while others might prefer using inches or other typographical units. However, the engine uses internally a single unit which is called scaled point. It is the same unit as used by TeX.

From the point of view of the programmer, a scaled point is a floating point number, though it can be turned into fixed-pointer number giving the option `--disable-floating' while configuring the widget. Doing so is not particularly recommended, since with most modern microprocessor floating-point arithmetics is rather efficient.

Another unit of measure which is of particular interest for the programmer is the pixel. Unfortunately, there is not a unique correspondence between pixels and scaled points. Theoretically, their relationship should depend on the resolution of the output device involved for rendering (usually, the display). Since this resolution is not available in general and often is also misconfigured, it has been fixed in the rendering engine to be 72 dots per inch (DPI), which gives pretty good results. Its value can be changed by modifing the file `src/defs.h'.

The following table summarizes the relationships between scaled points and the other units of measure recognized by the widget.

Unit Name scaled points
mm millimeter 186467.98
cm centimeter 1864679.8
pt point 65536
pc pica 786432
in inch 65536 * 72.27
px pixel 65536 * 72.27 / DPI

The include file `src/scaled.hh' defines several conversion functions to convert from one unit to another. The following table summarizes the conversion availables.

Inline Function: scaled xx2sp (float v)
convert the value v expressed in the xx unit into scaled points.

Inline Function: float sp2xx (scaled sp)
convert sp scaled points into the unit xx.

Inline Function: int sp2ipx (scaled sp)
convert sp scaled points into an integral number of pixels.

The system of coordinates depends on the actual drawing area used for the rendering. For example, the standard "browser-like" coordinate system has the vertical components growing to the bottom. On the other hand, PostScript has the vertical components growing to the top. In either case, when referring to vertical coordinates, "lower" means "nearer to the origin".


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.2 Boxes and Rectangles

MathML elements are enclosed inside rectangles and boxes.

5.2.1 Rectangles  
5.2.2 Bounding Boxes  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.2.1 Rectangles

A rectangle is a tuple consisting of four components which locate the element by means of absolute coordinates.

Method: Rectangle void Zero ()
Set all the instance variables x, y, width and height to zero.

Method: Rectangle bool Overlaps (const Rectangle& rect)
Return true if the rectangle (partially) overlaps with rect.

Method: Rectangle bool Overlaps (scaled x0, scaled y0, scaled w0, scaled h0)
Same as the previous method, but the rectangle is given in its components.

Method: Rectangle bool IsNull ()
Return true if the rectangle is null, that is if either width or height is strictly less than a predefined constant EPSILON.

Method: Rectangle bool IsInside (scaled x, scaled y)
Return true if the point (x, y) is inside the rectangle.

Method: Rectangle void Union (const Rectangle& rect)
Set the rectangle as the smallest rectangle which comprises both *this and rect.

Method: Rectangle void Dump ()
Debug method.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.2.2 Bounding Boxes

A bounding box is a tuple which identifies the extent of an element, but not its absolute position.

Method: BoundingBox void Null ()
Nullify the box.

Method: BoundingBox bool IsNull ()
Return true if the box is null.

Method: BoundingBox scaled GetHeight ()
Return the height of the box, given as the sum of ascent and descent.

Method: BoundingBox scaled GetTotalHeight ()
Return the "total height" of the box, given as the sum of tAscent and tDescent.

Method: BoundingBox void Set (scaled w, scaled a, scaled d)
Set the box to be non-null, with width w, ascent a, descent d, left bearing 0 and right bearing w.

Method: BoundingBox void Set (scaled w, scaled a, scaled d, scaled l, scaled r)
Set the box to be non-null, with width w, ascent a, descent d, left bearing l and right bearing r.

Method: BoundingBox void Append (const BoundingBox& box)
Enlarge current bounding box as if box was "appended" right after it. All the instance variable are updated accordingly.

Method: BoundingBox void Append (scaled w)
Augment the width of the current bounding box by w.

Method: BoundingBox void Max (const BoundingBox& box)
Enlarge current bounding box as if box was "overlaid" on top of it.

Method: BoundingBox void ToRectangle (scaled x, scaled y, Rectangle& rect)
Initialize a rectangle rect from the current bounding box as if it was placed at (x, y).

Method: BoundingBox void Dump ()
Debug method.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.3 The MathMLRenderingEngine Class

Method: MathMLRenderingEngine MathMLRenderingEngine ()
This is the default constructor of the rendering engine.

Method: MathMLRenderingEngine ~MathMLRenderingEngine ()
The descructor.

Method: MathMLRenderingEngine void InitGlobalData (const char* confPath)
Global initialization function. Must be called once (and only once) no matter how many instances of the rendering engine are created. confPath is the full path to the engine's configuration file. If it is NULL then the engine will try to open the default configuration file (usually located in `/usr/local/share/gtkmathview').

Method: MathMLRenderingEngine void Init (DrawingArea* area, FontManager* fm)
Initialization function. Must be called before any other method of this class is invoked. area must be a non-NULL pointer to an already instantiated DrawingArea object and fm must be a non-NULL pointer to an already instantiated FontManager object.

Method: MathMLRenderingEngine bool Load (const char* uri)
Load the document whose URI is uri. The document is parsed, the setup is done (see below). Return true if the document has been loaded correctly, false otherwise.

Method: MathMLRenderingEngine bool Load (const DOM::Document& doc)
Load the document whose DOM structure is doc. Return true if the document has been loaded correctly, false otherwise.

Method: MathMLRenderingEngine bool Load (const DOM::Element& elem)
Load the MathML document whose root math element is elem. Return true if the document has been loaded correctly, false otherwise.

Method: MathMLRenderingEngine void Unload ()
Unload the document currently loaded and release all resources associated to it. This method is implicitly called by the load method.

Method: MathMLRenderingEngine void SetDirty (const Rectangle* rect = 0)
Force a set of MathML elements to be redrawn. If rect is specified (i.e. it is non-NULL), then only elements whose bounding box has a non-empty intersection with rect are set as "dirty". If rect is NULL, all the elements in the document are set as "dirty". Only dirty elements will be drawn in the next call to the update method.

Method: MathMLRenderingEngine void Render (const Rectangle* rect = 0)
Render the whole document if rect is NULL, or all MathML elements whose bounding box has a non-empty intersection with rect.

Method: MathMLRenderingEngine Ptr<MathMLElement> GetRoot ()
Return the document's root element.

Method: MathMLRenderingEngine Ptr<MathMLDocument> GetDocument ()
Return the document.

Method: MathMLRenderingEngine Ptr<MathMLElement> GetElementAt (scaled x, scaled y)
Return the element pointed to by (x, y), or 0 if there is no element at that coordinates.

Method: MathMLRenderingEngine void GetDocumentBoundingBox (BoundingBox& box)
Initialize box with the bounding box of the whole document.

Method: MathMLRenderingEngine void GetDocumentRectangle (Rectangle& rect)
Initialize rect with the rectangle of the whole document.

Method: MathMLRenderingEngine void SetDefaultFontSize (unsigned size)
Set the default font size for the document. size is supposed to be expressed in points.

Method: MathMLRenderingEngine unsigned GetDefaultFontSize ()
Return the current default font size for the document in points.

Method: MathMLRenderingEngine void SetVerbosity (int level)
Set the verbosity level to level. Valid levels are the integers from 0 to 3, each associated to an increasing verbosity of messages.

Method: MathMLRenderingEngine int GetVerbosity ()
Return the current level of verbosity as an index from 0 to 3.

Method: MathMLRenderingEngine void SetAntiAliasing (bool b)
Enable anti-aliasing if b is true, disable otherwise. The document is updated at each invocation of this method. Anti-aliasing is available with Type1 fonts only and it is much slower than non-anti-aliased mode.

Method: MathMLRenderingEngine bool GetAntiAliasing ()
Return true if anti-aliasing is enabled.

Method: MathMLRenderingEngine void SetTransparency (bool b)
Enable transparency if b is true, disable otherwise. Transparency allows two or more glyphs to overlap transparently, which is rather useful in the case of combining characters. Since these characters are not frequent and transparency is slower than standard rendering mode, the default for transparency is false. Note also that transparency is currently supported for Type1 fonts only.

Method: MathMLRenderingEngine bool GetTransparency ()
Return true if transparency is enabled.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6. GTK+ Interface

The GTK+ interface provides a set of high-level methods for the creation, the usage, and the destruction of instances of the GtkMathView widget.

Macro: GTK_TYPE_MATH_VIEW
used to get the GTK type for the GtkMathView class. It is not normally needed, unless one is subclassing gtkmathview.

Macro: GTK_MATH_VIEW (object)
used to cast a Gtk widget to a GtkMathView class. Remember that all methods working with the widget takes a pointer to GtkMathView.

Macro: GTK_MATH_VIEW_CLASS (klass)
used to cast a Gtk class to a GtkMathView class. This macro is used internally, it is not normally needed.

Macro: GTK_IS_MATH_VIEW (object)
used to test wether a Gtk object is indeed a GtkMathView object. It is normally used as a runtime check before casting object to the GtkMathView type.

Method: GtkType gtk_math_view_get_type ()
allocates a new Gtk type for the class GtkMathView. Used internally.

Method: GtkWidget* gtk_math_view_new (GtkAdjustment* h_adj, GtkAdjustment* v_adj)
this is the main constructor for GtkMathView. It allocates a new GtkMathView object. You can pass a couple of adjustments for the scrolling bars, or just NULL in the case you want the widget to allocate its own scrolling bars.

Method: void gtk_math_view_freeze (GtkMathView* widget)
after the invocation of this method any update of the widget is postponed until the invocation of the gtk_math_view_thaw method. It can be useful to stop automatic update of the widget in those cases in which a large number of modifications to the source document tree are done, so that it would be inefficient and useless to update the view at every single modification.

Method: void gtk_math_view_thaw (GtkMathView* widget)
update the widget after the invocation of the gtk_math_view_freeze method. Any modification to the source document tree that occurred while the widget was "frozen" is displayed at this time.

Method: gboolean gtk_math_view_load (GtkMathView* widget, const gchar* uri)
load the MathML document whose URI is uri and display it. If the loading succeed then TRUE is returned, FALSE otherwise.

Method: gboolean gtk_math_view_load_doc (GtkMathView* widget, GdomeDocument* doc)
display the doc document. If the operation succeeds then TRUE is returned, FALSE otherwise.

Method: gboolean gtk_math_view_load_tree (GtkMathView* widget, GdomeElement* elem)
display the MathML fragment whose root is elem in the widget's window. elem must be a math element in the MathML namespace.

Method: void gtk_math_view_unload (GtkMathView* widget)
unload a document from the widget, release all resources related to the document itself. This is automatically invoked if you load two subsequent documents, so you don't need to call this method explicitly.

Method: void gtk_math_view_load_select (GtkMathView* widget, GdomeElement* elem)
mark the element elem as "selected." This has the effect of highlighting the portion of the widget's window that include the element itself, along with all its children.

Method: void gtk_math_view_load_unselect (GtkMathView* widget, GdomeElement* elem)
mark the element elem as "not selected."

Method: gboolean gtk_math_view_load_is_selected (GtkMathView* widget, GdomeElement* elem)
query about the selection status of the element elem, return TRUE if elem is selected, FALSE otherwise.

Method: gboolean gtk_math_view_get_element_coords (GtkMathView* widget, GdomeElement* elem, gint* x, gint* y)
return the coordinates of the upper-left corner of the rectangular area covered by the element elem. If elem does not belong to the rendered document, or if it has no corresponding visual object, the method returns FALSE and x and y are left unchanged.

Method: gboolean gtk_math_view_get_element_rectangle (GtkMathView* widget, GdomeElement* elem, GdkRectangle* rect)
return the position and the extents of the rectangular area covered by the element elem. If elem does not belong to the rendered document, or if it has no corresponding visual object, the method returns FALSE and rect is left unchanged.

Method: guint gtk_math_view_get_width (GtkMathView* widget)
return the width of the drawable area of the widget. Note that this is not necessarily equal to the whole widget width, due to the inner frame.

Method: guint gtk_math_view_get_height (GtkMathView* widget)
return the height of the drawable area of the widget. Same remark as for gtk_math_view_get_width.

Method: void gtk_math_view_get_top (GtkMathView* widget, guint* top_x, guint* top_y)
return in top_x and top_y the coordinates (in pixels) of the upper left displayed corner of the document. Either top_x or top_y may be NULL, if you are interested in only one of the two values.

Method: void gtk_math_view_set_top (GtkMathView* widget, guint top_x, guint top_y)
set the coordinates (in pixels) of the upper left displayed corner of the document.

Method: void gtk_math_view_set_adjustments (GtkMathView* widget, GtkAdjustment* h_adj, GtkAdjustment* v_adj)
set the horizontal and vertical adjustments for the widget.

Method: GtkAdjustment* gtk_math_view_get_hadjustment (GtkMathView* widget)
return a pointer to the horizontal adjustment of the widget.

Method: GtkAdjustment* gtk_math_view_get_vadjustment (GtkMathView* widget)
return a pointer to the vertical adjustment of the widget.

Method: GdkPixmap* gtk_math_view_get_buffer (GtkMathView* widget)
return a pointer to the internal GdkPixmap used by the widget as the backbuffer.

Method: GtkFrame* gtk_math_view_get_frame (GtkMathView* widget)
return a pointer to the GtkFrame used by the widget to draw the border around the drawable area.

Method: GtkDrawingArea* gtk_math_view_get_drawing_area (GtkMathView* widget)
Returns the GTK+ widget representing the drawing area that the widget uses for rendering on the screen. The returned widget can be used for setting signal handlers other than those generated directly by GtkMathView.

Method: void gtk_math_view_set_font_size (GtkMathView* widget, guint size)
set the default font size (in points) for displaying documents.

Method: guint gtk_math_view_get_font_size (GtkMathView* widget)
return the default font size (in points) for displaying documents.

Method: void gtk_math_view_set_anti_aliasing (GtkMathView* widget, gboolean b)
enable or disable anti-aliasing according to the value of flag. Anti-aliasing of characters is only available when Type1 fonts are used.

Method: gboolean gtk_math_view_get_anti_aliasing (GtkMathView* widget)
return TRUE if anti-aliasing is enabled (even if it is not supported), FALSE otherwise.

Method: gboolean gtk_math_view_set_transparency (GtkMathView* widget, gboolean b)
enable/disable transparency. This is available for Type1 fonts only. Transparency can be enabled for documents containing combining or otherwise overlapping characters. When transparency is enabled, only coloured pixels are drawn, leaving the background untouched. This prevents from glyphs overwriting one each other when they overlap. Since transparent mode is heavier than opaque mode, it is disabled by default.

Method: gboolean gtk_math_view_get_transparency (GtkMathView* widget, gboolean b)
retrieve the current state of transparency.

Method: void gtk_math_view_log_set_verbosity (GtkMathView* widget, gint level)
set the level of verbosity for displayed messages. level can be an integer from 0 (very few messages, in case of error only) to 3 (all messages). Useful for debugging purposes.

Method: gint gtk_math_view_log_get_verbosity (GtkMathView* widget)
return the current level of verbosity.

Method: void gtk_math_view_export_to_postscript (GtkMathView* widget, gint width, gint height, gint x0, gint y0, gboolean disable_colors, FILE* f)
write a rendered document to the file f in PostScript format. width, height, x0 and y0 give the size and the margins (in pixels) of the rendering area used by this method. disable_colors can be set to TRUE if you don't want to render colors in PostScript (this may be useful to print the document on a black-and-white printer).

Method: void gtk_math_view_set_font_manager_type (GtkMathview* widget, FontManagerId id)
Set the font manager used by the widget to retrieve fonts. Up 'till now, there are two valid values for id: use FONT_MANAGER_GTK to use the GTK font manager (actually, this is just a wrapper for the X font manager). This is the default. Alternatively, use FONT_MANAGER_T1 to use t1lib and Type1 fonts. This font manager is availabe only if you have installed the t1lib library.

Method: FontManagerId gtk_math_view_get_font_manager_type (GtkMathView* widget)
Return the current font manager id.

Signal: void "click" (GdomeElement* elem, gint state)
emitted whenever the user click on the displaying window. elem is the reference to the DOM element on which the used clicked, or NULL if the area clicked does not correspond to any MathML element. state represents the status of the control keys at the moment of the click event. Its possible values are the same as for the GdkModifier type.

Signal: void "select_begin" (GdomeElement* elem, gint state)
emitted when the user starts a selection, that is the first mouse button is pressed and the mouse is moved a bit from the original location. The elem and state arguments have the same meaning as for the click signal.

Signal: void select_over (GtkWidget* widget, GdomeElement* elem, int state)
emitted when the user moves the mouse while keeping the first button pressed. elem is the element which the mouse pointer is currently on.

Signal: void "select_end" (GdomeElement* node, gint state)
emitted when the user finally releases the mouse button after a selection.

Signal: void "select_abort" ()
emitted when the user presses the second mouse button when selection is progress, to notify that selection is aborted.

Signal: void "element_over" (GdomeElement* elem, gint state)
emitted as the user moves the mouse on the document, no matter of the state of the mouse buttons.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7. Tools

There are some tools provided along the widget. We will shortly describe them in the following two sections.

7.1 mathmlviewer  A simple viewer application.
7.2 mathml2ps  A MathML => PostScript conversion utility.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.1 mathmlviewer

This is a simple browsing application whose purpose is twofold. First, it is an example of application using the GtkMathView widget. Second, it allows viewing MathML documents. A document is referenced by means of a URL or just a file name.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

7.2 mathml2ps

This is a simple utility which allows to render a MathML document to PostScript. In addition to this, it shows how the widget's rendering engine can be exploited in a non-GTK+ application.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8. Bugs and Contributions

I appreciate any kind of contribution. The most basic (and, maybe, frequent) one is bug report. You can either send me an email (luca.padovani at cs.unibo.it) with a short description of the problem encountered, a list of the error messages or failed assertions and the simplest MathML document that causes the trouble, or use the Bugzilla Web interface at http://bugs.mowgli.cs.unibo.it, the module name is obviously GtkMathView.

If you think that the problem may be of interest for other people too, then I encourage to subscribe and post the report on the mailing list. You can subscribe by sending an empty email to the address gtkmathview-subscribe at cs.unibo.it.


[Top] [Contents] [Index] [ ? ]

Footnotes

(1)

See url{http://www.w3.org/TR/MathML2

(2)

See http://www.unicode.org


[Top] [Contents] [Index] [ ? ]

Table of Contents

1. Overview
2. Usage
2.1 Download
2.2 Requirements
2.3 Installing
2.4 Compile and Link
2.5 Configuration
2.5.1 Main Configuration File
2.5.2 Operator Dictionary
2.5.3 Font Setup
3. Interactivity Support
3.1 Selection
3.2 Point-and-click Functionalities
3.3 Editing
4. Sample Application
5. C++ Interface
5.1 Lengths
5.2 Boxes and Rectangles
5.2.1 Rectangles
5.2.2 Bounding Boxes
5.3 The MathMLRenderingEngine Class
6. GTK+ Interface
7. Tools
7.1 mathmlviewer
7.2 mathml2ps
8. Bugs and Contributions

[Top] [Contents] [Index] [ ? ]

Short Table of Contents

1. Overview
2. Usage
3. Interactivity Support
4. Sample Application
5. C++ Interface
6. GTK+ Interface
7. Tools
8. Bugs and Contributions

[Top] [Contents] [Index] [ ? ]

About this document

This document was generated using texi2html

The buttons in the navigation panels have the following meaning:

Button Name Go to From 1.2.3 go to
[ < ] Back previous section in reading order 1.2.2
[ > ] Forward next section in reading order 1.2.4
[ << ] FastBack previous or up-and-previous section 1.1
[ Up ] Up up section 1.2
[ >> ] FastForward next or up-and-next section 1.3
[Top] Top cover (top) of document  
[Contents] Contents table of contents  
[Index] Index concept index  
[ ? ] About this page  

where the Example assumes that the current position is at Subsubsection One-Two-Three of a document of the following structure:

This document was generated by Luca Padovani on March, 24 2003 using texi2html