home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C ++ / Applications / Pict2Ascii 1.03 / Src / FontLight.cp < prev    next >
Encoding:
Text File  |  1997-05-22  |  7.9 KB  |  304 lines  |  [TEXT/CWIE]

  1. // =================================================================================
  2. //    FontLight.cp                                    ©1997 BB's Team inc. All rights reserved
  3. // =================================================================================
  4. #include "PL_Utils.h"
  5. #include "GWorldSaver.h"
  6. #include "GreyGWorld.h"
  7. #include "FontLight.h"
  8.  
  9. #include "UDrawingState.h"
  10.  
  11. #ifdef PL_DEBUG
  12.     #include <iostream.h>
  13. #endif
  14.  
  15.  
  16. const Rect FontLight::nullRect = { 0, 0, 0, 0};
  17.  
  18.  
  19. // ---------------------------------------------------------------------------------
  20. //        • ctor
  21. // ---------------------------------------------------------------------------------
  22. FontLight::FontLight (void)
  23.     : mUpToDate (false)
  24.     , mRect (nullRect)
  25.     , mForScreen (false)
  26.     , m7Bits (true)
  27.     , mFirstChar(kFirstChar)
  28.     , mLastChar(127)
  29.     , mFirstEntry (0)
  30.     , mLastEntry (0)
  31.     , mAllowed ("\p")
  32. {
  33.     // default TextTraits.
  34.     UTextTraits::LoadSystemTraits (mTextTraits);
  35.  
  36.     // I like things to be initialized
  37.     InitPairs();
  38. }
  39.  
  40.  
  41. // ---------------------------------------------------------------------------------
  42. //        • dtor
  43. // ---------------------------------------------------------------------------------
  44. FontLight::~FontLight()
  45. { }
  46.  
  47.  
  48. // ---------------------------------------------------------------------------------
  49. //        • IsUpToDate
  50. // ---------------------------------------------------------------------------------
  51. Boolean FontLight::IsUpToDate (void)
  52. {
  53.     return mUpToDate;
  54. }
  55.  
  56.  
  57. // ---------------------------------------------------------------------------------
  58. //        • SetAllowed
  59. // ---------------------------------------------------------------------------------
  60. void FontLight::SetAllowed (LStr255 inAllowed)
  61. {
  62.     if ( inAllowed != mAllowed ) {
  63.         mUpToDate  = false;
  64.         mAllowed = inAllowed;
  65.         InitPairs();
  66.     }
  67. }
  68.  
  69.  
  70. // ---------------------------------------------------------------------------------
  71. //        • SetAllowed
  72. // ---------------------------------------------------------------------------------
  73. LStr255 FontLight::GetAllowed (void)
  74. {
  75.     return mAllowed;
  76. }
  77.  
  78.  
  79. // ---------------------------------------------------------------------------------
  80. //        • SetTextTraits
  81. // ---------------------------------------------------------------------------------
  82. void FontLight::SetTextTraits (const TextTraitsRecord &inTraits)
  83. {
  84.     mUpToDate = mUpToDate
  85.                 && inTraits.style      == mTextTraits.style
  86.                 && inTraits.fontNumber == mTextTraits.fontNumber
  87.                 && ::CompareString( inTraits.fontName, mTextTraits.fontName, nil ) == 0
  88.                 ;
  89.     if (mForScreen)
  90.         mUpToDate = mUpToDate && inTraits.size == mTextTraits.size;
  91.  
  92.     mTextTraits = inTraits;
  93. }
  94.  
  95.  
  96. // ---------------------------------------------------------------------------------
  97. //        • SetRect
  98. // ---------------------------------------------------------------------------------
  99. void FontLight::SetRect (Rect inRect)
  100. {
  101.     ::OffsetRect (&inRect, -inRect.left, -inRect.top);
  102.     if ( ! ::EqualRect (&inRect, &mRect) ) {
  103.         mUpToDate = false;
  104.         mRect = inRect;
  105.     }
  106. }
  107.  
  108.  
  109. // ---------------------------------------------------------------------------------
  110. //        • Set7Bits
  111. // ---------------------------------------------------------------------------------
  112. void FontLight::Set7Bits (Boolean in7Bits)
  113. {
  114.     if ( m7Bits!=in7Bits ) {
  115.         mUpToDate = false;
  116.         m7Bits=in7Bits;
  117.         mLastChar = m7Bits ? 127 : 255;
  118.     }
  119. }
  120.  
  121.  
  122. // ---------------------------------------------------------------------------------
  123. //        • SetScreen
  124. // ---------------------------------------------------------------------------------
  125. void FontLight::SetScreen (Boolean inScreen)
  126. {
  127.     if ( inScreen!=mForScreen ) {
  128.         mUpToDate = false;
  129.         mForScreen= inScreen;
  130.     }
  131. }
  132.  
  133.  
  134. // ---------------------------------------------------------------------------------
  135. //        • Update
  136. // ---------------------------------------------------------------------------------
  137. void FontLight::Update (void)
  138. {
  139.     if (mUpToDate)
  140.         return;
  141.  
  142.     // determine the base Rect for grey computations
  143.     Int32 bigWidth, bigHeight, bigAscent, bigSize;
  144.     if (mForScreen)
  145.         // take the Rect containing the kBaseWidthChar character
  146.         bigSize = mTextTraits.size;
  147.     else {
  148.         // find out the biggest size that fits in the Rect
  149.         bigSize = 9;
  150.         do {
  151.             bigSize++;
  152.             PL_Utils::ComputeBBox (mTextTraits, bigSize, bigWidth, bigHeight, bigAscent);
  153.         } while (   bigSize<255
  154.                  && bigWidth<(mRect.right-mRect.left)
  155.                  && bigHeight<mRect.bottom-mRect.top);
  156.         bigSize--;
  157.     }
  158.     PL_Utils::ComputeBBox (mTextTraits, bigSize, bigWidth, bigHeight, bigAscent);
  159.  
  160.     // create a grey offscreen
  161.     Rect    offRect;
  162.     ::SetRect (&offRect, 0, 0, bigWidth, bigHeight);
  163.     GreyGWorld theGrey(offRect);
  164.     if ( !theGrey.IsOK() )
  165.         return;
  166.     theGrey.Lock();
  167.  
  168.     // auto-save the GWorld (NOT ONLY THE PORT), and set it to the offscreen GWorld
  169.     // Warning : I used to have a StPortOriginState, and it worked… well… often !
  170.     GWorldSaver saveGWorld (theGrey);
  171.  
  172.     // Set out text traits
  173.     UTextTraits::SetPortTextTraits (&mTextTraits);
  174.     ::TextSize(bigSize);
  175.     StColorState::Normalize();
  176.  
  177.     // Initialize and set excluded
  178.     InitPairs();
  179.  
  180.     // compute for each char
  181.     Int16 baseWidth = PL_Utils::RepeatCharWidth ();
  182.     for (int theChar = mFirstChar ; theChar<=mLastChar ; theChar++)
  183.         if ( mPair[theChar].value != kForbidden )
  184.             if ( PL_Utils::RepeatCharWidth (theChar) == baseWidth )  {
  185.                 ::EraseRect( &offRect );
  186.                 ::MoveTo (0, bigAscent);
  187.                 ::DrawChar (theChar);
  188.                 mPair[theChar].value = theGrey.ComputeGrey ();
  189.             }
  190.  
  191.     mUpToDate = true;
  192.     theGrey.Unlock();
  193.  
  194.     // Sort on lightness for fast access
  195.     SortPairs();
  196.  
  197.     return;
  198. }
  199.  
  200.  
  201. // ---------------------------------------------------------------------------------
  202. //        • InitPairs
  203. // ---------------------------------------------------------------------------------
  204. void FontLight::InitPairs (void)
  205. {
  206.     // Initialize pairs
  207.     for (Int16 i=0 ; i<256 ; i++) {
  208.         mPair[i].glyph = i;
  209.         mPair[i].value = kForbidden;
  210.     }
  211.  
  212.     // allow some
  213.     for (Int16 i=1 ; i<=mAllowed.Length() ; ++i)
  214.         mPair[ mAllowed[i] ].value = kMissing;
  215.         
  216.     
  217. }
  218.  
  219.  
  220. // ---------------------------------------------------------------------------------
  221. //        • ComparePairs (not a member)
  222. // ---------------------------------------------------------------------------------
  223. Boolean ComparePairs (const FontPair &a, const FontPair &b)
  224. {
  225.     return a.value > b.value;
  226. }
  227.  
  228.  
  229. // ---------------------------------------------------------------------------------
  230. //        • SortPairs
  231. // ---------------------------------------------------------------------------------
  232. void FontLight::SortPairs(void)
  233. {
  234.     // Sort the glyph/light pairs for fast access
  235. //    ::qsort (mPair, 256, sizeof (FontPair), ComparePairs);
  236.     ShellSort (mPair, 256, ComparePairs);
  237.  
  238.     // Determine first and last usable indexes
  239.     mFirstEntry = 0;
  240.     while ( mPair[mFirstEntry].value < 0 )
  241.         mFirstEntry++;
  242.  
  243.     mLastEntry = 255;
  244.     while ( mPair[mLastEntry].value < 0 )
  245.         mLastEntry--;
  246.  
  247. #ifdef PL_DEBUG
  248. /*
  249.     for (int i=mFirstEntry ; i<=mLastEntry ; i++)
  250.         cout    << i 
  251.                 << "\t" <<      mPair[i].glyph
  252.                 << "\t" << (int)mPair[i].glyph
  253.                 << "\t" << mPair[i].value
  254.                 << endl;
  255. */
  256. #endif
  257. }
  258.  
  259.     
  260. // ---------------------------------------------------------------------------------
  261. //        • ComputeChar
  262. // ---------------------------------------------------------------------------------
  263. char FontLight::ComputeChar (float f)
  264. {
  265.     Int16 index;
  266.     char    ret;
  267.  
  268.     // darker than the darkest
  269.     if ( mPair[mFirstEntry].value >= f )
  270.         ret = mPair[mFirstEntry].glyph;
  271.  
  272.     // lighter than the lightest
  273.     else if ( mPair[mLastEntry].value <= f )
  274.         ret = mPair[mLastEntry].glyph;
  275.  
  276.     else {
  277.         // between index-1 and index
  278.         index = mFirstEntry+1;
  279.         while ( mPair[index].value < f )
  280.             index++;
  281.  
  282.         // return the closest
  283.         if ( abs(mPair[index].value-f) < abs(mPair[index-1].value-f) )
  284.             ret =  mPair[index].glyph;
  285.         else
  286.             ret =  mPair[index-1].glyph;
  287.     }
  288.     return ret;
  289. }
  290.  
  291.  
  292. // Simply compute Min and Max (excepts negative values). That's all !
  293. void FontLight::GetMinMax (float &fMin, float &fMax)
  294. {    
  295.     fMin = fMax = mPair[mFirstEntry].value;
  296.     for (Int16 i = mFirstEntry ; i<=mLastEntry ; i++) {
  297.         float u = mPair[i].value;
  298.         if (u > fMax)
  299.             fMax = u;
  300.         else if (u < fMin)
  301.             fMin=u;
  302.     }
  303. }
  304.