[cairo-commit] papers/opengl_freenix04 opengl_freenix04.tex, 1.42, 1.43

David Reveman commit at pdx.freedesktop.org
Tue Apr 6 04:55:04 PDT 2004


Committed by: davidr

Update of /cvs/cairo/papers/opengl_freenix04
In directory pdx:/tmp/cvs-serv10702

Modified Files:
	opengl_freenix04.tex 
Log Message:
fixes

Index: opengl_freenix04.tex
===================================================================
RCS file: /cvs/cairo/papers/opengl_freenix04/opengl_freenix04.tex,v
retrieving revision 1.42
retrieving revision 1.43
diff -C2 -d -r1.42 -r1.43
*** a/opengl_freenix04.tex	5 Apr 2004 14:15:29 -0000	1.42
--- b/opengl_freenix04.tex	6 Apr 2004 11:55:01 -0000	1.43
***************
*** 319,332 ****
      feature on the regular home desktop computer.
  
!     Pixel buffers or so called pbuffers are what makes off-screen rendering
      possible in OpenGL. Pbuffers are allocated independently of the
      framebuffer and usually stored in video memory. The process of 
      rendering to pbuffer is accelerated by hardware in the same way as
!     rendering to the frambuffer. However, as pbuffers is a relatively
      new feature in the OpenGL world, it is not yet supported by all 
      hardware and all drivers. When support for off-screen drawing is
      missing, the application using \libname{} will have to handle this
      on its own. Even though \libname{} is primarily designed for modern
!     graphics hardware it's important to be able to fall back to software
      rendering in cases where \libname{} is not able to carry out off-screen
      drawing operations. For example, the cairo library handles this 
--- 319,332 ----
      feature on the regular home desktop computer.
  
!     Pixel buffers or so called pbuffers are what make off-screen rendering
      possible in OpenGL. Pbuffers are allocated independently of the
      framebuffer and usually stored in video memory. The process of 
      rendering to pbuffer is accelerated by hardware in the same way as
!     rendering to the framebuffer. However, as pbuffers is a relatively
      new feature in the OpenGL world, it is not yet supported by all 
      hardware and all drivers. When support for off-screen drawing is
      missing, the application using \libname{} will have to handle this
      on its own. Even though \libname{} is primarily designed for modern
!     graphics hardware, it's important to be able to fall back on software
      rendering in cases where \libname{} is not able to carry out off-screen
      drawing operations. For example, the cairo library handles this 
***************
*** 370,374 ****
      operation creates some additional complications. The source surfaces
      must first be composited onto the mask using the Porter-Duff in-operator
!     and the result should then be composited onto the destination. The
      default method for handling this is to create an intermediate off-screen
      surface, which can be used for compositing using the in-operator.
--- 370,374 ----
      operation creates some additional complications. The source surfaces
      must first be composited onto the mask using the Porter-Duff in-operator
!     and the result must then be composited onto the destination. The
      default method for handling this is to create an intermediate off-screen
      surface, which can be used for compositing using the in-operator.
***************
*** 380,385 ****
      Even though the fixed OpenGL pipeline doesn't seem to allow for such an 
      operation, \libname{} is able to do this on hardware that support
!     fragment programs. Fragment programs allows for fragment level
!     programmability in OpenGL and in combination with multi-texturing 
      \libname{} can perform composite operations with a mask surface
      very efficiently.
--- 380,385 ----
      Even though the fixed OpenGL pipeline doesn't seem to allow for such an 
      operation, \libname{} is able to do this on hardware that support
!     fragment programs. Fragment programs allow for fragment level
!     programmability in OpenGL, and in combination with multi-texturing, 
      \libname{} can perform composite operations with a mask surface
      very efficiently.
***************
*** 390,405 ****
      done on all available hardware and with all available OpenGL
      implementations. \Libname{} simply transforms the vertex coordinates
!     of the rectangular polygon used for texturing and OpenGL will then in 
      hardware transform each fragment of the source surfaces.
  
      When using fragment programs for direct compositing with mask
!     surfaces some transformations cannot be done as the source
      surface and the mask surfaces share vertex coordinates. If this is 
!     the case \libname{} will be forced to not use direct compositing.
     
      \subsection{Repeating Patterns}
  
      To provide for solid colors and repeating patterns, surfaces have a 
