Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Functions | Variables
nsRenderingContextWin.cpp File Reference
#include "nsRenderingContextWin.h"
#include "nsICharRepresentable.h"
#include "nsFontMetricsWin.h"
#include "nsRegionWin.h"
#include <math.h>
#include "nsDeviceContextWin.h"
#include "prprf.h"
#include "nsDrawingSurfaceWin.h"
#include "nsGfxCIID.h"
#include "nsUnicharUtils.h"

Go to the source code of this file.

Classes

struct  lineddastructtag
class  GraphicsState
struct  GetWidthData
struct  BreakGetTextDimensionsData
struct  GetTextDimensionsData
struct  DrawStringData
class  SolidBrushCache
struct  SolidBrushCache::CacheEntry

Defines

#define BREAK_TO_DEBUGGER
#define VERIFY(exp)   (exp)
#define FLAG_CLIP_VALID   0x0001
#define FLAG_CLIP_CHANGED   0x0002
#define FLAG_LOCAL_CLIP_VALID   0x0004
#define FLAGS_ALL   (FLAG_CLIP_VALID | FLAG_CLIP_CHANGED | FLAG_LOCAL_CLIP_VALID)
#define PALETTERGB_COLORREF(c)   (0x02000000 | (c))
#define NOT_SETUP   0x33
#define DONT_INIT   0

Typedefs

typedef struct lineddastructtag lineddastruct

Functions

static NS_DEFINE_IID (kIRenderingContextIID, NS_IRENDERING_CONTEXT_IID)
static NS_DEFINE_IID (kIRenderingContextWinIID, NS_IRENDERING_CONTEXT_WIN_IID)
void CALLBACK LineDDAFunc (int x, int y, LONG lData)
void CheckLength (PRUint32 *aLength)
static PRBool PR_CALLBACK do_GetWidth (const nsFontSwitch *aFontSwitch, const PRUnichar *aSubstring, PRUint32 aSubstringLength, void *aData)
static PRBool PR_CALLBACK do_BreakGetTextDimensions (const nsFontSwitch *aFontSwitch, const PRUnichar *aSubstring, PRUint32 aSubstringLength, void *aData)
static PRBool PR_CALLBACK do_GetTextDimensions (const nsFontSwitch *aFontSwitch, const PRUnichar *aSubstring, PRUint32 aSubstringLength, void *aData)
static PRBool PR_CALLBACK do_DrawString (const nsFontSwitch *aFontSwitch, const PRUnichar *aSubstring, PRUint32 aSubstringLength, void *aData)

Variables

static PRBool gIsWIN95 = NOT_SETUP
static DWORD gBidiInfo = NOT_SETUP
static HFONT gStockSystemFont = (HFONT)::GetStockObject(SYSTEM_FONT)
static HBRUSH gStockWhiteBrush = (HBRUSH)::GetStockObject(WHITE_BRUSH)
static HPEN gStockBlackPen = (HPEN)::GetStockObject(BLACK_PEN)
static HPEN gStockWhitePen = (HPEN)::GetStockObject(WHITE_PEN)
static const int BRUSH_CACHE_SIZE = 17
static SolidBrushCache gSolidBrushCache

Class Documentation

struct lineddastructtag

Definition at line 79 of file nsRenderingContextWin.cpp.

Collaboration diagram for lineddastructtag:
Class Members
COLORREF crColor
HDC dc
int nDottedPixel
struct GetWidthData

Definition at line 1241 of file nsRenderingContextOS2.cpp.

Collaboration diagram for GetWidthData:
Class Members
HDC mDC
nsFontOS2 * mFont
HFONT mFont
HPS mPS
nsDrawingSurfaceOS2 * mSurface
LONG mWidth
struct BreakGetTextDimensionsData

Definition at line 4322 of file nsFontMetricsGTK.cpp.

Collaboration diagram for BreakGetTextDimensionsData:
Class Members
PRInt32 mAvailWidth
nscoord mAveCharWidth
PRInt32 * mBreaks
HDC mDC
PRInt32 mEstimatedNumChars
nsFontOS2 * mFont
HFONT mFont
nsVoidArray * mFonts
PRInt32 mNumBreaks
PRInt32 mNumCharsFit
nsVoidArray * mOffsets
float mP2T
PRInt32 mPrevBreakState_BreakIndex
nscoord mPrevBreakState_Width
HPS mPS
nscoord mSpaceWidth
nsDrawingSurfaceOS2 * mSurface
nscoord mWidth
struct GetTextDimensionsData

