ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ftbbox.c
Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ftbbox.c                                                               */
00004 /*                                                                         */
00005 /*    FreeType bbox computation (body).                                    */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2004, 2006, 2010 by                         */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used        */
00011 /*  modified and distributed under the terms of the FreeType project       */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019   /*************************************************************************/
00020   /*                                                                       */
00021   /* This component has a _single_ role: to compute exact outline bounding */
00022   /* boxes.                                                                */
00023   /*                                                                       */
00024   /*************************************************************************/
00025 
00026 
00027 #include <ft2build.h>
00028 #include FT_BBOX_H
00029 #include FT_IMAGE_H
00030 #include FT_OUTLINE_H
00031 #include FT_INTERNAL_CALC_H
00032 #include FT_INTERNAL_OBJECTS_H
00033 
00034 
00035   typedef struct  TBBox_Rec_
00036   {
00037     FT_Vector  last;
00038     FT_BBox    bbox;
00039 
00040   } TBBox_Rec;
00041 
00042 
00043   /*************************************************************************/
00044   /*                                                                       */
00045   /* <Function>                                                            */
00046   /*    BBox_Move_To                                                       */
00047   /*                                                                       */
00048   /* <Description>                                                         */
00049   /*    This function is used as a `move_to' and `line_to' emitter during  */
00050   /*    FT_Outline_Decompose().  It simply records the destination point   */
00051   /*    in `user->last'; no further computations are necessary since we    */
00052   /*    use the cbox as the starting bbox which must be refined.           */
00053   /*                                                                       */
00054   /* <Input>                                                               */
00055   /*    to   :: A pointer to the destination vector.                       */
00056   /*                                                                       */
00057   /* <InOut>                                                               */
00058   /*    user :: A pointer to the current walk context.                     */
00059   /*                                                                       */
00060   /* <Return>                                                              */
00061   /*    Always 0.  Needed for the interface only.                          */
00062   /*                                                                       */
00063   static int
00064   BBox_Move_To( FT_Vector*  to,
00065                 TBBox_Rec*  user )
00066   {
00067     user->last = *to;
00068 
00069     return 0;
00070   }
00071 
00072 
00073 #define CHECK_X( p, bbox )  \
00074           ( p->x < bbox.xMin || p->x > bbox.xMax )
00075 
00076 #define CHECK_Y( p, bbox )  \
00077           ( p->y < bbox.yMin || p->y > bbox.yMax )
00078 
00079 
00080   /*************************************************************************/
00081   /*                                                                       */
00082   /* <Function>                                                            */
00083   /*    BBox_Conic_Check                                                   */
00084   /*                                                                       */
00085   /* <Description>                                                         */
00086   /*    Finds the extrema of a 1-dimensional conic Bezier curve and update */
00087   /*    a bounding range.  This version uses direct computation, as it     */
00088   /*    doesn't need square roots.                                         */
00089   /*                                                                       */
00090   /* <Input>                                                               */
00091   /*    y1  :: The start coordinate.                                       */
00092   /*                                                                       */
00093   /*    y2  :: The coordinate of the control point.                        */
00094   /*                                                                       */
00095   /*    y3  :: The end coordinate.                                         */
00096   /*                                                                       */
00097   /* <InOut>                                                               */
00098   /*    min :: The address of the current minimum.                         */
00099   /*                                                                       */
00100   /*    max :: The address of the current maximum.                         */
00101   /*                                                                       */
00102   static void
00103   BBox_Conic_Check( FT_Pos   y1,
00104                     FT_Pos   y2,
00105                     FT_Pos   y3,
00106                     FT_Pos*  min,
00107                     FT_Pos*  max )
00108   {
00109     if ( y1 <= y3 && y2 == y1 )     /* flat arc */
00110       goto Suite;
00111 
00112     if ( y1 < y3 )
00113     {
00114       if ( y2 >= y1 && y2 <= y3 )   /* ascending arc */
00115         goto Suite;
00116     }
00117     else
00118     {
00119       if ( y2 >= y3 && y2 <= y1 )   /* descending arc */
00120       {
00121         y2 = y1;
00122         y1 = y3;
00123         y3 = y2;
00124         goto Suite;
00125       }
00126     }
00127 
00128     y1 = y3 = y1 - FT_MulDiv( y2 - y1, y2 - y1, y1 - 2*y2 + y3 );
00129 
00130   Suite:
00131     if ( y1 < *min ) *min = y1;
00132     if ( y3 > *max ) *max = y3;
00133   }
00134 
00135 
00136   /*************************************************************************/
00137   /*                                                                       */
00138   /* <Function>                                                            */
00139   /*    BBox_Conic_To                                                      */
00140   /*                                                                       */
00141   /* <Description>                                                         */
00142   /*    This function is used as a `conic_to' emitter during               */
00143   /*    FT_Outline_Decompose().  It checks a conic Bezier curve with the   */
00144   /*    current bounding box, and computes its extrema if necessary to     */
00145   /*    update it.                                                         */
00146   /*                                                                       */
00147   /* <Input>                                                               */
00148   /*    control :: A pointer to a control point.                           */
00149   /*                                                                       */
00150   /*    to      :: A pointer to the destination vector.                    */
00151   /*                                                                       */
00152   /* <InOut>                                                               */
00153   /*    user    :: The address of the current walk context.                */
00154   /*                                                                       */
00155   /* <Return>                                                              */
00156   /*    Always 0.  Needed for the interface only.                          */
00157   /*                                                                       */
00158   /* <Note>                                                                */
00159   /*    In the case of a non-monotonous arc, we compute directly the       */
00160   /*    extremum coordinates, as it is sufficiently fast.                  */
00161   /*                                                                       */
00162   static int
00163   BBox_Conic_To( FT_Vector*  control,
00164                  FT_Vector*  to,
00165                  TBBox_Rec*  user )
00166   {
00167     /* we don't need to check `to' since it is always an `on' point, thus */
00168     /* within the bbox                                                    */
00169 
00170     if ( CHECK_X( control, user->bbox ) )
00171       BBox_Conic_Check( user->last.x,
00172                         control->x,
00173                         to->x,
00174                         &user->bbox.xMin,
00175                         &user->bbox.xMax );
00176 
00177     if ( CHECK_Y( control, user->bbox ) )
00178       BBox_Conic_Check( user->last.y,
00179                         control->y,
00180                         to->y,
00181                         &user->bbox.yMin,
00182                         &user->bbox.yMax );
00183 
00184     user->last = *to;
00185 
00186     return 0;
00187   }
00188 
00189 
00190   /*************************************************************************/
00191   /*                                                                       */
00192   /* <Function>                                                            */
00193   /*    BBox_Cubic_Check                                                   */
00194   /*                                                                       */
00195   /* <Description>                                                         */
00196   /*    Finds the extrema of a 1-dimensional cubic Bezier curve and        */
00197   /*    updates a bounding range.  This version uses splitting because we  */
00198   /*    don't want to use square roots and extra accuracy.                 */
00199   /*                                                                       */
00200   /* <Input>                                                               */
00201   /*    p1  :: The start coordinate.                                       */
00202   /*                                                                       */
00203   /*    p2  :: The coordinate of the first control point.                  */
00204   /*                                                                       */
00205   /*    p3  :: The coordinate of the second control point.                 */
00206   /*                                                                       */
00207   /*    p4  :: The end coordinate.                                         */
00208   /*                                                                       */
00209   /* <InOut>                                                               */
00210   /*    min :: The address of the current minimum.                         */
00211   /*                                                                       */
00212   /*    max :: The address of the current maximum.                         */
00213   /*                                                                       */
00214 
00215 #if 0
00216 
00217   static void
00218   BBox_Cubic_Check( FT_Pos   p1,
00219                     FT_Pos   p2,
00220                     FT_Pos   p3,
00221                     FT_Pos   p4,
00222                     FT_Pos*  min,
00223                     FT_Pos*  max )
00224   {
00225     FT_Pos  stack[32*3 + 1], *arc;
00226 
00227 
00228     arc = stack;
00229 
00230     arc[0] = p1;
00231     arc[1] = p2;
00232     arc[2] = p3;
00233     arc[3] = p4;
00234 
00235     do
00236     {
00237       FT_Pos  y1 = arc[0];
00238       FT_Pos  y2 = arc[1];
00239       FT_Pos  y3 = arc[2];
00240       FT_Pos  y4 = arc[3];
00241 
00242 
00243       if ( y1 == y4 )
00244       {
00245         if ( y1 == y2 && y1 == y3 )                         /* flat */
00246           goto Test;
00247       }
00248       else if ( y1 < y4 )
00249       {
00250         if ( y2 >= y1 && y2 <= y4 && y3 >= y1 && y3 <= y4 ) /* ascending */
00251           goto Test;
00252       }
00253       else
00254       {
00255         if ( y2 >= y4 && y2 <= y1 && y3 >= y4 && y3 <= y1 ) /* descending */
00256         {
00257           y2 = y1;
00258           y1 = y4;
00259           y4 = y2;
00260           goto Test;
00261         }
00262       }
00263 
00264       /* unknown direction -- split the arc in two */
00265       arc[6] = y4;
00266       arc[1] = y1 = ( y1 + y2 ) / 2;
00267       arc[5] = y4 = ( y4 + y3 ) / 2;
00268       y2 = ( y2 + y3 ) / 2;
00269       arc[2] = y1 = ( y1 + y2 ) / 2;
00270       arc[4] = y4 = ( y4 + y2 ) / 2;
00271       arc[3] = ( y1 + y4 ) / 2;
00272 
00273       arc += 3;
00274       goto Suite;
00275 
00276    Test:
00277       if ( y1 < *min ) *min = y1;
00278       if ( y4 > *max ) *max = y4;
00279       arc -= 3;
00280 
00281     Suite:
00282       ;
00283     } while ( arc >= stack );
00284   }
00285 
00286 #else
00287 
00288   static void
00289   test_cubic_extrema( FT_Pos    y1,
00290                       FT_Pos    y2,
00291                       FT_Pos    y3,
00292                       FT_Pos    y4,
00293                       FT_Fixed  u,
00294                       FT_Pos*   min,
00295                       FT_Pos*   max )
00296   {
00297  /* FT_Pos    a = y4 - 3*y3 + 3*y2 - y1; */
00298     FT_Pos    b = y3 - 2*y2 + y1;
00299     FT_Pos    c = y2 - y1;
00300     FT_Pos    d = y1;
00301     FT_Pos    y;
00302     FT_Fixed  uu;
00303 
00304     FT_UNUSED ( y4 );
00305 
00306 
00307     /* The polynomial is                      */
00308     /*                                        */
00309     /*    P(x) = a*x^3 + 3b*x^2 + 3c*x + d  , */
00310     /*                                        */
00311     /*   dP/dx = 3a*x^2 + 6b*x + 3c         . */
00312     /*                                        */
00313     /* However, we also have                  */
00314     /*                                        */
00315     /*   dP/dx(u) = 0                       , */
00316     /*                                        */
00317     /* which implies by subtraction that      */
00318     /*                                        */
00319     /*   P(u) = b*u^2 + 2c*u + d            . */
00320 
00321     if ( u > 0 && u < 0x10000L )
00322     {
00323       uu = FT_MulFix( u, u );
00324       y  = d + FT_MulFix( c, 2*u ) + FT_MulFix( b, uu );
00325 
00326       if ( y < *min ) *min = y;
00327       if ( y > *max ) *max = y;
00328     }
00329   }
00330 
00331 
00332   static void
00333   BBox_Cubic_Check( FT_Pos   y1,
00334                     FT_Pos   y2,
00335                     FT_Pos   y3,
00336                     FT_Pos   y4,
00337                     FT_Pos*  min,
00338                     FT_Pos*  max )
00339   {
00340     /* always compare first and last points */
00341     if      ( y1 < *min )  *min = y1;
00342     else if ( y1 > *max )  *max = y1;
00343 
00344     if      ( y4 < *min )  *min = y4;
00345     else if ( y4 > *max )  *max = y4;
00346 
00347     /* now, try to see if there are split points here */
00348     if ( y1 <= y4 )
00349     {
00350       /* flat or ascending arc test */
00351       if ( y1 <= y2 && y2 <= y4 && y1 <= y3 && y3 <= y4 )
00352         return;
00353     }
00354     else /* y1 > y4 */
00355     {
00356       /* descending arc test */
00357       if ( y1 >= y2 && y2 >= y4 && y1 >= y3 && y3 >= y4 )
00358         return;
00359     }
00360 
00361     /* There are some split points.  Find them. */
00362     {
00363       FT_Pos    a = y4 - 3*y3 + 3*y2 - y1;
00364       FT_Pos    b = y3 - 2*y2 + y1;
00365       FT_Pos    c = y2 - y1;
00366       FT_Pos    d;
00367       FT_Fixed  t;
00368 
00369 
00370       /* We need to solve `ax^2+2bx+c' here, without floating points!      */
00371       /* The trick is to normalize to a different representation in order  */
00372       /* to use our 16.16 fixed point routines.                            */
00373       /*                                                                   */
00374       /* We compute FT_MulFix(b,b) and FT_MulFix(a,c) after normalization. */
00375       /* These values must fit into a single 16.16 value.                  */
00376       /*                                                                   */
00377       /* We normalize a, b, and c to `8.16' fixed float values to ensure   */
00378       /* that its product is held in a `16.16' value.                      */
00379 
00380       {
00381         FT_ULong  t1, t2;
00382         int       shift = 0;
00383 
00384 
00385         /* The following computation is based on the fact that for   */
00386         /* any value `y', if `n' is the position of the most         */
00387         /* significant bit of `abs(y)' (starting from 0 for the      */
00388         /* least significant bit), then `y' is in the range          */
00389         /*                                                           */
00390         /*   -2^n..2^n-1                                             */
00391         /*                                                           */
00392         /* We want to shift `a', `b', and `c' concurrently in order  */
00393         /* to ensure that they all fit in 8.16 values, which maps    */
00394         /* to the integer range `-2^23..2^23-1'.                     */
00395         /*                                                           */
00396         /* Necessarily, we need to shift `a', `b', and `c' so that   */
00397         /* the most significant bit of its absolute values is at     */
00398         /* _most_ at position 23.                                    */
00399         /*                                                           */
00400         /* We begin by computing `t1' as the bitwise `OR' of the     */
00401         /* absolute values of `a', `b', `c'.                         */
00402 
00403         t1  = (FT_ULong)( ( a >= 0 ) ? a : -a );
00404         t2  = (FT_ULong)( ( b >= 0 ) ? b : -b );
00405         t1 |= t2;
00406         t2  = (FT_ULong)( ( c >= 0 ) ? c : -c );
00407         t1 |= t2;
00408 
00409         /* Now we can be sure that the most significant bit of `t1'  */
00410         /* is the most significant bit of either `a', `b', or `c',   */
00411         /* depending on the greatest integer range of the particular */
00412         /* variable.                                                 */
00413         /*                                                           */
00414         /* Next, we compute the `shift', by shifting `t1' as many    */
00415         /* times as necessary to move its MSB to position 23.  This  */
00416         /* corresponds to a value of `t1' that is in the range       */
00417         /* 0x40_0000..0x7F_FFFF.                                     */
00418         /*                                                           */
00419         /* Finally, we shift `a', `b', and `c' by the same amount.   */
00420         /* This ensures that all values are now in the range         */
00421         /* -2^23..2^23, i.e., they are now expressed as 8.16         */
00422         /* fixed-float numbers.  This also means that we are using   */
00423         /* 24 bits of precision to compute the zeros, independently  */
00424         /* of the range of the original polynomial coefficients.     */
00425         /*                                                           */
00426         /* This algorithm should ensure reasonably accurate values   */
00427         /* for the zeros.  Note that they are only expressed with    */
00428         /* 16 bits when computing the extrema (the zeros need to     */
00429         /* be in 0..1 exclusive to be considered part of the arc).   */
00430 
00431         if ( t1 == 0 )  /* all coefficients are 0! */
00432           return;
00433 
00434         if ( t1 > 0x7FFFFFUL )
00435         {
00436           do
00437           {
00438             shift++;
00439             t1 >>= 1;
00440 
00441           } while ( t1 > 0x7FFFFFUL );
00442 
00443           /* this loses some bits of precision, but we use 24 of them */
00444           /* for the computation anyway                               */
00445           a >>= shift;
00446           b >>= shift;
00447           c >>= shift;
00448         }
00449         else if ( t1 < 0x400000UL )
00450         {
00451           do
00452           {
00453             shift++;
00454             t1 <<= 1;
00455 
00456           } while ( t1 < 0x400000UL );
00457 
00458           a <<= shift;
00459           b <<= shift;
00460           c <<= shift;
00461         }
00462       }
00463 
00464       /* handle a == 0 */
00465       if ( a == 0 )
00466       {
00467         if ( b != 0 )
00468         {
00469           t = - FT_DivFix( c, b ) / 2;
00470           test_cubic_extrema( y1, y2, y3, y4, t, min, max );
00471         }
00472       }
00473       else
00474       {
00475         /* solve the equation now */
00476         d = FT_MulFix( b, b ) - FT_MulFix( a, c );
00477         if ( d < 0 )
00478           return;
00479 
00480         if ( d == 0 )
00481         {
00482           /* there is a single split point at -b/a */
00483           t = - FT_DivFix( b, a );
00484           test_cubic_extrema( y1, y2, y3, y4, t, min, max );
00485         }
00486         else
00487         {
00488           /* there are two solutions; we need to filter them */
00489           d = FT_SqrtFixed( (FT_Int32)d );
00490           t = - FT_DivFix( b - d, a );
00491           test_cubic_extrema( y1, y2, y3, y4, t, min, max );
00492 
00493           t = - FT_DivFix( b + d, a );
00494           test_cubic_extrema( y1, y2, y3, y4, t, min, max );
00495         }
00496       }
00497     }
00498   }
00499 
00500 #endif
00501 
00502 
00503   /*************************************************************************/
00504   /*                                                                       */
00505   /* <Function>                                                            */
00506   /*    BBox_Cubic_To                                                      */
00507   /*                                                                       */
00508   /* <Description>                                                         */
00509   /*    This function is used as a `cubic_to' emitter during               */
00510   /*    FT_Outline_Decompose().  It checks a cubic Bezier curve with the   */
00511   /*    current bounding box, and computes its extrema if necessary to     */
00512   /*    update it.                                                         */
00513   /*                                                                       */
00514   /* <Input>                                                               */
00515   /*    control1 :: A pointer to the first control point.                  */
00516   /*                                                                       */
00517   /*    control2 :: A pointer to the second control point.                 */
00518   /*                                                                       */
00519   /*    to       :: A pointer to the destination vector.                   */
00520   /*                                                                       */
00521   /* <InOut>                                                               */
00522   /*    user     :: The address of the current walk context.               */
00523   /*                                                                       */
00524   /* <Return>                                                              */
00525   /*    Always 0.  Needed for the interface only.                          */
00526   /*                                                                       */
00527   /* <Note>                                                                */
00528   /*    In the case of a non-monotonous arc, we don't compute directly     */
00529   /*    extremum coordinates, we subdivide instead.                        */
00530   /*                                                                       */
00531   static int
00532   BBox_Cubic_To( FT_Vector*  control1,
00533                  FT_Vector*  control2,
00534                  FT_Vector*  to,
00535                  TBBox_Rec*  user )
00536   {
00537     /* we don't need to check `to' since it is always an `on' point, thus */
00538     /* within the bbox                                                    */
00539 
00540     if ( CHECK_X( control1, user->bbox ) ||
00541          CHECK_X( control2, user->bbox ) )
00542       BBox_Cubic_Check( user->last.x,
00543                         control1->x,
00544                         control2->x,
00545                         to->x,
00546                         &user->bbox.xMin,
00547                         &user->bbox.xMax );
00548 
00549     if ( CHECK_Y( control1, user->bbox ) ||
00550          CHECK_Y( control2, user->bbox ) )
00551       BBox_Cubic_Check( user->last.y,
00552                         control1->y,
00553                         control2->y,
00554                         to->y,
00555                         &user->bbox.yMin,
00556                         &user->bbox.yMax );
00557 
00558     user->last = *to;
00559 
00560     return 0;
00561   }
00562 
00563 FT_DEFINE_OUTLINE_FUNCS(bbox_interface,
00564     (FT_Outline_MoveTo_Func) BBox_Move_To,
00565     (FT_Outline_LineTo_Func) BBox_Move_To,
00566     (FT_Outline_ConicTo_Func)BBox_Conic_To,
00567     (FT_Outline_CubicTo_Func)BBox_Cubic_To,
00568     0, 0
00569   )
00570 
00571   /* documentation is in ftbbox.h */
00572 
00573   FT_EXPORT_DEF( FT_Error )
00574   FT_Outline_Get_BBox( FT_Outline*  outline,
00575                        FT_BBox     *abbox )
00576   {
00577     FT_BBox     cbox;
00578     FT_BBox     bbox;
00579     FT_Vector*  vec;
00580     FT_UShort   n;
00581 
00582 
00583     if ( !abbox )
00584       return FT_Err_Invalid_Argument;
00585 
00586     if ( !outline )
00587       return FT_Err_Invalid_Outline;
00588 
00589     /* if outline is empty, return (0,0,0,0) */
00590     if ( outline->n_points == 0 || outline->n_contours <= 0 )
00591     {
00592       abbox->xMin = abbox->xMax = 0;
00593       abbox->yMin = abbox->yMax = 0;
00594       return 0;
00595     }
00596 
00597     /* We compute the control box as well as the bounding box of  */
00598     /* all `on' points in the outline.  Then, if the two boxes    */
00599     /* coincide, we exit immediately.                             */
00600 
00601     vec = outline->points;
00602     bbox.xMin = bbox.xMax = cbox.xMin = cbox.xMax = vec->x;
00603     bbox.yMin = bbox.yMax = cbox.yMin = cbox.yMax = vec->y;
00604     vec++;
00605 
00606     for ( n = 1; n < outline->n_points; n++ )
00607     {
00608       FT_Pos  x = vec->x;
00609       FT_Pos  y = vec->y;
00610 
00611 
00612       /* update control box */
00613       if ( x < cbox.xMin ) cbox.xMin = x;
00614       if ( x > cbox.xMax ) cbox.xMax = x;
00615 
00616       if ( y < cbox.yMin ) cbox.yMin = y;
00617       if ( y > cbox.yMax ) cbox.yMax = y;
00618 
00619       if ( FT_CURVE_TAG( outline->tags[n] ) == FT_CURVE_TAG_ON )
00620       {
00621         /* update bbox for `on' points only */
00622         if ( x < bbox.xMin ) bbox.xMin = x;
00623         if ( x > bbox.xMax ) bbox.xMax = x;
00624 
00625         if ( y < bbox.yMin ) bbox.yMin = y;
00626         if ( y > bbox.yMax ) bbox.yMax = y;
00627       }
00628 
00629       vec++;
00630     }
00631 
00632     /* test two boxes for equality */
00633     if ( cbox.xMin < bbox.xMin || cbox.xMax > bbox.xMax ||
00634          cbox.yMin < bbox.yMin || cbox.yMax > bbox.yMax )
00635     {
00636       /* the two boxes are different, now walk over the outline to */
00637       /* get the Bezier arc extrema.                               */
00638 
00639       FT_Error   error;
00640       TBBox_Rec  user;
00641 
00642 #ifdef FT_CONFIG_OPTION_PIC
00643       FT_Outline_Funcs bbox_interface;
00644       Init_Class_bbox_interface(&bbox_interface);
00645 #endif
00646 
00647       user.bbox = bbox;
00648 
00649       error = FT_Outline_Decompose( outline, &bbox_interface, &user );
00650       if ( error )
00651         return error;
00652 
00653       *abbox = user.bbox;
00654     }
00655     else
00656       *abbox = bbox;
00657 
00658     return FT_Err_Ok;
00659   }
00660 
00661 
00662 /* END */

Generated on Sun May 27 2012 04:33:34 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.