!     `repeat' attribute. When set, the surface is treated as if it's width 
      and height were infinite by tiling the contents of the surface along 
      both axes.
--- 390,405 ----
      done on all available hardware and with all available OpenGL
      implementations. \Libname{} simply transforms the vertex coordinates
!     of the rectangular polygon used for texturing, and OpenGL will then in 
      hardware transform each fragment of the source surfaces.
  
      When using fragment programs for direct compositing with mask
!     surfaces, some transformations cannot be done since the source
      surface and the mask surfaces share vertex coordinates. If this is 
!     the case, \libname{} will be forced to not use direct compositing.
     
      \subsection{Repeating Patterns}
  
      To provide for solid colors and repeating patterns, surfaces have a 
!     `repeat' attribute. When set, the surface is treated as if its width 
      and height were infinite by tiling the contents of the surface along 
      both axes.
***************
*** 408,416 ****
      are power of two sized. If surface dimensions are of this size
      \libname{} can let OpenGL handle the tiling for maximum efficiency.
!     For surfaces that don't have power of two sized dimensions
      \libname{} will repeat the surfaces manually by performing multiple
      texturing operations.
  
!     Some OpenGL implementations supports tiling of none power of two sized
      textures as well. If this is the case, \libname{} will let OpenGL 
      handle tiling of all surfaces.
--- 408,416 ----
      are power of two sized. If surface dimensions are of this size
      \libname{} can let OpenGL handle the tiling for maximum efficiency.
!     For surfaces that don't have power of two sized dimensions,
      \libname{} will repeat the surfaces manually by performing multiple
      texturing operations.
  
!     Some OpenGL implementations support tiling of none power of two sized
      textures as well. If this is the case, \libname{} will let OpenGL 
      handle tiling of all surfaces.
***************
*** 421,435 ****
        trapezoids. Triangles are specified by locating their three vertices.
        Trapezoids are represented by two horizontal lines delimiting the top
!       and bottom of the trapezoid and two additional lines specified by
        arbitrary points. These primitives are designed to be used for
        rendering complex objects tessellated by higher level libraries.
  
        \Libname{} only supports imprecise pixelization. Precise pixelization
!       is not supported as OpenGL has relatively weak invariant 
        requirements of pixelization. This is because of the desire for 
        high-performance mixed software and hardware implementations.
!       \Libname{} matches the following set of invariants
!       for imprecise polygons Hence the visual artifacts associated with 
!       polygon tessellation and translation are minimized.
  
        \begin{itemize}
--- 421,434 ----
        trapezoids. Triangles are specified by locating their three vertices.
        Trapezoids are represented by two horizontal lines delimiting the top
!       and bottom of the trapezoid, and two additional lines specified by
        arbitrary points. These primitives are designed to be used for
        rendering complex objects tessellated by higher level libraries.
  
        \Libname{} only supports imprecise pixelization. Precise pixelization
!       is not supported since OpenGL has relatively weak invariant 
        requirements of pixelization. This is because of the desire for 
        high-performance mixed software and hardware implementations.
!       \Libname{} matches the following set of invariants for imprecise
!       polygons.
  
        \begin{itemize}
***************
*** 440,443 ****
--- 439,445 ----
        \end{itemize}
  
+       Hence the visual artifacts associated with polygon tessellation and
+       translation are minimized.
+ 
        \subsubsection{Anti-aliasing}
        
***************
*** 456,464 ****
        enough. 
  
!       The results of aliasing are called artifacts, the most common 
        artifacts in computer graphics include jagged profiles, 
        disappearing or improperly rendered fine detail and disintegrating 
!       textures. The most obvious one and the one that most applies 
!       to 2D graphics is the jagged profile artifact.
        Figure~\ref{jaggies} illustrates an aliased graphical image suffering 
        from a jagged edge.
--- 458,466 ----
        enough. 
  
!       The results of aliasing are called artifacts. The most common 
        artifacts in computer graphics include jagged profiles, 
        disappearing or improperly rendered fine detail and disintegrating 
!       textures. The most obvious one, and the one that most applies 
!       to 2D graphics, is the jagged profile artifact.
        Figure~\ref{jaggies} illustrates an aliased graphical image suffering 
        from a jagged edge.
***************
*** 479,483 ****
        along the borders of graphical elements. There are several techniques 
        that can be used to achieve anti-aliased graphics rendering with the 
