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

pshrec.c
Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  pshrec.c                                                               */
00004 /*                                                                         */
00005 /*    FreeType PostScript hints recorder (body).                           */
00006 /*                                                                         */
00007 /*  Copyright 2001, 2002, 2003, 2004, 2007, 2009 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 #include <ft2build.h>
00020 #include FT_FREETYPE_H
00021 #include FT_INTERNAL_OBJECTS_H
00022 #include FT_INTERNAL_DEBUG_H
00023 #include FT_INTERNAL_CALC_H
00024 
00025 #include "pshrec.h"
00026 #include "pshalgo.h"
00027 
00028 #include "pshnterr.h"
00029 
00030 #undef  FT_COMPONENT
00031 #define FT_COMPONENT  trace_pshrec
00032 
00033 #ifdef DEBUG_HINTER
00034   PS_Hints  ps_debug_hints         = 0;
00035   int       ps_debug_no_horz_hints = 0;
00036   int       ps_debug_no_vert_hints = 0;
00037 #endif
00038 
00039 
00040   /*************************************************************************/
00041   /*************************************************************************/
00042   /*****                                                               *****/
00043   /*****                      PS_HINT MANAGEMENT                       *****/
00044   /*****                                                               *****/
00045   /*************************************************************************/
00046   /*************************************************************************/
00047 
00048   /* destroy hints table */
00049   static void
00050   ps_hint_table_done( PS_Hint_Table  table,
00051                       FT_Memory      memory )
00052   {
00053     FT_FREE( table->hints );
00054     table->num_hints = 0;
00055     table->max_hints = 0;
00056   }
00057 
00058 
00059   /* ensure that a table can contain "count" elements */
00060   static FT_Error
00061   ps_hint_table_ensure( PS_Hint_Table  table,
00062                         FT_UInt        count,
00063                         FT_Memory      memory )
00064   {
00065     FT_UInt   old_max = table->max_hints;
00066     FT_UInt   new_max = count;
00067     FT_Error  error   = PSH_Err_Ok;
00068 
00069 
00070     if ( new_max > old_max )
00071     {
00072       /* try to grow the table */
00073       new_max = FT_PAD_CEIL( new_max, 8 );
00074       if ( !FT_RENEW_ARRAY( table->hints, old_max, new_max ) )
00075         table->max_hints = new_max;
00076     }
00077     return error;
00078   }
00079 
00080 
00081   static FT_Error
00082   ps_hint_table_alloc( PS_Hint_Table  table,
00083                        FT_Memory      memory,
00084                        PS_Hint       *ahint )
00085   {
00086     FT_Error  error = PSH_Err_Ok;
00087     FT_UInt   count;
00088     PS_Hint   hint = 0;
00089 
00090 
00091     count = table->num_hints;
00092     count++;
00093 
00094     if ( count >= table->max_hints )
00095     {
00096       error = ps_hint_table_ensure( table, count, memory );
00097       if ( error )
00098         goto Exit;
00099     }
00100 
00101     hint        = table->hints + count - 1;
00102     hint->pos   = 0;
00103     hint->len   = 0;
00104     hint->flags = 0;
00105 
00106     table->num_hints = count;
00107 
00108   Exit:
00109     *ahint = hint;
00110     return error;
00111   }
00112 
00113 
00114   /*************************************************************************/
00115   /*************************************************************************/
00116   /*****                                                               *****/
00117   /*****                      PS_MASK MANAGEMENT                       *****/
00118   /*****                                                               *****/
00119   /*************************************************************************/
00120   /*************************************************************************/
00121 
00122   /* destroy mask */
00123   static void
00124   ps_mask_done( PS_Mask    mask,
00125                 FT_Memory  memory )
00126   {
00127     FT_FREE( mask->bytes );
00128     mask->num_bits  = 0;
00129     mask->max_bits  = 0;
00130     mask->end_point = 0;
00131   }
00132 
00133 
00134   /* ensure that a mask can contain "count" bits */
00135   static FT_Error
00136   ps_mask_ensure( PS_Mask    mask,
00137                   FT_UInt    count,
00138                   FT_Memory  memory )
00139   {
00140     FT_UInt   old_max = ( mask->max_bits + 7 ) >> 3;
00141     FT_UInt   new_max = ( count          + 7 ) >> 3;
00142     FT_Error  error   = PSH_Err_Ok;
00143 
00144 
00145     if ( new_max > old_max )
00146     {
00147       new_max = FT_PAD_CEIL( new_max, 8 );
00148       if ( !FT_RENEW_ARRAY( mask->bytes, old_max, new_max ) )
00149         mask->max_bits = new_max * 8;
00150     }
00151     return error;
00152   }
00153 
00154 
00155   /* test a bit value in a given mask */
00156   static FT_Int
00157   ps_mask_test_bit( PS_Mask  mask,
00158                     FT_Int   idx )
00159   {
00160     if ( (FT_UInt)idx >= mask->num_bits )
00161       return 0;
00162 
00163     return mask->bytes[idx >> 3] & ( 0x80 >> ( idx & 7 ) );
00164   }
00165 
00166 
00167   /* clear a given bit */
00168   static void
00169   ps_mask_clear_bit( PS_Mask  mask,
00170                      FT_Int   idx )
00171   {
00172     FT_Byte*  p;
00173 
00174 
00175     if ( (FT_UInt)idx >= mask->num_bits )
00176       return;
00177 
00178     p    = mask->bytes + ( idx >> 3 );
00179     p[0] = (FT_Byte)( p[0] & ~( 0x80 >> ( idx & 7 ) ) );
00180   }
00181 
00182 
00183   /* set a given bit, possibly grow the mask */
00184   static FT_Error
00185   ps_mask_set_bit( PS_Mask    mask,
00186                    FT_Int     idx,
00187                    FT_Memory  memory )
00188   {
00189     FT_Error  error = PSH_Err_Ok;
00190     FT_Byte*  p;
00191 
00192 
00193     if ( idx < 0 )
00194       goto Exit;
00195 
00196     if ( (FT_UInt)idx >= mask->num_bits )
00197     {
00198       error = ps_mask_ensure( mask, idx + 1, memory );
00199       if ( error )
00200         goto Exit;
00201 
00202       mask->num_bits = idx + 1;
00203     }
00204 
00205     p    = mask->bytes + ( idx >> 3 );
00206     p[0] = (FT_Byte)( p[0] | ( 0x80 >> ( idx & 7 ) ) );
00207 
00208   Exit:
00209     return error;
00210   }
00211 
00212 
00213   /* destroy mask table */
00214   static void
00215   ps_mask_table_done( PS_Mask_Table  table,
00216                       FT_Memory      memory )
00217   {
00218     FT_UInt  count = table->max_masks;
00219     PS_Mask  mask  = table->masks;
00220 
00221 
00222     for ( ; count > 0; count--, mask++ )
00223       ps_mask_done( mask, memory );
00224 
00225     FT_FREE( table->masks );
00226     table->num_masks = 0;
00227     table->max_masks = 0;
00228   }
00229 
00230 
00231   /* ensure that a mask table can contain "count" masks */
00232   static FT_Error
00233   ps_mask_table_ensure( PS_Mask_Table  table,
00234                         FT_UInt        count,
00235                         FT_Memory      memory )
00236   {
00237     FT_UInt   old_max = table->max_masks;
00238     FT_UInt   new_max = count;
00239     FT_Error  error   = PSH_Err_Ok;
00240 
00241 
00242     if ( new_max > old_max )
00243     {
00244       new_max = FT_PAD_CEIL( new_max, 8 );
00245       if ( !FT_RENEW_ARRAY( table->masks, old_max, new_max ) )
00246         table->max_masks = new_max;
00247     }
00248     return error;
00249   }
00250 
00251 
00252   /* allocate a new mask in a table */
00253   static FT_Error
00254   ps_mask_table_alloc( PS_Mask_Table  table,
00255                        FT_Memory      memory,
00256                        PS_Mask       *amask )
00257   {
00258     FT_UInt   count;
00259     FT_Error  error = PSH_Err_Ok;
00260     PS_Mask   mask  = 0;
00261 
00262 
00263     count = table->num_masks;
00264     count++;
00265 
00266     if ( count > table->max_masks )
00267     {
00268       error = ps_mask_table_ensure( table, count, memory );
00269       if ( error )
00270         goto Exit;
00271     }
00272 
00273     mask             = table->masks + count - 1;
00274     mask->num_bits   = 0;
00275     mask->end_point  = 0;
00276     table->num_masks = count;
00277 
00278   Exit:
00279     *amask = mask;
00280     return error;
00281   }
00282 
00283 
00284   /* return last hint mask in a table, create one if the table is empty */
00285   static FT_Error
00286   ps_mask_table_last( PS_Mask_Table  table,
00287                       FT_Memory      memory,
00288                       PS_Mask       *amask )
00289   {
00290     FT_Error  error = PSH_Err_Ok;
00291     FT_UInt   count;
00292     PS_Mask   mask;
00293 
00294 
00295     count = table->num_masks;
00296     if ( count == 0 )
00297     {
00298       error = ps_mask_table_alloc( table, memory, &mask );
00299       if ( error )
00300         goto Exit;
00301     }
00302     else
00303       mask = table->masks + count - 1;
00304 
00305   Exit:
00306     *amask = mask;
00307     return error;
00308   }
00309 
00310 
00311   /* set a new mask to a given bit range */
00312   static FT_Error
00313   ps_mask_table_set_bits( PS_Mask_Table   table,
00314                           const FT_Byte*  source,
00315                           FT_UInt         bit_pos,
00316                           FT_UInt         bit_count,
00317                           FT_Memory       memory )
00318   {
00319     FT_Error  error = PSH_Err_Ok;
00320     PS_Mask   mask;
00321 
00322 
00323     error = ps_mask_table_last( table, memory, &mask );
00324     if ( error )
00325       goto Exit;
00326 
00327     error = ps_mask_ensure( mask, bit_count, memory );
00328     if ( error )
00329       goto Exit;
00330 
00331     mask->num_bits = bit_count;
00332 
00333     /* now, copy bits */
00334     {
00335       FT_Byte*  read  = (FT_Byte*)source + ( bit_pos >> 3 );
00336       FT_Int    rmask = 0x80 >> ( bit_pos & 7 );
00337       FT_Byte*  write = mask->bytes;
00338       FT_Int    wmask = 0x80;
00339       FT_Int    val;
00340 
00341 
00342       for ( ; bit_count > 0; bit_count-- )
00343       {
00344         val = write[0] & ~wmask;
00345 
00346         if ( read[0] & rmask )
00347           val |= wmask;
00348 
00349         write[0] = (FT_Byte)val;
00350 
00351         rmask >>= 1;
00352         if ( rmask == 0 )
00353         {
00354           read++;
00355           rmask = 0x80;
00356         }
00357 
00358         wmask >>= 1;
00359         if ( wmask == 0 )
00360         {
00361           write++;
00362           wmask = 0x80;
00363         }
00364       }
00365     }
00366 
00367   Exit:
00368     return error;
00369   }
00370 
00371 
00372   /* test whether two masks in a table intersect */
00373   static FT_Int
00374   ps_mask_table_test_intersect( PS_Mask_Table  table,
00375                                 FT_Int         index1,
00376                                 FT_Int         index2 )
00377   {
00378     PS_Mask   mask1  = table->masks + index1;
00379     PS_Mask   mask2  = table->masks + index2;
00380     FT_Byte*  p1     = mask1->bytes;
00381     FT_Byte*  p2     = mask2->bytes;
00382     FT_UInt   count1 = mask1->num_bits;
00383     FT_UInt   count2 = mask2->num_bits;
00384     FT_UInt   count;
00385 
00386 
00387     count = ( count1 <= count2 ) ? count1 : count2;
00388     for ( ; count >= 8; count -= 8 )
00389     {
00390       if ( p1[0] & p2[0] )
00391         return 1;
00392 
00393       p1++;
00394       p2++;
00395     }
00396 
00397     if ( count == 0 )
00398       return 0;
00399 
00400     return ( p1[0] & p2[0] ) & ~( 0xFF >> count );
00401   }
00402 
00403 
00404   /* merge two masks, used by ps_mask_table_merge_all */
00405   static FT_Error
00406   ps_mask_table_merge( PS_Mask_Table  table,
00407                        FT_Int         index1,
00408                        FT_Int         index2,
00409                        FT_Memory      memory )
00410   {
00411     FT_UInt   temp;
00412     FT_Error  error = PSH_Err_Ok;
00413 
00414 
00415     /* swap index1 and index2 so that index1 < index2 */
00416     if ( index1 > index2 )
00417     {
00418       temp   = index1;
00419       index1 = index2;
00420       index2 = temp;
00421     }
00422 
00423     if ( index1 < index2 && index1 >= 0 && index2 < (FT_Int)table->num_masks )
00424     {
00425       /* we need to merge the bitsets of index1 and index2 with a */
00426       /* simple union                                             */
00427       PS_Mask  mask1  = table->masks + index1;
00428       PS_Mask  mask2  = table->masks + index2;
00429       FT_UInt  count1 = mask1->num_bits;
00430       FT_UInt  count2 = mask2->num_bits;
00431       FT_Int   delta;
00432 
00433 
00434       if ( count2 > 0 )
00435       {
00436         FT_UInt   pos;
00437         FT_Byte*  read;
00438         FT_Byte*  write;
00439 
00440 
00441         /* if "count2" is greater than "count1", we need to grow the */
00442         /* first bitset, and clear the highest bits                  */
00443         if ( count2 > count1 )
00444         {
00445           error = ps_mask_ensure( mask1, count2, memory );
00446           if ( error )
00447             goto Exit;
00448 
00449           for ( pos = count1; pos < count2; pos++ )
00450             ps_mask_clear_bit( mask1, pos );
00451         }
00452 
00453         /* merge (unite) the bitsets */
00454         read  = mask2->bytes;
00455         write = mask1->bytes;
00456         pos   = (FT_UInt)( ( count2 + 7 ) >> 3 );
00457 
00458         for ( ; pos > 0; pos-- )
00459         {
00460           write[0] = (FT_Byte)( write[0] | read[0] );
00461           write++;
00462           read++;
00463         }
00464       }
00465 
00466       /* Now, remove "mask2" from the list.  We need to keep the masks */
00467       /* sorted in order of importance, so move table elements.        */
00468       mask2->num_bits  = 0;
00469       mask2->end_point = 0;
00470 
00471       delta = table->num_masks - 1 - index2; /* number of masks to move */
00472       if ( delta > 0 )
00473       {
00474         /* move to end of table for reuse */
00475         PS_MaskRec  dummy = *mask2;
00476 
00477 
00478         ft_memmove( mask2, mask2 + 1, delta * sizeof ( PS_MaskRec ) );
00479 
00480         mask2[delta] = dummy;
00481       }
00482 
00483       table->num_masks--;
00484     }
00485     else
00486       FT_TRACE0(( "ps_mask_table_merge: ignoring invalid indices (%d,%d)\n",
00487                   index1, index2 ));
00488 
00489   Exit:
00490     return error;
00491   }
00492 
00493 
00494   /* Try to merge all masks in a given table.  This is used to merge */
00495   /* all counter masks into independent counter "paths".             */
00496   /*                                                                 */
00497   static FT_Error
00498   ps_mask_table_merge_all( PS_Mask_Table  table,
00499                            FT_Memory      memory )
00500   {
00501     FT_Int    index1, index2;
00502     FT_Error  error = PSH_Err_Ok;
00503 
00504 
00505     for ( index1 = table->num_masks - 1; index1 > 0; index1-- )
00506     {
00507       for ( index2 = index1 - 1; index2 >= 0; index2-- )
00508       {
00509         if ( ps_mask_table_test_intersect( table, index1, index2 ) )
00510         {
00511           error = ps_mask_table_merge( table, index2, index1, memory );
00512           if ( error )
00513             goto Exit;
00514 
00515           break;
00516         }
00517       }
00518     }
00519 
00520   Exit:
00521     return error;
00522   }
00523 
00524 
00525   /*************************************************************************/
00526   /*************************************************************************/
00527   /*****                                                               *****/
00528   /*****                    PS_DIMENSION MANAGEMENT                    *****/
00529   /*****                                                               *****/
00530   /*************************************************************************/
00531   /*************************************************************************/
00532 
00533 
00534   /* finalize a given dimension */
00535   static void
00536   ps_dimension_done( PS_Dimension  dimension,
00537                      FT_Memory     memory )
00538   {
00539     ps_mask_table_done( &dimension->counters, memory );
00540     ps_mask_table_done( &dimension->masks,    memory );
00541     ps_hint_table_done( &dimension->hints,    memory );
00542   }
00543 
00544 
00545   /* initialize a given dimension */
00546   static void
00547   ps_dimension_init( PS_Dimension  dimension )
00548   {
00549     dimension->hints.num_hints    = 0;
00550     dimension->masks.num_masks    = 0;
00551     dimension->counters.num_masks = 0;
00552   }
00553 
00554 
00555 #if 0
00556 
00557   /* set a bit at a given index in the current hint mask */
00558   static FT_Error
00559   ps_dimension_set_mask_bit( PS_Dimension  dim,
00560                              FT_UInt       idx,
00561                              FT_Memory     memory )
00562   {
00563     PS_Mask   mask;
00564     FT_Error  error = PSH_Err_Ok;
00565 
00566 
00567     /* get last hint mask */
00568     error = ps_mask_table_last( &dim->masks, memory, &mask );
00569     if ( error )
00570       goto Exit;
00571 
00572     error = ps_mask_set_bit( mask, idx, memory );
00573 
00574   Exit:
00575     return error;
00576   }
00577 
00578 #endif
00579 
00580   /* set the end point in a mask, called from "End" & "Reset" methods */
00581   static void
00582   ps_dimension_end_mask( PS_Dimension  dim,
00583                          FT_UInt       end_point )
00584   {
00585     FT_UInt  count = dim->masks.num_masks;
00586     PS_Mask  mask;
00587 
00588 
00589     if ( count > 0 )
00590     {
00591       mask            = dim->masks.masks + count - 1;
00592       mask->end_point = end_point;
00593     }
00594   }
00595 
00596 
00597   /* set the end point in the current mask, then create a new empty one */
00598   /* (called by "Reset" method)                                         */
00599   static FT_Error
00600   ps_dimension_reset_mask( PS_Dimension  dim,
00601                            FT_UInt       end_point,
00602                            FT_Memory     memory )
00603   {
00604     PS_Mask  mask;
00605 
00606 
00607     /* end current mask */
00608     ps_dimension_end_mask( dim, end_point );
00609 
00610     /* allocate new one */
00611     return ps_mask_table_alloc( &dim->masks, memory, &mask );
00612   }
00613 
00614 
00615   /* set a new mask, called from the "T2Stem" method */
00616   static FT_Error
00617   ps_dimension_set_mask_bits( PS_Dimension    dim,
00618                               const FT_Byte*  source,
00619                               FT_UInt         source_pos,
00620                               FT_UInt         source_bits,
00621                               FT_UInt         end_point,
00622                               FT_Memory       memory )
00623   {
00624     FT_Error  error = PSH_Err_Ok;
00625 
00626 
00627     /* reset current mask, if any */
00628     error = ps_dimension_reset_mask( dim, end_point, memory );
00629     if ( error )
00630       goto Exit;
00631 
00632     /* set bits in new mask */
00633     error = ps_mask_table_set_bits( &dim->masks, source,
00634                                     source_pos, source_bits, memory );
00635 
00636   Exit:
00637     return error;
00638   }
00639 
00640 
00641   /* add a new single stem (called from "T1Stem" method) */
00642   static FT_Error
00643   ps_dimension_add_t1stem( PS_Dimension  dim,
00644                            FT_Int        pos,
00645                            FT_Int        len,
00646                            FT_Memory     memory,
00647                            FT_Int       *aindex )
00648   {
00649     FT_Error  error = PSH_Err_Ok;
00650     FT_UInt   flags = 0;
00651 
00652 
00653     /* detect ghost stem */
00654     if ( len < 0 )
00655     {
00656       flags |= PS_HINT_FLAG_GHOST;
00657       if ( len == -21 )
00658       {
00659         flags |= PS_HINT_FLAG_BOTTOM;
00660         pos   += len;
00661       }
00662       len = 0;
00663     }
00664 
00665     if ( aindex )
00666       *aindex = -1;
00667 
00668     /* now, lookup stem in the current hints table */
00669     {
00670       PS_Mask  mask;
00671       FT_UInt  idx;
00672       FT_UInt  max   = dim->hints.num_hints;
00673       PS_Hint  hint  = dim->hints.hints;
00674 
00675 
00676       for ( idx = 0; idx < max; idx++, hint++ )
00677       {
00678         if ( hint->pos == pos && hint->len == len )
00679           break;
00680       }
00681 
00682       /* we need to create a new hint in the table */
00683       if ( idx >= max )
00684       {
00685         error = ps_hint_table_alloc( &dim->hints, memory, &hint );
00686         if ( error )
00687           goto Exit;
00688 
00689         hint->pos   = pos;
00690         hint->len   = len;
00691         hint->flags = flags;
00692       }
00693 
00694       /* now, store the hint in the current mask */
00695       error = ps_mask_table_last( &dim->masks, memory, &mask );
00696       if ( error )
00697         goto Exit;
00698 
00699       error = ps_mask_set_bit( mask, idx, memory );
00700       if ( error )
00701         goto Exit;
00702 
00703       if ( aindex )
00704         *aindex = (FT_Int)idx;
00705     }
00706 
00707   Exit:
00708     return error;
00709   }
00710 
00711 
00712   /* add a "hstem3/vstem3" counter to our dimension table */
00713   static FT_Error
00714   ps_dimension_add_counter( PS_Dimension  dim,
00715                             FT_Int        hint1,
00716                             FT_Int        hint2,
00717                             FT_Int        hint3,
00718                             FT_Memory     memory )
00719   {
00720     FT_Error  error   = PSH_Err_Ok;
00721     FT_UInt   count   = dim->counters.num_masks;
00722     PS_Mask   counter = dim->counters.masks;
00723 
00724 
00725     /* try to find an existing counter mask that already uses */
00726     /* one of these stems here                                */
00727     for ( ; count > 0; count--, counter++ )
00728     {
00729       if ( ps_mask_test_bit( counter, hint1 ) ||
00730            ps_mask_test_bit( counter, hint2 ) ||
00731            ps_mask_test_bit( counter, hint3 ) )
00732         break;
00733     }
00734 
00735     /* create a new counter when needed */
00736     if ( count == 0 )
00737     {
00738       error = ps_mask_table_alloc( &dim->counters, memory, &counter );
00739       if ( error )
00740         goto Exit;
00741     }
00742 
00743     /* now, set the bits for our hints in the counter mask */
00744     error = ps_mask_set_bit( counter, hint1, memory );
00745     if ( error )
00746       goto Exit;
00747 
00748     error = ps_mask_set_bit( counter, hint2, memory );
00749     if ( error )
00750       goto Exit;
00751 
00752     error = ps_mask_set_bit( counter, hint3, memory );
00753     if ( error )
00754       goto Exit;
00755 
00756   Exit:
00757     return error;
00758   }
00759 
00760 
00761   /* end of recording session for a given dimension */
00762   static FT_Error
00763   ps_dimension_end( PS_Dimension  dim,
00764                     FT_UInt       end_point,
00765                     FT_Memory     memory )
00766   {
00767     /* end hint mask table */
00768     ps_dimension_end_mask( dim, end_point );
00769 
00770     /* merge all counter masks into independent "paths" */
00771     return ps_mask_table_merge_all( &dim->counters, memory );
00772   }
00773 
00774 
00775   /*************************************************************************/
00776   /*************************************************************************/
00777   /*****                                                               *****/
00778   /*****                    PS_RECORDER MANAGEMENT                     *****/
00779   /*****                                                               *****/
00780   /*************************************************************************/
00781   /*************************************************************************/
00782 
00783 
00784   /* destroy hints */
00785   FT_LOCAL( void )
00786   ps_hints_done( PS_Hints  hints )
00787   {
00788     FT_Memory  memory = hints->memory;
00789 
00790 
00791     ps_dimension_done( &hints->dimension[0], memory );
00792     ps_dimension_done( &hints->dimension[1], memory );
00793 
00794     hints->error  = PSH_Err_Ok;
00795     hints->memory = 0;
00796   }
00797 
00798 
00799   FT_LOCAL( FT_Error )
00800   ps_hints_init( PS_Hints   hints,
00801                  FT_Memory  memory )
00802   {
00803     FT_MEM_ZERO( hints, sizeof ( *hints ) );
00804     hints->memory = memory;
00805     return PSH_Err_Ok;
00806   }
00807 
00808 
00809   /* initialize a hints for a new session */
00810   static void
00811   ps_hints_open( PS_Hints      hints,
00812                  PS_Hint_Type  hint_type )
00813   {
00814     switch ( hint_type )
00815     {
00816     case PS_HINT_TYPE_1:
00817     case PS_HINT_TYPE_2:
00818       hints->error     = PSH_Err_Ok;
00819       hints->hint_type = hint_type;
00820 
00821       ps_dimension_init( &hints->dimension[0] );
00822       ps_dimension_init( &hints->dimension[1] );
00823       break;
00824 
00825     default:
00826       hints->error     = PSH_Err_Invalid_Argument;
00827       hints->hint_type = hint_type;
00828 
00829       FT_TRACE0(( "ps_hints_open: invalid charstring type\n" ));
00830       break;
00831     }
00832   }
00833 
00834 
00835   /* add one or more stems to the current hints table */
00836   static void
00837   ps_hints_stem( PS_Hints  hints,
00838                  FT_Int    dimension,
00839                  FT_UInt   count,
00840                  FT_Long*  stems )
00841   {
00842     if ( !hints->error )
00843     {
00844       /* limit "dimension" to 0..1 */
00845       if ( dimension < 0 || dimension > 1 )
00846       {
00847         FT_TRACE0(( "ps_hints_stem: invalid dimension (%d) used\n",
00848                     dimension ));
00849         dimension = ( dimension != 0 );
00850       }
00851 
00852       /* record the stems in the current hints/masks table */
00853       switch ( hints->hint_type )
00854       {
00855       case PS_HINT_TYPE_1:  /* Type 1 "hstem" or "vstem" operator */
00856       case PS_HINT_TYPE_2:  /* Type 2 "hstem" or "vstem" operator */
00857         {
00858           PS_Dimension  dim = &hints->dimension[dimension];
00859 
00860 
00861           for ( ; count > 0; count--, stems += 2 )
00862           {
00863             FT_Error   error;
00864             FT_Memory  memory = hints->memory;
00865 
00866 
00867             error = ps_dimension_add_t1stem(
00868                       dim, (FT_Int)stems[0], (FT_Int)stems[1],
00869                       memory, NULL );
00870             if ( error )
00871             {
00872               FT_ERROR(( "ps_hints_stem: could not add stem"
00873                          " (%d,%d) to hints table\n", stems[0], stems[1] ));
00874 
00875               hints->error = error;
00876               return;
00877             }
00878           }
00879           break;
00880         }
00881 
00882       default:
00883         FT_TRACE0(( "ps_hints_stem: called with invalid hint type (%d)\n",
00884                     hints->hint_type ));
00885         break;
00886       }
00887     }
00888   }
00889 
00890 
00891   /* add one Type1 counter stem to the current hints table */
00892   static void
00893   ps_hints_t1stem3( PS_Hints   hints,
00894                     FT_Int     dimension,
00895                     FT_Fixed*  stems )
00896   {
00897     FT_Error  error = PSH_Err_Ok;
00898 
00899 
00900     if ( !hints->error )
00901     {
00902       PS_Dimension  dim;
00903       FT_Memory     memory = hints->memory;
00904       FT_Int        count;
00905       FT_Int        idx[3];
00906 
00907 
00908       /* limit "dimension" to 0..1 */
00909       if ( dimension < 0 || dimension > 1 )
00910       {
00911         FT_TRACE0(( "ps_hints_t1stem3: invalid dimension (%d) used\n",
00912                     dimension ));
00913         dimension = ( dimension != 0 );
00914       }
00915 
00916       dim = &hints->dimension[dimension];
00917 
00918       /* there must be 6 elements in the 'stem' array */
00919       if ( hints->hint_type == PS_HINT_TYPE_1 )
00920       {
00921         /* add the three stems to our hints/masks table */
00922         for ( count = 0; count < 3; count++, stems += 2 )
00923         {
00924           error = ps_dimension_add_t1stem( dim,
00925                                            (FT_Int)FIXED_TO_INT( stems[0] ),
00926                                            (FT_Int)FIXED_TO_INT( stems[1] ),
00927                                            memory, &idx[count] );
00928           if ( error )
00929             goto Fail;
00930         }
00931 
00932         /* now, add the hints to the counters table */
00933         error = ps_dimension_add_counter( dim, idx[0], idx[1], idx[2],
00934                                           memory );
00935         if ( error )
00936           goto Fail;
00937       }
00938       else
00939       {
00940         FT_ERROR(( "ps_hints_t1stem3: called with invalid hint type\n" ));
00941         error = PSH_Err_Invalid_Argument;
00942         goto Fail;
00943       }
00944     }
00945 
00946     return;
00947 
00948   Fail:
00949     FT_ERROR(( "ps_hints_t1stem3: could not add counter stems to table\n" ));
00950     hints->error = error;
00951   }
00952 
00953 
00954   /* reset hints (only with Type 1 hints) */
00955   static void
00956   ps_hints_t1reset( PS_Hints  hints,
00957                     FT_UInt   end_point )
00958   {
00959     FT_Error  error = PSH_Err_Ok;
00960 
00961 
00962     if ( !hints->error )
00963     {
00964       FT_Memory  memory = hints->memory;
00965 
00966 
00967       if ( hints->hint_type == PS_HINT_TYPE_1 )
00968       {
00969         error = ps_dimension_reset_mask( &hints->dimension[0],
00970                                          end_point, memory );
00971         if ( error )
00972           goto Fail;
00973 
00974         error = ps_dimension_reset_mask( &hints->dimension[1],
00975                                          end_point, memory );
00976         if ( error )
00977           goto Fail;
00978       }
00979       else
00980       {
00981         /* invalid hint type */
00982         error = PSH_Err_Invalid_Argument;
00983         goto Fail;
00984       }
00985     }
00986     return;
00987 
00988   Fail:
00989     hints->error = error;
00990   }
00991 
00992 
00993   /* Type2 "hintmask" operator, add a new hintmask to each direction */
00994   static void
00995   ps_hints_t2mask( PS_Hints        hints,
00996                    FT_UInt         end_point,
00997                    FT_UInt         bit_count,
00998                    const FT_Byte*  bytes )
00999   {
01000     FT_Error  error;
01001 
01002 
01003     if ( !hints->error )
01004     {
01005       PS_Dimension  dim    = hints->dimension;
01006       FT_Memory     memory = hints->memory;
01007       FT_UInt       count1 = dim[0].hints.num_hints;
01008       FT_UInt       count2 = dim[1].hints.num_hints;
01009 
01010 
01011       /* check bit count; must be equal to current total hint count */
01012       if ( bit_count !=  count1 + count2 )
01013       {
01014         FT_TRACE0(( "ps_hints_t2mask:"
01015                     " called with invalid bitcount %d (instead of %d)\n",
01016                    bit_count, count1 + count2 ));
01017 
01018         /* simply ignore the operator */
01019         return;
01020       }
01021 
01022       /* set-up new horizontal and vertical hint mask now */
01023       error = ps_dimension_set_mask_bits( &dim[0], bytes, count2, count1,
01024                                           end_point, memory );
01025       if ( error )
01026         goto Fail;
01027 
01028       error = ps_dimension_set_mask_bits( &dim[1], bytes, 0, count2,
01029                                           end_point, memory );
01030       if ( error )
01031         goto Fail;
01032     }
01033     return;
01034 
01035   Fail:
01036     hints->error = error;
01037   }
01038 
01039 
01040   static void
01041   ps_hints_t2counter( PS_Hints        hints,
01042                       FT_UInt         bit_count,
01043                       const FT_Byte*  bytes )
01044   {
01045     FT_Error  error;
01046 
01047 
01048     if ( !hints->error )
01049     {
01050       PS_Dimension  dim    = hints->dimension;
01051       FT_Memory     memory = hints->memory;
01052       FT_UInt       count1 = dim[0].hints.num_hints;
01053       FT_UInt       count2 = dim[1].hints.num_hints;
01054 
01055 
01056       /* check bit count, must be equal to current total hint count */
01057       if ( bit_count !=  count1 + count2 )
01058       {
01059         FT_TRACE0(( "ps_hints_t2counter:"
01060                     " called with invalid bitcount %d (instead of %d)\n",
01061                    bit_count, count1 + count2 ));
01062 
01063         /* simply ignore the operator */
01064         return;
01065       }
01066 
01067       /* set-up new horizontal and vertical hint mask now */
01068       error = ps_dimension_set_mask_bits( &dim[0], bytes, 0, count1,
01069                                           0, memory );
01070       if ( error )
01071         goto Fail;
01072 
01073       error = ps_dimension_set_mask_bits( &dim[1], bytes, count1, count2,
01074                                           0, memory );
01075       if ( error )
01076         goto Fail;
01077     }
01078     return;
01079 
01080   Fail:
01081     hints->error = error;
01082   }
01083 
01084 
01085   /* end recording session */
01086   static FT_Error
01087   ps_hints_close( PS_Hints  hints,
01088                   FT_UInt   end_point )
01089   {
01090     FT_Error  error;
01091 
01092 
01093     error = hints->error;
01094     if ( !error )
01095     {
01096       FT_Memory     memory = hints->memory;
01097       PS_Dimension  dim    = hints->dimension;
01098 
01099 
01100       error = ps_dimension_end( &dim[0], end_point, memory );
01101       if ( !error )
01102       {
01103         error = ps_dimension_end( &dim[1], end_point, memory );
01104       }
01105     }
01106 
01107 #ifdef DEBUG_HINTER
01108     if ( !error )
01109       ps_debug_hints = hints;
01110 #endif
01111     return error;
01112   }
01113 
01114 
01115   /*************************************************************************/
01116   /*************************************************************************/
01117   /*****                                                               *****/
01118   /*****                TYPE 1 HINTS RECORDING INTERFACE               *****/
01119   /*****                                                               *****/
01120   /*************************************************************************/
01121   /*************************************************************************/
01122 
01123   static void
01124   t1_hints_open( T1_Hints  hints )
01125   {
01126     ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_1 );
01127   }
01128 
01129   static void
01130   t1_hints_stem( T1_Hints   hints,
01131                  FT_Int     dimension,
01132                  FT_Fixed*  coords )
01133   {
01134     FT_Pos  stems[2];
01135 
01136 
01137     stems[0] = FIXED_TO_INT( coords[0] );
01138     stems[1] = FIXED_TO_INT( coords[1] );
01139 
01140     ps_hints_stem( (PS_Hints)hints, dimension, 1, stems );
01141   }
01142 
01143 
01144   FT_LOCAL_DEF( void )
01145   t1_hints_funcs_init( T1_Hints_FuncsRec*  funcs )
01146   {
01147     FT_MEM_ZERO( (char*)funcs, sizeof ( *funcs ) );
01148 
01149     funcs->open  = (T1_Hints_OpenFunc)    t1_hints_open;
01150     funcs->close = (T1_Hints_CloseFunc)   ps_hints_close;
01151     funcs->stem  = (T1_Hints_SetStemFunc) t1_hints_stem;
01152     funcs->stem3 = (T1_Hints_SetStem3Func)ps_hints_t1stem3;
01153     funcs->reset = (T1_Hints_ResetFunc)   ps_hints_t1reset;
01154     funcs->apply = (T1_Hints_ApplyFunc)   ps_hints_apply;
01155   }
01156 
01157 
01158   /*************************************************************************/
01159   /*************************************************************************/
01160   /*****                                                               *****/
01161   /*****                TYPE 2 HINTS RECORDING INTERFACE               *****/
01162   /*****                                                               *****/
01163   /*************************************************************************/
01164   /*************************************************************************/
01165 
01166   static void
01167   t2_hints_open( T2_Hints  hints )
01168   {
01169     ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_2 );
01170   }
01171 
01172 
01173   static void
01174   t2_hints_stems( T2_Hints   hints,
01175                   FT_Int     dimension,
01176                   FT_Int     count,
01177                   FT_Fixed*  coords )
01178   {
01179     FT_Pos  stems[32], y, n;
01180     FT_Int  total = count;
01181 
01182 
01183     y = 0;
01184     while ( total > 0 )
01185     {
01186       /* determine number of stems to write */
01187       count = total;
01188       if ( count > 16 )
01189         count = 16;
01190 
01191       /* compute integer stem positions in font units */
01192       for ( n = 0; n < count * 2; n++ )
01193       {
01194         y       += coords[n];
01195         stems[n] = FIXED_TO_INT( y );
01196       }
01197 
01198       /* compute lengths */
01199       for ( n = 0; n < count * 2; n += 2 )
01200         stems[n + 1] = stems[n + 1] - stems[n];
01201 
01202       /* add them to the current dimension */
01203       ps_hints_stem( (PS_Hints)hints, dimension, count, stems );
01204 
01205       total -= count;
01206     }
01207   }
01208 
01209 
01210   FT_LOCAL_DEF( void )
01211   t2_hints_funcs_init( T2_Hints_FuncsRec*  funcs )
01212   {
01213     FT_MEM_ZERO( funcs, sizeof ( *funcs ) );
01214 
01215     funcs->open    = (T2_Hints_OpenFunc)   t2_hints_open;
01216     funcs->close   = (T2_Hints_CloseFunc)  ps_hints_close;
01217     funcs->stems   = (T2_Hints_StemsFunc)  t2_hints_stems;
01218     funcs->hintmask= (T2_Hints_MaskFunc)   ps_hints_t2mask;
01219     funcs->counter = (T2_Hints_CounterFunc)ps_hints_t2counter;
01220     funcs->apply   = (T2_Hints_ApplyFunc)  ps_hints_apply;
01221   }
01222 
01223 
01224 /* END */

Generated on Sun May 27 2012 04:34:00 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.