Definition at line 1915 of file nsRenderingContextOS2.cpp.

Collaboration diagram for GetTextDimensionsData:
Class Members
nscoord mAscent
HDC mDC
nscoord mDescent
nsFontOS2 * mFont
HFONT mFont
float mP2T
HPS mPS
nsDrawingSurfaceOS2 * mSurface
LONG mWidth
struct DrawStringData

Definition at line 201 of file nsFontMetricsXft.cpp.

Collaboration diagram for DrawStringData:
Class Members
XftColor color
nsRenderingContextGTK * context
nsCairoRenderingContext * context
XftDraw * draw
nsAutoDrawSpecBuffer * drawBuffer
HDC mDC
nsFontOS2 * mFont
HFONT mFont
nscoord mLength
nscoord mMaxLength
HPS mPS
const nscoord * mSpacing
nsDrawingSurfaceOS2 * mSurface
nsTransform2D * mTranMatrix
nscoord mX
nscoord mY
float p2t
const nscoord * spacing
nscoord x
nscoord xOffset
nscoord y
struct SolidBrushCache::CacheEntry

Definition at line 2532 of file nsRenderingContextWin.cpp.

Class Members
HBRUSH mBrush
COLORREF mBrushColor

Define Documentation

Definition at line 55 of file nsRenderingContextWin.cpp.

#define DONT_INIT   0

Definition at line 169 of file nsRenderingContextWin.cpp.

#define FLAG_CLIP_CHANGED   0x0002

Definition at line 69 of file nsRenderingContextWin.cpp.

#define FLAG_CLIP_VALID   0x0001

Definition at line 68 of file nsRenderingContextWin.cpp.

Definition at line 70 of file nsRenderingContextWin.cpp.

Definition at line 72 of file nsRenderingContextWin.cpp.

#define NOT_SETUP   0x33

Definition at line 166 of file nsRenderingContextWin.cpp.

#define PALETTERGB_COLORREF (   c)    (0x02000000 | (c))

Definition at line 77 of file nsRenderingContextWin.cpp.

#define VERIFY (   exp)    (exp)

Definition at line 61 of file nsRenderingContextWin.cpp.


Typedef Documentation


Function Documentation

void CheckLength ( PRUint32 aLength) [inline]

Definition at line 1421 of file nsRenderingContextWin.cpp.

{
  if (gIsWIN95 && *aLength > 8192)
    *aLength = 8192;
}

Here is the caller graph for this function:

static PRBool PR_CALLBACK do_BreakGetTextDimensions ( const nsFontSwitch aFontSwitch,
const PRUnichar aSubstring,
PRUint32  aSubstringLength,
void aData 
) [static]

Definition at line 1696 of file nsRenderingContextWin.cpp.