!       OpenGL API. The most common techniques include;
    
        \begin{itemize}
--- 481,485 ----
        along the borders of graphical elements. There are several techniques 
        that can be used to achieve anti-aliased graphics rendering with the 
!       OpenGL API. The most common techniques include:
    
        \begin{itemize}
***************
*** 503,507 ****
        immediate rendering model used in \libname.
  
!       The anti-aliasing model chosen for \libname{} is very flexible
        and other techniques can easily be added for special cases later on.
        The current implementation uses hardware assisted full-scene 
--- 505,509 ----
        immediate rendering model used in \libname.
  
!       The anti-aliasing model chosen for \libname{} is flexible
        and other techniques can easily be added for special cases later on.
        The current implementation uses hardware assisted full-scene 
***************
*** 525,529 ****
        people may not find them acceptable for small text. This doesn't 
        affect the choice in this case however, as anti-aliasing of text will 
!       preferably be handled by the external font rendering library.
        On high end systems this technique has potential for generating 
        extremely high quality results with a relatively low cost. Unfortunately 
--- 527,531 ----
        people may not find them acceptable for small text. This doesn't 
        affect the choice in this case however, as anti-aliasing of text will 
!       preferably be handled by an external font rendering library.
        On high end systems this technique has potential for generating 
        extremely high quality results with a relatively low cost. Unfortunately 
***************
*** 540,551 ****
        The first method creates an off-screen surface containing only an alpha
        channel. The polygons are then rendered into this intermediate surface,
!       which is then used as mask when compositing the supplied source surface
        onto the destination surface. This method requires off-screen drawing
!       support and anti-aliased polygon edges can
!       only be rendered if off-screen multi-sample support is available. 
    
        Whenever a stencil buffer is available, it will be used for drawing
        indirect polygons. The polygons are then rendered into the stencil
!       buffer and the stencil buffer is then used for clipping when
        compositing the supplied source surface onto the destination surface. 
        This method for drawing indirect polygons is faster and doesn't require
--- 542,553 ----
        The first method creates an off-screen surface containing only an alpha
        channel. The polygons are then rendered into this intermediate surface,
!       which is used as mask when compositing the supplied source surface
        onto the destination surface. This method requires off-screen drawing
!       support, and anti-aliased polygon edges can only be rendered if
!       off-screen multi-sample support is available. 
    
        Whenever a stencil buffer is available, it will be used for drawing
        indirect polygons. The polygons are then rendered into the stencil
!       buffer and the stencil buffer is used for clipping when
        compositing the supplied source surface onto the destination surface. 
        This method for drawing indirect polygons is faster and doesn't require
***************
*** 561,577 ****
        and colors are linearly interpolated between the vertices. Direct
        polygons have the advantages of not requiring an intermediate off-screen
!       surface or stencil buffer and are therefor faster and supported on more
        hardware. Direct polygons might not produce the same results as indirect
!       polygons when alpha component differ from one and should as a result not
!       be used for complex objects with these properties. The more general
!       indirect polygons should instead be used in these cases.
  
      \subsection{Text Rendering}
  
!     Current versions of \libname{} has no built in text support. 
      Glyph rasterization and glyph management could however be handled by 
      the application or a higher level library. For efficient text rendering, 
!     glyph sets with off-screen surfaces containing alpha masks should be 
!     used. With external glyph management \libname{} renders text at 
      approximately 50000 glyphs/sec on the test setup described in section
      \ref{section: Results}.
--- 563,579 ----
        and colors are linearly interpolated between the vertices. Direct
        polygons have the advantages of not requiring an intermediate off-screen
!       surface or stencil buffer and are therefor faster, and supported on more
        hardware. Direct polygons might not produce the same results as indirect
!       polygons when the alpha color component is not equal to one and should
!       as a result not be used for complex objects with these properties. 
!       The more general indirect polygons should instead be used in these cases.
  
      \subsection{Text Rendering}
  
!     Current version of \libname{} has no built in text support. 
      Glyph rasterization and glyph management could however be handled by 
      the application or a higher level library. For efficient text rendering, 
!     glyph-sets with off-screen surfaces containing alpha masks, should be 
!     used. With external glyph management, \libname{} renders text at 
      approximately 50000 glyphs/sec on the test setup described in section
      \ref{section: Results}.
