home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-05-22 | 7.9 KB | 304 lines | [TEXT/CWIE] |
- // =================================================================================
- // FontLight.cp ©1997 BB's Team inc. All rights reserved
- // =================================================================================
- #include "PL_Utils.h"
- #include "GWorldSaver.h"
- #include "GreyGWorld.h"
- #include "FontLight.h"
-
- #include "UDrawingState.h"
-
- #ifdef PL_DEBUG
- #include <iostream.h>
- #endif
-
-
- const Rect FontLight::nullRect = { 0, 0, 0, 0};
-
-
- // ---------------------------------------------------------------------------------
- // • ctor
- // ---------------------------------------------------------------------------------
- FontLight::FontLight (void)
- : mUpToDate (false)
- , mRect (nullRect)
- , mForScreen (false)
- , m7Bits (true)
- , mFirstChar(kFirstChar)
- , mLastChar(127)
- , mFirstEntry (0)
- , mLastEntry (0)
- , mAllowed ("\p")
- {
- // default TextTraits.
- UTextTraits::LoadSystemTraits (mTextTraits);
-
- // I like things to be initialized
- InitPairs();
- }
-
-
- // ---------------------------------------------------------------------------------
- // • dtor
- // ---------------------------------------------------------------------------------
- FontLight::~FontLight()
- { }
-
-
- // ---------------------------------------------------------------------------------
- // • IsUpToDate
- // ---------------------------------------------------------------------------------
- Boolean FontLight::IsUpToDate (void)
- {
- return mUpToDate;
- }
-
-
- // ---------------------------------------------------------------------------------
- // • SetAllowed
- // ---------------------------------------------------------------------------------
- void FontLight::SetAllowed (LStr255 inAllowed)
- {
- if ( inAllowed != mAllowed ) {
- mUpToDate = false;
- mAllowed = inAllowed;
- InitPairs();
- }
- }
-
-
- // ---------------------------------------------------------------------------------
- // • SetAllowed
- // ---------------------------------------------------------------------------------
- LStr255 FontLight::GetAllowed (void)
- {
- return mAllowed;
- }
-
-
- // ---------------------------------------------------------------------------------
- // • SetTextTraits
- // ---------------------------------------------------------------------------------
- void FontLight::SetTextTraits (const TextTraitsRecord &inTraits)
- {
- mUpToDate = mUpToDate
- && inTraits.style == mTextTraits.style
- && inTraits.fontNumber == mTextTraits.fontNumber
- && ::CompareString( inTraits.fontName, mTextTraits.fontName, nil ) == 0
- ;
- if (mForScreen)
- mUpToDate = mUpToDate && inTraits.size == mTextTraits.size;
-
- mTextTraits = inTraits;
- }
-
-
- // ---------------------------------------------------------------------------------
- // • SetRect
- // ---------------------------------------------------------------------------------
- void FontLight::SetRect (Rect inRect)
- {
- ::OffsetRect (&inRect, -inRect.left, -inRect.top);
- if ( ! ::EqualRect (&inRect, &mRect) ) {
- mUpToDate = false;
- mRect = inRect;
- }
- }
-
-
- // ---------------------------------------------------------------------------------
- // • Set7Bits
- // ---------------------------------------------------------------------------------
- void FontLight::Set7Bits (Boolean in7Bits)
- {
- if ( m7Bits!=in7Bits ) {
- mUpToDate = false;
- m7Bits=in7Bits;
- mLastChar = m7Bits ? 127 : 255;
- }
- }
-
-
- // ---------------------------------------------------------------------------------
- // • SetScreen
- // ---------------------------------------------------------------------------------
- void FontLight::SetScreen (Boolean inScreen)
- {
- if ( inScreen!=mForScreen ) {
- mUpToDate = false;
- mForScreen= inScreen;
- }
- }
-
-
- // ---------------------------------------------------------------------------------
- // • Update
- // ---------------------------------------------------------------------------------
- void FontLight::Update (void)
- {
- if (mUpToDate)
- return;
-
- // determine the base Rect for grey computations
- Int32 bigWidth, bigHeight, bigAscent, bigSize;
- if (mForScreen)
- // take the Rect containing the kBaseWidthChar character
- bigSize = mTextTraits.size;
- else {
- // find out the biggest size that fits in the Rect
- bigSize = 9;
- do {
- bigSize++;
- PL_Utils::ComputeBBox (mTextTraits, bigSize, bigWidth, bigHeight, bigAscent);
- } while ( bigSize<255
- && bigWidth<(mRect.right-mRect.left)
- && bigHeight<mRect.bottom-mRect.top);
- bigSize--;
- }
- PL_Utils::ComputeBBox (mTextTraits, bigSize, bigWidth, bigHeight, bigAscent);
-
- // create a grey offscreen
- Rect offRect;
- ::SetRect (&offRect, 0, 0, bigWidth, bigHeight);
- GreyGWorld theGrey(offRect);
- if ( !theGrey.IsOK() )
- return;
- theGrey.Lock();
-
- // auto-save the GWorld (NOT ONLY THE PORT), and set it to the offscreen GWorld
- // Warning : I used to have a StPortOriginState, and it worked… well… often !
- GWorldSaver saveGWorld (theGrey);
-
- // Set out text traits
- UTextTraits::SetPortTextTraits (&mTextTraits);
- ::TextSize(bigSize);
- StColorState::Normalize();
-
- // Initialize and set excluded
- InitPairs();
-
- // compute for each char
- Int16 baseWidth = PL_Utils::RepeatCharWidth ();
- for (int theChar = mFirstChar ; theChar<=mLastChar ; theChar++)
- if ( mPair[theChar].value != kForbidden )
- if ( PL_Utils::RepeatCharWidth (theChar) == baseWidth ) {
- ::EraseRect( &offRect );
- ::MoveTo (0, bigAscent);
- ::DrawChar (theChar);
- mPair[theChar].value = theGrey.ComputeGrey ();
- }
-
- mUpToDate = true;
- theGrey.Unlock();
-
- // Sort on lightness for fast access
- SortPairs();
-
- return;
- }
-
-
- // ---------------------------------------------------------------------------------
- // • InitPairs
- // ---------------------------------------------------------------------------------
- void FontLight::InitPairs (void)
- {
- // Initialize pairs
- for (Int16 i=0 ; i<256 ; i++) {
- mPair[i].glyph = i;
- mPair[i].value = kForbidden;
- }
-
- // allow some
- for (Int16 i=1 ; i<=mAllowed.Length() ; ++i)
- mPair[ mAllowed[i] ].value = kMissing;
-
-
- }
-
-
- // ---------------------------------------------------------------------------------
- // • ComparePairs (not a member)
- // ---------------------------------------------------------------------------------
- Boolean ComparePairs (const FontPair &a, const FontPair &b)
- {
- return a.value > b.value;
- }
-
-
- // ---------------------------------------------------------------------------------
- // • SortPairs
- // ---------------------------------------------------------------------------------
- void FontLight::SortPairs(void)
- {
- // Sort the glyph/light pairs for fast access
- // ::qsort (mPair, 256, sizeof (FontPair), ComparePairs);
- ShellSort (mPair, 256, ComparePairs);
-
- // Determine first and last usable indexes
- mFirstEntry = 0;
- while ( mPair[mFirstEntry].value < 0 )
- mFirstEntry++;
-
- mLastEntry = 255;
- while ( mPair[mLastEntry].value < 0 )
- mLastEntry--;
-
- #ifdef PL_DEBUG
- /*
- for (int i=mFirstEntry ; i<=mLastEntry ; i++)
- cout << i
- << "\t" << mPair[i].glyph
- << "\t" << (int)mPair[i].glyph
- << "\t" << mPair[i].value
- << endl;
- */
- #endif
- }
-
-
- // ---------------------------------------------------------------------------------
- // • ComputeChar
- // ---------------------------------------------------------------------------------
- char FontLight::ComputeChar (float f)
- {
- Int16 index;
- char ret;
-
- // darker than the darkest
- if ( mPair[mFirstEntry].value >= f )
- ret = mPair[mFirstEntry].glyph;
-
- // lighter than the lightest
- else if ( mPair[mLastEntry].value <= f )
- ret = mPair[mLastEntry].glyph;
-
- else {
- // between index-1 and index
- index = mFirstEntry+1;
- while ( mPair[index].value < f )
- index++;
-
- // return the closest
- if ( abs(mPair[index].value-f) < abs(mPair[index-1].value-f) )
- ret = mPair[index].glyph;
- else
- ret = mPair[index-1].glyph;
- }
- return ret;
- }
-
-
- // Simply compute Min and Max (excepts negative values). That's all !
- void FontLight::GetMinMax (float &fMin, float &fMax)
- {
- fMin = fMax = mPair[mFirstEntry].value;
- for (Int16 i = mFirstEntry ; i<=mLastEntry ; i++) {
- float u = mPair[i].value;
- if (u > fMax)
- fMax = u;
- else if (u < fMin)
- fMin=u;
- }
- }
-