{
  nsFontWin* fontWin = aFontSwitch->mFontWin;

  // Make sure the font is selected
  BreakGetTextDimensionsData* data = (BreakGetTextDimensionsData*)aData;
  if (data->mFont != fontWin->mFont) {
    data->mFont = fontWin->mFont;
    ::SelectObject(data->mDC, data->mFont);
  }

  // Our current state relative to the _full_ string...
  // This allows emulation of the previous code...
  const PRUnichar* pstr = (const PRUnichar*)data->mOffsets->ElementAt(0);
  PRInt32 numCharsFit = data->mNumCharsFit;
  nscoord width = data->mWidth;
  PRInt32 start = (PRInt32)(aSubstring - pstr);
  PRInt32 end = start + aSubstringLength;
  PRBool allDone = PR_FALSE;

  while (start < end) {
    // Estimate how many characters will fit. Do that by dividing the
    // available space by the average character width
    PRInt32 estimatedNumChars = data->mEstimatedNumChars;
    if (!estimatedNumChars && data->mAveCharWidth > 0) {
      estimatedNumChars = (data->mAvailWidth - width) / data->mAveCharWidth;
    }
    // Make sure the estimated number of characters is at least 1
    if (estimatedNumChars < 1) {
      estimatedNumChars = 1;
    }

    // Find the nearest break offset
    PRInt32 estimatedBreakOffset = start + estimatedNumChars;
    PRInt32 breakIndex = -1; // not yet computed
    PRBool  inMiddleOfSegment = PR_FALSE;
    nscoord numChars;

    // Avoid scanning the break array in the case where we think all
    // the text should fit
    if (end <= estimatedBreakOffset) {
      // Everything should fit
      numChars = end - start;
    }
    else {
      // Find the nearest place to break that is less than or equal to
      // the estimated break offset
      breakIndex = data->mPrevBreakState_BreakIndex;
      while (breakIndex + 1 < data->mNumBreaks &&
             data->mBreaks[breakIndex + 1] <= estimatedBreakOffset) {
        ++breakIndex;
      }

      if (breakIndex == -1)
        breakIndex = 0;

      // We found a place to break that is before the estimated break
      // offset. Where we break depends on whether the text crosses a
      // segment boundary
      if (start < data->mBreaks[breakIndex]) {
        // The text crosses at least one segment boundary so measure to the
        // break point just before the estimated break offset
        numChars = PR_MIN(data->mBreaks[breakIndex], end) - start;
      } 
      else {
        // See whether there is another segment boundary between this one
        // and the end of the text
        if ((breakIndex < (data->mNumBreaks - 1)) && (data->mBreaks[breakIndex] < end)) {
          ++breakIndex;
          numChars = PR_MIN(data->mBreaks[breakIndex], end) - start;
        }
        else {
          NS_ASSERTION(end != data->mBreaks[breakIndex], "don't expect to be at segment boundary");

          // The text is all within the same segment
          numChars = end - start;

          // Remember we're in the middle of a segment and not between
          // two segments
          inMiddleOfSegment = PR_TRUE;
        }
      }
    }

    // Measure the text
    nscoord twWidth, pxWidth;
    if ((1 == numChars) && (pstr[start] == ' ')) {
      twWidth = data->mSpaceWidth;
    }
    else {
      pxWidth = fontWin->GetWidth(data->mDC, &pstr[start], numChars);
      twWidth = NSToCoordRound(float(pxWidth) * data->mP2T);
    }

    // See if the text fits
    PRBool textFits = (twWidth + width) <= data->mAvailWidth;

    // If the text fits then update the width and the number of
    // characters that fit
    if (textFits) {
      numCharsFit += numChars;
      width += twWidth;

      // If we computed the break index and we're not in the middle
      // of a segment then this is a spot that we can back up to if
      // we need to, so remember this state
      if ((breakIndex != -1) && !inMiddleOfSegment) {
        data->mPrevBreakState_BreakIndex = breakIndex;
        data->mPrevBreakState_Width = width;
      }
    }
    else {
      // The text didn't fit. If we're out of room then we're all done
      allDone = PR_TRUE;

      // See if we can just back up to the previous saved state and not
      // have to measure any text
      if (data->mPrevBreakState_BreakIndex != -1) {
        PRBool canBackup;

        // If we're in the middle of a word then the break index
        // must be the same if we can use it. If we're at a segment
        // boundary, then if the saved state is for the previous
        // break index then we can use it
        if (inMiddleOfSegment) {
          canBackup = data->mPrevBreakState_BreakIndex == breakIndex;
        } else {
          canBackup = data->mPrevBreakState_BreakIndex == (breakIndex - 1);
        }

        if (canBackup) {
          numCharsFit = data->mBreaks[data->mPrevBreakState_BreakIndex];
          width = data->mPrevBreakState_Width;
          break;
        }
      }

      // We can't just revert to the previous break state. Find the break
      // index just before the end of the text
      end = start + numChars;
      breakIndex = 0;
      if (data->mBreaks[breakIndex] < end) {
        while ((breakIndex + 1 < data->mNumBreaks) && (data->mBreaks[breakIndex + 1] < end)) {
          ++breakIndex;
        }
      }

      if ((0 == breakIndex) && (end <= data->mBreaks[0])) {
        // There's no place to back up to, so even though the text doesn't fit
        // return it anyway
        numCharsFit += numChars;
        width += twWidth;

        // Edge case of one word: it could be that we just measured a fragment of the
        // first word and its remainder involves other fonts, so we want to keep going
        // until we at least measure the entire first word
        if (numCharsFit < data->mBreaks[0]) {
          allDone = PR_FALSE;
          // From now on we don't care anymore what is the _real_ estimated
          // number of characters that fits. Rather, we have no where to break
          // and have to measure one word fully, but the real estimate is less
          // than that one word. However, since the other bits of code rely on
          // what is in "data->mEstimatedNumChars", we want to override
          // "data->mEstimatedNumChars" and pass in what _has_ to be measured
          // so that it is transparent to the other bits that depend on it.
          data->mEstimatedNumChars = data->mBreaks[0] - numCharsFit;
          start += numChars;
        }

        break;
      }

      // Repeatedly back up until we get to where the text fits or we're
      // all the way back to the first word
      width += twWidth;
      while ((breakIndex >= 0) && (width > data->mAvailWidth)) {
        start = data->mBreaks[breakIndex];
        numChars = end - start;
        numCharsFit = start;
        if ((1 == numChars) && (pstr[start] == ' ')) {
          width -= data->mSpaceWidth;
        }
        else if (pstr + start >= aSubstring) {
          // The entire fragment to chop is within the current font.
          pxWidth = fontWin->GetWidth(data->mDC, &pstr[start], numChars);
          width -= NSToCoordRound(float(pxWidth) * data->mP2T);
        }
        else {
          // The fragment that we want to chop extends back into previous fonts.
          // We need to reverse into previous fonts. Fortunately,
          // data->mFonts[] and data->mOffsets[] tell us which fonts are used
          // and when. 
          end = data->mNumCharsFit; // same as aSubstring - pstr
          data->mNumCharsFit = numCharsFit; // has got shorter...
          PRInt32 k = data->mFonts->Count() - 1;
          for ( ; k >= 0 && start < end; --k, end -= numChars) {
            fontWin = (nsFontWin*)data->mFonts->ElementAt(k);
            const PRUnichar* ps = (const PRUnichar*)data->mOffsets->ElementAt(k);
            if (ps < pstr + start)
              ps = pstr + start;

            numChars = pstr + end - ps;
            NS_ASSERTION(numChars > 0, "empty string");

            data->mFont = fontWin->mFont;
            ::SelectObject(data->mDC, data->mFont);
            pxWidth = fontWin->GetWidth(data->mDC, ps, numChars);
            data->mWidth -= NSToCoordRound(float(pxWidth) * data->mP2T);

            // By construction, mFonts[k] is the last font, and
            // mOffsets[k+1] is the last offset.
            data->mFonts->RemoveElementAt(k);
            data->mOffsets->RemoveElementAt(k+1);
          }

          // We are done, update the data now because we won't do it later.
          // The |if (data->mNumCharsFit != numCharsFit)| won't apply below
          data->mFonts->AppendElement(fontWin);
          data->mOffsets->AppendElement((void*)&pstr[numCharsFit]);
          break;
        }

        --breakIndex;
        end = start;
      }
    }

    start += numChars;
  }

#ifdef DEBUG_rbs
  NS_ASSERTION(allDone || start == end, "internal error");
  NS_ASSERTION(allDone || data->mNumCharsFit != numCharsFit, "internal error");
#endif /* DEBUG_rbs */

  if (data->mNumCharsFit != numCharsFit) {
    // some text was actually retained
    data->mWidth = width;
    data->mNumCharsFit = numCharsFit;
    data->mFonts->AppendElement(fontWin);
    data->mOffsets->AppendElement((void*)&pstr[numCharsFit]);
  }

  if (allDone) {
    // stop now
    return PR_FALSE;
  }

  return PR_TRUE; // don't stop if we still need to measure more characters
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool PR_CALLBACK do_DrawString ( const nsFontSwitch aFontSwitch,
const PRUnichar aSubstring,
PRUint32  aSubstringLength,
void aData 
) [static]

Definition at line 2233 of file nsRenderingContextWin.cpp.

{
  nsFontWin* fontWin = aFontSwitch->mFontWin;

  PRInt32 x, y;
  DrawStringData* data = (DrawStringData*)aData;
  if (data->mFont != fontWin->mFont) {
    data->mFont = fontWin->mFont;
    ::SelectObject(data->mDC, data->mFont);
  }

  data->mLength += aSubstringLength;
  if (data->mSpacing) {
    // XXX Fix path to use a twips transform in the DC and use the
    // spacing values directly and let windows deal with the sub-pixel
    // positioning.

    // Slow, but accurate rendering
    const PRUnichar* str = aSubstring;
    const PRUnichar* end = aSubstring + aSubstringLength;
    while (str < end) {
      // XXX can shave some cycles by inlining a version of transform
      // coord where y is constant and transformed once
      x = data->mX;
      y = data->mY;
      data->mTranMatrix->TransformCoord(&x, &y);
      if (IS_HIGH_SURROGATE(*str) && 
          ((str+1)<end) && 
          IS_LOW_SURROGATE(*(str+1))) 
      {
        // special case for surrogate pair
        fontWin->DrawString(data->mDC, x, y, str, 2);
        // we need to advance data->mX and str twice
        data->mX += *data->mSpacing++;
        ++str;
      } else {
        fontWin->DrawString(data->mDC, x, y, str, 1);
      }
      data->mX += *data->mSpacing++;
      ++str;
    }
  }
  else {
    fontWin->DrawString(data->mDC, data->mX, data->mY, aSubstring, aSubstringLength);
    // be ready if there is more to come
    if (data->mLength < data->mMaxLength) {
      data->mX += fontWin->GetWidth(data->mDC, aSubstring, aSubstringLength);
    }
  }
  return PR_TRUE; // don't stop till the end
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool PR_CALLBACK do_GetTextDimensions ( const nsFontSwitch aFontSwitch,
const PRUnichar aSubstring,
PRUint32  aSubstringLength,
void aData 
) [static]

Definition at line 2137 of file nsRenderingContextWin.cpp.

{
  nsFontWin* fontWin = aFontSwitch->mFontWin;
  GetTextDimensionsData* data = (GetTextDimensionsData*)aData;
  if (data->mFont != fontWin->mFont) {
    data->mFont = fontWin->mFont;
    ::SelectObject(data->mDC, data->mFont);
  }
  data->mWidth += fontWin->GetWidth(data->mDC, aSubstring, aSubstringLength);
  if (data->mAscent < fontWin->mMaxAscent) {
    data->mAscent = fontWin->mMaxAscent;
  }
  if (data->mDescent < fontWin->mMaxDescent) {
    data->mDescent = fontWin->mMaxDescent;
  }

  return PR_TRUE; // don't stop till the end
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool PR_CALLBACK do_GetWidth ( const nsFontSwitch aFontSwitch,
const PRUnichar aSubstring,
PRUint32  aSubstringLength,
void aData 
) [static]

Definition at line 1473 of file nsRenderingContextWin.cpp.

{
  nsFontWin* fontWin = aFontSwitch->mFontWin;

  GetWidthData* data = (GetWidthData*)aData;
  if (data->mFont != fontWin->mFont) {
    // the desired font is not the current font in the DC
    data->mFont = fontWin->mFont;
    ::SelectObject(data->mDC, data->mFont);
  }
  data->mWidth += fontWin->GetWidth(data->mDC, aSubstring, aSubstringLength);
  return PR_TRUE; // don't stop till the end
}

Here is the call graph for this function:

Here is the caller graph for this function:

void CALLBACK LineDDAFunc ( int  x,
int  y,
LONG  lData 
)

Definition at line 86 of file nsRenderingContextWin.cpp.

{
  lineddastruct * dda_struct = (lineddastruct *) lData;
  
  dda_struct->nDottedPixel ^= 1; 

  if (dda_struct->nDottedPixel)
    SetPixel(dda_struct->dc, x, y, dda_struct->crColor);
}   

Here is the call graph for this function:

Here is the caller graph for this function:

static NS_DEFINE_IID ( kIRenderingContextIID  ,
NS_IRENDERING_CONTEXT_IID   
) [static]
static NS_DEFINE_IID ( kIRenderingContextWinIID  ,
NS_IRENDERING_CONTEXT_WIN_IID   
) [static]

Variable Documentation

const int BRUSH_CACHE_SIZE = 17 [static]

Definition at line 2522 of file nsRenderingContextWin.cpp.

Definition at line 170 of file nsRenderingContextWin.cpp.

Definition at line 167 of file nsRenderingContextWin.cpp.

Definition at line 2605 of file nsRenderingContextWin.cpp.

HPEN gStockBlackPen = (HPEN)::GetStockObject(BLACK_PEN) [static]

Definition at line 176 of file nsRenderingContextWin.cpp.

HFONT gStockSystemFont = (HFONT)::GetStockObject(SYSTEM_FONT) [static]

Definition at line 174 of file nsRenderingContextWin.cpp.

HBRUSH gStockWhiteBrush = (HBRUSH)::GetStockObject(WHITE_BRUSH) [static]

Definition at line 175 of file nsRenderingContextWin.cpp.

HPEN gStockWhitePen = (HPEN)::GetStockObject(WHITE_PEN) [static]

Definition at line 177 of file nsRenderingContextWin.cpp.