***************
*** 608,612 ****
  
      In \libname{} convolution filtering is implemented using fragment
!     programs and is only available on hardware that have fragment program.
      The alternative would be to use OpenGL's imaging extension, which would
      require a transfer of all pixels through OpenGL's pixel pipeline to an
--- 610,614 ----
  
      In \libname{} convolution filtering is implemented using fragment
!     programs and is only available on hardware with fragment program support.
      The alternative would be to use OpenGL's imaging extension, which would
      require a transfer of all pixels through OpenGL's pixel pipeline to an
***************
*** 618,622 ****
  
      Table~\ref{conv} presents three useful convolution kernels and
!     figures ~\ref{original} and ~\ref{filtered} shows the results of filtering
      an image using a gaussian convolution kernel.
  
--- 620,624 ----
  
      Table~\ref{conv} presents three useful convolution kernels and
!     figure ~\ref{original} and ~\ref{filtered} show the results of filtering
      an image using a gaussian convolution kernel.
  
***************
*** 686,690 ****
      radial transition vector patterns. A linear pattern defines two points,
      which form a transition vector. A radial gradient defines a center point
!     and a radius, together they form a dynamic transition vector around the 
      center point. The color of each fragment in these programmatic surfaces
      is fetched from a color range, using the fragments offset along the
--- 688,692 ----
      radial transition vector patterns. A linear pattern defines two points,
      which form a transition vector. A radial gradient defines a center point
!     and a radius, which together form a dynamic transition vector around the 
      center point. The color of each fragment in these programmatic surfaces
      is fetched from a color range, using the fragments offset along the
***************
*** 696,700 ****
      applications to use linear and radial patterns for wide range of 
      shading effects. e.g. linear color gradients and gaussian shading. 
!     By setting the \emph{extend} attribute of a color range to one of 
      \emph{pad, repeat} or \emph{reflect}, the application can also control
      what should happend when patterns try to fetch color values outside 
--- 698,702 ----
      applications to use linear and radial patterns for wide range of 
      shading effects. e.g. linear color gradients and gaussian shading. 
!     By setting the \emph{extend} attribute of a color range to 
      \emph{pad, repeat} or \emph{reflect}, the application can also control
      what should happend when patterns try to fetch color values outside 
***************
*** 722,726 ****
      
      In addition to the 2D drawing functions \libname{} also
!     provides a set of functions that makes it possible to use
      \libname{} as a cross-platform OpenGL layer. The following three 
      functions allow the application to use ordinary OpenGL calls
--- 724,728 ----
      
      In addition to the 2D drawing functions \libname{} also
!     provides a set of functions that make it possible to use
      \libname{} as a cross-platform OpenGL layer. The following three 
      functions allow the application to use ordinary OpenGL calls
***************
*** 743,752 ****
      An application can use both \libname's 2D drawing functions
      and ordinary OpenGL calls on all surfaces as long as all OpenGL calls
!     are made in the scope between the \libnamespace\_gl\_begin and 
!     \libnamespace\_gl\_end calls.
  
      \libnamespace\_get\_gl\_texture allows the application 
      to retrieve a texture name for a \libname{} surface. The application 
!     can then use this texture name with ordinary OpenGL calls.
  
      \begin{figure}[h!tbp]
--- 745,754 ----
      An application can use both \libname's 2D drawing functions
      and ordinary OpenGL calls on all surfaces as long as all OpenGL calls
!     are made within the scope of \libnamespace\_gl\_begin and 
!     \libnamespace\_gl\_end.
  
      \libnamespace\_get\_gl\_texture allows the application 
      to retrieve a texture name for a \libname{} surface. The application 
!     can use this texture name with ordinary OpenGL calls.
  
      \begin{figure}[h!tbp]
***************
*** 811,815 ****
      
    Right now the library hasn't been tested that much in real
!   applications as it is relatively early in the development process. 
    Some test and benchmark utilities have been developed to analyze library
    functionality with respect to accuracy and performance. 
--- 813,817 ----
      
    Right now the library hasn't been tested that much in real
!   applications since it's relatively early in the development process. 
    Some test and benchmark utilities have been developed to analyze library
    functionality with respect to accuracy and performance. 
***************
*** 820,829 ****
    corresponding output from Xrender. Most objects tessellated by the cairo
    library are rendered without noticeable differences compared to Xrender
!   using \libname{}. However in some complex objects a slight
    variation can be seen between \libname's output and Xrender's output. 
!   Figures~\ref{Infinity Sign 1} and~\ref{Infinity Sign 2} illustrates the
    output inconsistencies for aliased rendering. The infinite sign is 
    tessellated into 370 trapezoids by the cairo library, which are then
!   rendered using \libname{} and xrender. Both figures are magnified to
    better show the output differences.
    
--- 822,831 ----
    corresponding output from Xrender. Most objects tessellated by the cairo
    library are rendered without noticeable differences compared to Xrender
!   using \libname{}. However, in some complex objects a slight
    variation can be seen between \libname's output and Xrender's output. 
!   Figure~\ref{Infinity Sign 1} and~\ref{Infinity Sign 2} illustrates the
    output inconsistencies for aliased rendering. The infinite sign is 
    tessellated into 370 trapezoids by the cairo library, which are then
!   rendered using \libname{} and Xrender. Both figures are magnified to
    better show the output differences.
    
***************
*** 847,858 ****
  
    Anti-aliased rendering may introduce some additional inconsistencies in 
!   the output between \libname{} and Xrender. Different anti-aliasing 
!   techniques might be used in \libname{} depending on the graphics driver and 
!   hardware being used. On older hardware anti-aliasing isn't even 
!   guaranteed as it depends on relatively new OpenGL extensions. 
!   Nevertheless, if \libname{} is run on fairly modern graphics hardware, 
!   very similar results are achieved with anti-aliased output.  
!   Figures~\ref{Infinity Sign 3} and~\ref{Infinity Sign 4} shows the same
!   object as above and illustrates the output inconsistencies for
    anti-aliased rendering.
    
--- 849,860 ----
  
    Anti-aliased rendering may introduce some additional inconsistencies in 
!   the output between \libname{} and Xrender. The number of samples used
!   for multi-sampling has a big effect on the anti-aliasing quailty.
!   On older hardware, anti-aliasing isn't even guaranteed as it depends on
!   relatively new OpenGL extensions. Nevertheless, if \libname{} is run on
!   fairly modern graphics hardware, very similar results are achieved with
!   anti-aliased output.  
!   Figure~\ref{Infinity Sign 3} and~\ref{Infinity Sign 4} show the same
!   infinite sign and illustrates the output inconsistencies for
    anti-aliased rendering.
    
***************
*** 861,865 ****
        \epsfig{file=inf-gl-aa.eps}
        \small\itshape
!       \caption{\small\itshape Anti-Aliased OpenGL output}
        \label{Infinity Sign 3}
      \end{centering}
--- 863,868 ----
        \epsfig{file=inf-gl-aa.eps}
        \small\itshape
!       \caption{\small\itshape Anti-Aliased OpenGL output
!                               (using 4 samples multi-sampling)}
        \label{Infinity Sign 3}
      \end{centering}
***************
*** 870,874 ****
        \epsfig{file=inf-xr-aa.eps}
        \small\itshape
!       \caption{\small\itshape Anti-Aliased xrender output}
        \label{Infinity Sign 4}
      \end{centering}
--- 873,877 ----
        \epsfig{file=inf-xr-aa.eps}
        \small\itshape
!       \caption{\small\itshape Anti-Aliased Xrender output}
        \label{Infinity Sign 4}
      \end{centering}
***************
*** 886,893 ****
    This section presents results from a benchmark utility named rendermark.
    Rendermark compares the rendering performance of \libname{}, Xrender and
!   Imlib2~\cite{imlib2} by doing a set of basic operations repeated times.
!   Comparison with Imlib2 is interesting as it's promoted as the fastest
!   image compositing, rendering and manipulation library for X. Imlib2
!   performs all its rendering operations on client-side image buffers, so
    no on-screen rendering results are available for Imlib2.
  
--- 889,896 ----
    This section presents results from a benchmark utility named rendermark.
    Rendermark compares the rendering performance of \libname{}, Xrender and
!   Imlib2~\cite{imlib2} by doing a set of basic operations a repeated number
!   of times. Comparison with Imlib2 is interesting as it's promoted as
!   the fastest image compositing, rendering and manipulation library for X.
!   Imlib2 performs all its rendering operations on client-side image buffers, so
    no on-screen rendering results are available for Imlib2.
  
***************
*** 929,935 ****
    \end{table}
  
!   Repeat parameter 1000 is used for all tests. This means that each test
!   is repeated a thousand times and the time shown in the table is the time
!   needed to complete all thousand tests.
  
    \subsubsection{Image Compositing}
--- 932,937 ----
    \end{table}
  
!   Each test is repeated a thousand times and the time shown in the tables is
!   the time needed to complete all thousand tests.
  
    \subsubsection{Image Compositing}
***************
*** 952,957 ****
            blends one image onto another using the over operator with
            a blur filter. For \libname{} this means applying a 3x3 mean blur
!           convolution filter. The Xrender version used for these test doesn't
!           support convolution filters so Xrender skips this test.
    \end{itemize}
  
--- 954,959 ----
            blends one image onto another using the over operator with
            a blur filter. For \libname{} this means applying a 3x3 mean blur
!           convolution filter. The Xrender version used for this test doesn't
!           support convolution filters, and is therefor skipped by this test.
    \end{itemize}
  
***************
*** 979,984 ****
    \subsubsection{Color fill}
  
!   The following test evaluates color fill performance by drawing
!   solid rectangles.
  
    Table~\ref{rendermark2} shows the color fill results.
--- 981,985 ----
    \subsubsection{Color fill}
  
!   This test evaluates color fill performance by drawing solid rectangles.
  
    Table~\ref{rendermark2} shows the color fill results.
***************
*** 1088,1103 ****
  
    Table~\ref{rendermark5} shows that nvidia's driver performs well 
!   compared to \libname{} except for the case were transformations
!   are used. \libname{} is then much faster than nvidia's driver, which
!   most likely fall-backs to software rendering in this case.
  
    \section{Conclusion}
  
    During the development of \libname{} we've found that with the OpenGL 
!   API and the extensions available today and the wide range of hardware 
!   supporting them, it's not only possible to create an Render-like interface 
!   on top of OpenGL, it's actually very efficient. This is an important
!   conclusion as the desire for having an X server running on top of OpenGL
!   rapidly grows.
  
    The benchmark results points out \libname's remarkable rendering 
--- 1089,1104 ----
  
    Table~\ref{rendermark5} shows that nvidia's driver performs well 
!   compared to \libname{}, except for the case where transformations
!   are used. In this case \libname{} is much faster than nvidia's driver,
!   which most likely fall-backs on software rendering.
  
    \section{Conclusion}
  
    During the development of \libname{} we've found that with the OpenGL 
!   API and the extensions available today, along with the wide range of
!   hardware supporting them, it's not only possible to create an
!   Render-like interface on top of OpenGL, it's actually very efficient.
!   This is an important conclusion as the desire for having an X server
!   running on top of OpenGL grows rapidly.
  
    The benchmark results points out \libname's remarkable rendering 
***************
*** 1112,1120 ****
    \section{Future Work}
  
!   As of today the existing implementation of the library supports all 
!   the basic functionality initially set up for the project. But there are
!   still some important features missing and the software is in an early
!   stage of development and lots of work remains for making it stable and 
!   optimized with regards to performance and accuracy.
  
    The following list contains those features that most importantly need to 
--- 1113,1121 ----
    \section{Future Work}
  
!   Today, the existing implementation of the library supports all 
!   the basic functionality, which where initially set up for the project.
!   But there are still some important features missing, and the software is
!   in an early stage of development with a lot of work remaining to make it
!   stable and optimized with regards to performance and accuracy.
  
    The following list contains those features that most importantly need to 
***************
*** 1132,1137 ****
    \end{itemize}
  
!   Of course the future will demand new features from the library as it is an 
!   area of continuous development.
  
    \section{Visions}
--- 1133,1138 ----
    \end{itemize}
  
!   Of course the future will demand new features from the library, since it's
!   an area of continuous development.
  
    \section{Visions}
***************
*** 1150,1154 ****
    encouraging. We would also like to thank our internal supervisor 
    Berit Kvernes along with the staff at the department of Computing Science 
!   at Umeå University for supporting us in this project, thereby approving
    it for financial funding in terms of study allowances.
  
--- 1151,1155 ----
    encouraging. We would also like to thank our internal supervisor 
    Berit Kvernes along with the staff at the department of Computing Science 
!   at Umeå University for supporting us in this project by approving
    it for financial funding in terms of study allowances.
  





More information about the cairo-commit mailing list