diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp index 42020855d99..ee767cf9ead 100644 --- a/content/canvas/src/nsCanvasRenderingContext2D.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -1589,8 +1589,8 @@ nsCanvasRenderingContext2D::MozMeasureText(const nsAString& textToMeasure, float PRBool tightBoundingBox = PR_FALSE; gfxTextRun::Metrics metrics = textRun->MeasureText(/* offset = */ 0, textToMeasure.Length(), - tightBoundingBox, mThebesContext, - nsnull); + tightBoundingBox, + nsnull); *retVal = metrics.mAdvanceWidth/gfxFloat(elemDocument->GetPrimaryShell()->GetPresContext()->AppUnitsPerCSSPixel()); return NS_OK; } diff --git a/gfx/cairo/cairo/src/cairo-win32-font.c b/gfx/cairo/cairo/src/cairo-win32-font.c index 9f01bc8ddd5..81213e770eb 100644 --- a/gfx/cairo/cairo/src/cairo-win32-font.c +++ b/gfx/cairo/cairo/src/cairo-win32-font.c @@ -99,7 +99,6 @@ typedef struct { HFONT scaled_hfont; HFONT unscaled_hfont; - cairo_bool_t is_truetype; cairo_bool_t glyph_indexing; cairo_bool_t delete_scaled_hfont; @@ -745,11 +744,11 @@ _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font) } - scaled_font->is_truetype = (metrics.tmPitchAndFamily & TMPF_TRUETYPE) != 0; - scaled_font->glyph_indexing = scaled_font->is_truetype || - (GetFontData (hdc, OPENTYPE_CFF_TAG, 0, NULL, 0) != GDI_ERROR); - // XXX in what situations does this OPENTYPE_CFF thing not have the - // TMPF_TRUETYPE flag? GetFontData says it only works on Truetype fonts... + if ((metrics.tmPitchAndFamily & TMPF_TRUETYPE) || + (GetFontData (hdc, OPENTYPE_CFF_TAG, 0, NULL, 0) != GDI_ERROR)) + scaled_font->glyph_indexing = TRUE; + else + scaled_font->glyph_indexing = FALSE; _cairo_scaled_font_set_metrics (&scaled_font->base, &extents); @@ -765,35 +764,18 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f cairo_status_t status; cairo_text_extents_t extents; HDC hdc; + UINT glyph_index_option; hdc = _get_global_font_dc (); if (!hdc) return CAIRO_STATUS_NO_MEMORY; - if (!scaled_font->is_truetype) { - /* GetGlyphOutline will not work. Assume that the glyph does not extend outside the font box. */ - cairo_font_extents_t font_extents; - INT width = 0; - UINT charIndex = _cairo_scaled_glyph_index (scaled_glyph); + if (scaled_font->glyph_indexing) + glyph_index_option = GGO_GLYPH_INDEX; + else + glyph_index_option = 0; - cairo_scaled_font_extents (&scaled_font->base, &font_extents); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (!status) { - if (!GetCharWidth32(hdc, charIndex, charIndex, &width)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetCharWidth32"); - width = 0; - } - } - cairo_win32_scaled_font_done_font (&scaled_font->base); - - extents.x_bearing = 0; - extents.y_bearing = -font_extents.ascent / scaled_font->y_scale; - extents.width = width / scaled_font->x_scale; - extents.height = (font_extents.ascent + font_extents.descent) / scaled_font->y_scale; - extents.x_advance = extents.width; - extents.y_advance = 0; - } else if (scaled_font->preserve_axes && scaled_font->base.options.hint_style != CAIRO_HINT_METRICS_OFF) { + if (scaled_font->preserve_axes && scaled_font->base.options.hint_style != CAIRO_HINT_METRICS_OFF) { /* If we aren't rotating / skewing the axes, then we get the metrics * from the GDI in device space and convert to font space. */ @@ -801,7 +783,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f if (status) return status; if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_METRICS | GGO_GLYPH_INDEX, + GGO_METRICS | glyph_index_option, &metrics, 0, NULL, &matrix) == GDI_ERROR) { status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW"); memset (&metrics, 0, sizeof (GLYPHMETRICS)); @@ -840,7 +822,7 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f */ status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc); if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_METRICS | GGO_GLYPH_INDEX, + GGO_METRICS | glyph_index_option, &metrics, 0, NULL, &matrix) == GDI_ERROR) { status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW"); memset (&metrics, 0, sizeof (GLYPHMETRICS)); diff --git a/gfx/thebes/public/gfxAtsuiFonts.h b/gfx/thebes/public/gfxAtsuiFonts.h index 31e70f39eb2..5191093f226 100644 --- a/gfx/thebes/public/gfxAtsuiFonts.h +++ b/gfx/thebes/public/gfxAtsuiFonts.h @@ -72,9 +72,6 @@ public: PRBool HasMirroringInfo(); - virtual void SetupGlyphExtents(gfxContext *aContext, PRUint32 aGlyphID, - PRBool aNeedTight, gfxGlyphExtents *aExtents); - protected: const gfxFontStyle *mFontStyle; @@ -96,7 +93,7 @@ protected: void InitMetrics(ATSUFontID aFontID, ATSFontRef aFontRef); - virtual PRBool SetupCairoFont(gfxContext *aContext); + virtual PRBool SetupCairoFont(cairo_t *aCR); }; class THEBES_API gfxAtsuiFontGroup : public gfxFontGroup { diff --git a/gfx/thebes/public/gfxFont.h b/gfx/thebes/public/gfxFont.h index f2c53a85116..80d0d6cddd4 100644 --- a/gfx/thebes/public/gfxFont.h +++ b/gfx/thebes/public/gfxFont.h @@ -56,6 +56,7 @@ class gfxTextRun; class nsIAtom; class gfxFont; class gfxFontGroup; +typedef struct _cairo cairo_t; #define FONT_STYLE_NORMAL 0 #define FONT_STYLE_ITALIC 1 @@ -229,75 +230,6 @@ protected: nsTHashtable mFonts; }; -/** - * This stores glyph bounds information for a particular gfxFont, at - * a particular appunits-per-dev-pixel ratio (because the compressed glyph - * width array is stored in appunits). - * - * We store a hashtable from glyph IDs to float bounding rects. For the - * common case where the glyph has no horizontal left bearing, and no - * y overflow above the font ascent or below the font descent, and tight - * bounding boxes are not required, we avoid storing the glyph ID in the hashtable - * and instead consult an array of 16-bit glyph XMost values (in appunits). - * This array always has an entry for the font's space glyph --- the width is - * assumed to be zero. - */ -class THEBES_API gfxGlyphExtents { -public: - gfxGlyphExtents(PRUint32 aAppUnitsPerDevUnit) : - mAppUnitsPerDevUnit(aAppUnitsPerDevUnit) { - mTightGlyphExtents.Init(); - } - - enum { INVALID_WIDTH = 0xFFFF }; - - // returns INVALID_WIDTH => not a contained glyph - // Otherwise the glyph has no before-bearing or vertical bearings, - // and the result is its width measured from the baseline origin, in - // appunits. - PRUint16 GetContainedGlyphWidthAppUnits(PRUint32 aGlyphID) const { - if (aGlyphID >= mWidthsForContainedGlyphsAppUnits.Length()) - return INVALID_WIDTH; - return mWidthsForContainedGlyphsAppUnits[aGlyphID]; - } - - PRBool IsGlyphKnown(PRUint32 aGlyphID) const { - if (aGlyphID < mWidthsForContainedGlyphsAppUnits.Length() && - mWidthsForContainedGlyphsAppUnits[aGlyphID] != INVALID_WIDTH) - return PR_TRUE; - return mTightGlyphExtents.GetEntry(aGlyphID) != nsnull; - } - - PRBool IsGlyphKnownWithTightExtents(PRUint32 aGlyphID) const { - return mTightGlyphExtents.GetEntry(aGlyphID) != nsnull; - } - - // Get glyph extents; a rectangle relative to the left baseline origin - gfxRect GetTightGlyphExtentsAppUnits(gfxFont *aFont, gfxContext *aContext, PRUint32 aGlyphID); - - void SetContainedGlyphWidthAppUnits(PRUint32 aGlyphID, PRUint16 aWidth); - void SetTightGlyphExtents(PRUint32 aGlyphID, const gfxRect& aExtentsAppUnits); - - PRUint32 GetAppUnitsPerDevUnit() { return mAppUnitsPerDevUnit; } - -private: - class HashEntry : public nsUint32HashKey { - public: - // When constructing a new entry in the hashtable, we'll leave this - // blank. The caller of Put() will fill this in. - HashEntry(KeyTypePointer aPtr) : nsUint32HashKey(aPtr) {} - HashEntry(const HashEntry& toCopy) : nsUint32HashKey(toCopy) { - x = toCopy.x; y = toCopy.y; width = toCopy.width; height = toCopy.height; - } - - float x, y, width, height; - }; - - nsTArray mWidthsForContainedGlyphsAppUnits; - nsTHashtable mTightGlyphExtents; - PRUint32 mAppUnitsPerDevUnit; -}; - /* a SPECIFIC single font family */ class THEBES_API gfxFont { public: @@ -327,7 +259,7 @@ protected: public: gfxFont(const nsAString &aName, const gfxFontStyle *aFontGroup); - virtual ~gfxFont(); + virtual ~gfxFont() {} const nsString& GetName() const { return mName; } const gfxFontStyle *GetStyle() const { return &mStyle; } @@ -457,7 +389,6 @@ public: virtual RunMetrics Measure(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd, PRBool aTightBoundingBox, - gfxContext *aContextForTightBoundingBox, Spacing *aSpacing); /** * Line breaks have been changed at the beginning and/or end of a substring @@ -474,21 +405,14 @@ public: // Get the glyphID of a space virtual PRUint32 GetSpaceGlyph() = 0; - gfxGlyphExtents *GetOrCreateGlyphExtents(PRUint32 aAppUnitsPerDevUnit); - - // You need to call SetupCairoFont on the aCR just before calling this - virtual void SetupGlyphExtents(gfxContext *aContext, PRUint32 aGlyphID, - PRBool aNeedTight, gfxGlyphExtents *aExtents); - - // This is called by the default Draw() implementation above. - virtual PRBool SetupCairoFont(gfxContext *aContext) = 0; - protected: // The family name of the font - nsString mName; - nsExpirationState mExpirationState; - gfxFontStyle mStyle; - nsAutoTArray mGlyphExtentsArray; + nsString mName; + nsExpirationState mExpirationState; + gfxFontStyle mStyle; + + // This is called by the default Draw() implementation above. + virtual PRBool SetupCairoFont(cairo_t *aCR) = 0; }; class THEBES_API gfxTextRunFactory { @@ -762,7 +686,6 @@ public: */ Metrics MeasureText(PRUint32 aStart, PRUint32 aLength, PRBool aTightBoundingBox, - gfxContext *aRefContextForTightBoundingBox, PropertyProvider *aProvider); /** @@ -841,8 +764,6 @@ public: * @param aMetrics if non-null, we fill this in for the returned substring. * If a hyphenation break was used, the hyphen is NOT included in the returned metrics. * @param aTightBoundingBox if true, we make the bounding box in aMetrics tight - * @param aRefContextForTightBoundingBox a reference context to get the - * tight bounding box, if aTightBoundingBox is true * @param aUsedHyphenation if non-null, records if we selected a hyphenation break * @param aLastBreak if non-null and result is aMaxLength, we set this to * the maximal N such that @@ -861,7 +782,6 @@ public: PRBool aSuppressInitialBreak, gfxFloat *aTrimWhitespace, Metrics *aMetrics, PRBool aTightBoundingBox, - gfxContext *aRefContextForTightBoundingBox, PRBool *aUsedHyphenation, PRUint32 *aLastBreak); @@ -1012,8 +932,6 @@ public: PRBool CanBreakBefore() const { return (mValue & FLAG_CAN_BREAK_BEFORE) != 0; } // Returns FLAG_CAN_BREAK_BEFORE if the setting changed, 0 otherwise PRUint32 SetCanBreakBefore(PRBool aCanBreakBefore) { - NS_ASSERTION(aCanBreakBefore == PR_FALSE || aCanBreakBefore == PR_TRUE, - "Bogus break-before value!"); PRUint32 breakMask = aCanBreakBefore*FLAG_CAN_BREAK_BEFORE; PRUint32 toggle = breakMask ^ (mValue & FLAG_CAN_BREAK_BEFORE); mValue ^= toggle; @@ -1152,8 +1070,6 @@ public: PRUint32 aNumGlyphs); void SetMissingGlyph(PRUint32 aCharIndex, PRUint32 aChar); void SetSpaceGlyph(gfxFont *aFont, gfxContext *aContext, PRUint32 aCharIndex); - - void FetchGlyphExtents(gfxContext *aRefContext); // API for access to the raw glyph data, needed by gfxFont::Draw // and gfxFont::GetBoundingBox @@ -1163,7 +1079,6 @@ public: // Missing glyphs need not have details. return mDetailedGlyphs ? mDetailedGlyphs[aCharIndex].get() : nsnull; } - PRBool HasDetailedGlyphs() { return mDetailedGlyphs.get() != nsnull; } PRUint32 CountMissingGlyphs(); const GlyphRun *GetGlyphRuns(PRUint32 *aNumGlyphRuns) { *aNumGlyphRuns = mGlyphRuns.Length(); @@ -1242,14 +1157,12 @@ private: gfxFloat GetPartialLigatureWidth(PRUint32 aStart, PRUint32 aEnd, PropertyProvider *aProvider); void AccumulatePartialLigatureMetrics(gfxFont *aFont, PRUint32 aStart, PRUint32 aEnd, PRBool aTight, - gfxContext *aRefContext, PropertyProvider *aProvider, Metrics *aMetrics); // **** measurement helper **** void AccumulateMetricsForRun(gfxFont *aFont, PRUint32 aStart, PRUint32 aEnd, PRBool aTight, - gfxContext *aRefContext, PropertyProvider *aProvider, PRUint32 aSpacingStart, PRUint32 aSpacingEnd, Metrics *aMetrics); diff --git a/gfx/thebes/public/gfxPangoFonts.h b/gfx/thebes/public/gfxPangoFonts.h index a90ff137c80..54dc20b3a88 100644 --- a/gfx/thebes/public/gfxPangoFonts.h +++ b/gfx/thebes/public/gfxPangoFonts.h @@ -111,7 +111,7 @@ protected: void GetCharSize(const char aChar, gfxSize& aInkSize, gfxSize& aLogSize, PRUint32 *aGlyphID = nsnull); - virtual PRBool SetupCairoFont(gfxContext *aContext); + virtual PRBool SetupCairoFont(cairo_t *aCR); }; class FontSelector; diff --git a/gfx/thebes/public/gfxWindowsFonts.h b/gfx/thebes/public/gfxWindowsFonts.h index cde963261c5..7cb35c76872 100644 --- a/gfx/thebes/public/gfxWindowsFonts.h +++ b/gfx/thebes/public/gfxWindowsFonts.h @@ -533,7 +533,7 @@ private: nsRefPtr mFontEntry; - virtual PRBool SetupCairoFont(gfxContext *aContext); + virtual PRBool SetupCairoFont(cairo_t *aCR); }; /********************************************************************** diff --git a/gfx/thebes/src/gfxAtsuiFonts.cpp b/gfx/thebes/src/gfxAtsuiFonts.cpp index f6de6aabef6..e9686fa54d6 100644 --- a/gfx/thebes/src/gfxAtsuiFonts.cpp +++ b/gfx/thebes/src/gfxAtsuiFonts.cpp @@ -171,8 +171,8 @@ gfxAtsuiFont::InitMetrics(ATSUFontID aFontID, ATSFontRef aFontRef) mMetrics.emHeight = size; - mMetrics.maxAscent = NS_ceil(atsMetrics.ascent * size); - mMetrics.maxDescent = NS_ceil(- (atsMetrics.descent * size)); + mMetrics.maxAscent = atsMetrics.ascent * size; + mMetrics.maxDescent = - (atsMetrics.descent * size); mMetrics.maxHeight = mMetrics.maxAscent + mMetrics.maxDescent; @@ -226,7 +226,7 @@ gfxAtsuiFont::InitMetrics(ATSUFontID aFontID, ATSFontRef aFontRef) } PRBool -gfxAtsuiFont::SetupCairoFont(gfxContext *aContext) +gfxAtsuiFont::SetupCairoFont(cairo_t *aCR) { cairo_scaled_font_t *scaledFont = CairoScaledFont(); if (cairo_scaled_font_status(scaledFont) != CAIRO_STATUS_SUCCESS) { @@ -234,7 +234,7 @@ gfxAtsuiFont::SetupCairoFont(gfxContext *aContext) // the cairo_t, precluding any further drawing. return PR_FALSE; } - cairo_set_scaled_font(aContext->GetCairo(), scaledFont); + cairo_set_scaled_font(aCR, scaledFont); return PR_TRUE; } @@ -329,35 +329,6 @@ CreateFontFallbacksFromFontList(nsTArray< nsRefPtr > *aFonts, return status == noErr ? NS_OK : NS_ERROR_FAILURE; } -void -gfxAtsuiFont::SetupGlyphExtents(gfxContext *aContext, PRUint32 aGlyphID, - PRBool aNeedTight, gfxGlyphExtents *aExtents) -{ - ATSGlyphScreenMetrics metrics; - GlyphID glyph = aGlyphID; - OSStatus err = ATSUGlyphGetScreenMetrics(mATSUStyle, 1, &glyph, 0, false, false, - &metrics); - if (err != noErr) - return; - PRUint32 appUnitsPerDevUnit = aExtents->GetAppUnitsPerDevUnit(); - - if (!aNeedTight && metrics.topLeft.x >= 0 && - -metrics.topLeft.y + metrics.height <= mMetrics.maxAscent && - metrics.topLeft.y <= mMetrics.maxDescent) { - PRUint32 appUnitsWidth = - PRUint32(NS_ceil((metrics.topLeft.x + metrics.width)*appUnitsPerDevUnit)); - if (appUnitsWidth < gfxGlyphExtents::INVALID_WIDTH) { - aExtents->SetContainedGlyphWidthAppUnits(aGlyphID, PRUint16(appUnitsWidth)); - return; - } - } - - double d2a = appUnitsPerDevUnit; - gfxRect bounds(metrics.topLeft.x*d2a, (metrics.topLeft.y - metrics.height)*d2a, - metrics.width*d2a, metrics.height*d2a); - aExtents->SetTightGlyphExtents(aGlyphID, bounds); -} - PRBool gfxAtsuiFont::HasMirroringInfo() { @@ -601,8 +572,6 @@ gfxAtsuiFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength, break; textRun->ResetGlyphRuns(); } - - textRun->FetchGlyphExtents(aParams->mContext); return textRun; } @@ -645,8 +614,6 @@ gfxAtsuiFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength, textRun->ResetGlyphRuns(); } - textRun->FetchGlyphExtents(aParams->mContext); - return textRun; } diff --git a/gfx/thebes/src/gfxFont.cpp b/gfx/thebes/src/gfxFont.cpp index 3623bcadf4f..925c94f8a59 100644 --- a/gfx/thebes/src/gfxFont.cpp +++ b/gfx/thebes/src/gfxFont.cpp @@ -162,17 +162,6 @@ gfxFont::gfxFont(const nsAString &aName, const gfxFontStyle *aFontStyle) : { } -gfxFont::~gfxFont() -{ - PRUint32 i; - // We destroy the contents of mGlyphExtentsArray explicitly instead of - // using nsAutoPtr because VC++ can't deal with nsTArrays of nsAutoPtrs - // of classes that lack a proper copy constructor - for (i = 0; i < mGlyphExtentsArray.Length(); ++i) { - delete mGlyphExtentsArray[i]; - } -} - /** * A helper function in case we need to do any rounding or other * processing here. @@ -224,13 +213,13 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd, double x = aPt->x; double y = aPt->y; - PRBool success = SetupCairoFont(aContext); + cairo_t *cr = aContext->GetCairo(); + PRBool success = SetupCairoFont(cr); if (NS_UNLIKELY(!success)) return; GlyphBuffer glyphs; cairo_glyph_t *glyph; - cairo_t *cr = aContext->GetCairo(); if (aSpacing) { x += direction*aSpacing[0].mBefore; @@ -317,222 +306,55 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd, *aPt = gfxPoint(x, y); } -static void -UnionWithXPoint(gfxRect *aRect, double aX) -{ - if (aX < aRect->pos.x) { - aRect->size.width += aRect->pos.x - aX; - aRect->pos.x = aX; - } else if (aX > aRect->XMost()) { - aRect->size.width = aX - aRect->pos.x; - } -} - -static PRBool -NeedsGlyphExtents(gfxTextRun *aTextRun) -{ - return (aTextRun->GetFlags() & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED) == 0; - // return PR_TRUE; -} - gfxFont::RunMetrics gfxFont::Measure(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd, - PRBool aTightBoundingBox, gfxContext *aRefContext, + PRBool aTightBoundingBox, Spacing *aSpacing) { + // XXX temporary code, does not handle glyphs outside the font-box + // XXX comment out the assertion for now since it fires too much + // NS_ASSERTION(!(aTextRun->GetFlags() & gfxTextRunFactory::TEXT_NEED_BOUNDING_BOX), + // "Glyph extents not yet supported"); + PRInt32 advance = 0; + PRUint32 i; const gfxTextRun::CompressedGlyph *charGlyphs = aTextRun->GetCharacterGlyphs(); - const PRUint32 appUnitsPerDevUnit = aTextRun->GetAppUnitsPerDevUnit(); - PRBool isRTL = aTextRun->IsRightToLeft(); - double direction = aTextRun->GetDirection(); - // Current position in appunits - const gfxFont::Metrics& fontMetrics = GetMetrics(); - - RunMetrics metrics; - metrics.mAscent = fontMetrics.maxAscent*appUnitsPerDevUnit; - metrics.mDescent = fontMetrics.maxDescent*appUnitsPerDevUnit; - metrics.mAdvanceWidth = 0; - if (aTightBoundingBox) { - metrics.mBoundingBox = gfxRect(0, 0, 0, 0); - } else { - metrics.mBoundingBox = gfxRect(0, -metrics.mAscent, 0, metrics.mAscent + metrics.mDescent); - } - - gfxGlyphExtents *extents = - (!aTightBoundingBox && !NeedsGlyphExtents(aTextRun) && !aTextRun->HasDetailedGlyphs()) ? nsnull - : GetOrCreateGlyphExtents(aTextRun->GetAppUnitsPerDevUnit()); - double x = 0; - if (aSpacing) { - x += direction*aSpacing[0].mBefore; - } - PRUint32 i; for (i = aStart; i < aEnd; ++i) { - const gfxTextRun::CompressedGlyph *glyphData = &charGlyphs[i]; - if (glyphData->IsSimpleGlyph()) { - double advance = glyphData->GetSimpleAdvance(); - // Only get the real glyph horizontal extent if we were asked - // for the tight bounding box or we're in quality mode - if (aTightBoundingBox || NeedsGlyphExtents(aTextRun)) { - PRUint32 glyphIndex = glyphData->GetSimpleGlyph(); - PRUint16 extentsWidth = extents->GetContainedGlyphWidthAppUnits(glyphIndex); - if (extentsWidth != gfxGlyphExtents::INVALID_WIDTH && !aTightBoundingBox) { - UnionWithXPoint(&metrics.mBoundingBox, x + direction*extentsWidth); - } else { - gfxRect glyphRect = - extents->GetTightGlyphExtentsAppUnits(this, aRefContext, glyphIndex); - if (isRTL) { - glyphRect.pos.x -= advance; - } - glyphRect.pos.x += x; - metrics.mBoundingBox = metrics.mBoundingBox.Union(glyphRect); + gfxTextRun::CompressedGlyph g = charGlyphs[i]; + if (g.IsClusterStart()) { + if (g.IsSimpleGlyph()) { + advance += charGlyphs[i].GetSimpleAdvance(); + } else if (g.IsComplexOrMissing()) { + const gfxTextRun::DetailedGlyph *details = aTextRun->GetDetailedGlyphs(i); + while (details) { + advance += details->mAdvance; + if (details->mIsLastGlyph) + break; + ++details; } } - x += direction*advance; - } else if (glyphData->IsComplexCluster()) { - const gfxTextRun::DetailedGlyph *details = aTextRun->GetDetailedGlyphs(i); - for (;;) { - PRUint32 glyphIndex = details->mGlyphID; - gfxPoint glyphPt(x + details->mXOffset, details->mYOffset); - double advance = details->mAdvance; - gfxRect glyphRect = - extents->GetTightGlyphExtentsAppUnits(this, aRefContext, glyphIndex); - if (isRTL) { - glyphRect.pos.x -= advance; - } - glyphRect.pos.x += x; - metrics.mBoundingBox = metrics.mBoundingBox.Union(glyphRect); - x += direction*advance; - if (details->mIsLastGlyph) - break; - ++details; - } - } else if (glyphData->IsMissing()) { - const gfxTextRun::DetailedGlyph *details = aTextRun->GetDetailedGlyphs(i); - if (details) { - double advance = details->mAdvance; - gfxRect glyphRect(x, -metrics.mAscent, advance, metrics.mAscent); - if (isRTL) { - glyphRect.pos.x -= advance; - } - metrics.mBoundingBox = metrics.mBoundingBox.Union(glyphRect); - x += direction*advance; - } - } - // Every other glyph type is ignored - if (aSpacing) { - double space = aSpacing[i - aStart].mAfter; - if (i + 1 < aEnd) { - space += aSpacing[i + 1 - aStart].mBefore; - } - x += direction*space; } } - if (!aTightBoundingBox) { - // Make sure the non-tight bounding box includes the entire advance - UnionWithXPoint(&metrics.mBoundingBox, x); + gfxFloat floatAdvance = advance; + if (aSpacing) { + for (i = 0; i < aEnd - aStart; ++i) { + floatAdvance += aSpacing[i].mBefore + aSpacing[i].mAfter; + } } - if (isRTL) { - metrics.mBoundingBox.pos.x -= x; - } - - metrics.mAdvanceWidth = x*direction; + RunMetrics metrics; + const gfxFont::Metrics& fontMetrics = GetMetrics(); + metrics.mAdvanceWidth = floatAdvance; + const PRUint32 appUnitsPerDevUnit = aTextRun->GetAppUnitsPerDevUnit(); + metrics.mAscent = fontMetrics.maxAscent*appUnitsPerDevUnit; + gfxFloat descentForUnderline = + NS_round(fontMetrics.underlineSize) + NS_round(metrics.mAscent - fontMetrics.underlineOffset) - metrics.mAscent; + metrics.mDescent = PR_MAX(fontMetrics.maxDescent, descentForUnderline)*appUnitsPerDevUnit; + metrics.mBoundingBox = + gfxRect(0, -metrics.mAscent, floatAdvance, metrics.mAscent + metrics.mDescent); return metrics; } -gfxGlyphExtents * -gfxFont::GetOrCreateGlyphExtents(PRUint32 aAppUnitsPerDevUnit) { - PRUint32 i; - for (i = 0; i < mGlyphExtentsArray.Length(); ++i) { - if (mGlyphExtentsArray[i]->GetAppUnitsPerDevUnit() == aAppUnitsPerDevUnit) - return mGlyphExtentsArray[i]; - } - gfxGlyphExtents *glyphExtents = new gfxGlyphExtents(aAppUnitsPerDevUnit); - if (glyphExtents) { - mGlyphExtentsArray.AppendElement(glyphExtents); - // Initialize the extents of a space glyph, assuming that spaces don't - // render anything! - glyphExtents->SetContainedGlyphWidthAppUnits(GetSpaceGlyph(), 0); - } - return glyphExtents; -} - -void -gfxFont::SetupGlyphExtents(gfxContext *aContext, PRUint32 aGlyphID, PRBool aNeedTight, - gfxGlyphExtents *aExtents) -{ - cairo_glyph_t glyph; - glyph.index = aGlyphID; - glyph.x = 0; - glyph.y = 0; - cairo_text_extents_t extents; - cairo_glyph_extents(aContext->GetCairo(), &glyph, 1, &extents); - - const Metrics& fontMetrics = GetMetrics(); - PRUint32 appUnitsPerDevUnit = aExtents->GetAppUnitsPerDevUnit(); - if (!aNeedTight && extents.x_bearing >= 0 && - extents.y_bearing >= -fontMetrics.maxAscent && - extents.height + extents.y_bearing <= fontMetrics.maxDescent) { - PRUint32 appUnitsWidth = - PRUint32(NS_ceil((extents.x_bearing + extents.width)*appUnitsPerDevUnit)); - if (appUnitsWidth < gfxGlyphExtents::INVALID_WIDTH) { - aExtents->SetContainedGlyphWidthAppUnits(aGlyphID, PRUint16(appUnitsWidth)); - return; - } - } - - double d2a = appUnitsPerDevUnit; - gfxRect bounds(extents.x_bearing*d2a, extents.y_bearing*d2a, - extents.width*d2a, extents.height*d2a); - aExtents->SetTightGlyphExtents(aGlyphID, bounds); -} - -gfxRect -gfxGlyphExtents::GetTightGlyphExtentsAppUnits(gfxFont *aFont, - gfxContext *aContext, PRUint32 aGlyphID) -{ - HashEntry *entry = mTightGlyphExtents.GetEntry(aGlyphID); - if (!entry) { - aFont->SetupCairoFont(aContext); - aFont->SetupGlyphExtents(aContext, aGlyphID, PR_TRUE, this); - entry = mTightGlyphExtents.GetEntry(aGlyphID); - if (!entry) { - NS_WARNING("Could not get glyph extents"); - return gfxRect(0,0,0,0); - } - } - - return gfxRect(entry->x, entry->y, entry->width, entry->height); -} - -void -gfxGlyphExtents::SetContainedGlyphWidthAppUnits(PRUint32 aGlyphID, PRUint16 aWidth) -{ - PRUint32 len = mWidthsForContainedGlyphsAppUnits.Length(); - if (aGlyphID >= len) { - PRUint16 *elems = mWidthsForContainedGlyphsAppUnits.AppendElements(aGlyphID + 1 - len); - if (!elems) - return; - PRUint32 i; - for (i = len; i < aGlyphID; ++i) { - mWidthsForContainedGlyphsAppUnits[i] = INVALID_WIDTH; - } - } - mWidthsForContainedGlyphsAppUnits[aGlyphID] = aWidth; -} - -void -gfxGlyphExtents::SetTightGlyphExtents(PRUint32 aGlyphID, const gfxRect& aExtentsAppUnits) -{ - HashEntry *entry = mTightGlyphExtents.PutEntry(aGlyphID); - if (!entry) - return; - entry->x = aExtentsAppUnits.pos.x; - entry->y = aExtentsAppUnits.pos.y; - entry->width = aExtentsAppUnits.size.width; - entry->height = aExtentsAppUnits.size.height; -} - gfxFontGroup::gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle) : mFamilies(aFamilies), mStyle(*aStyle) { @@ -757,9 +579,6 @@ gfxFontGroup::MakeSpaceTextRun(const Parameters *aParams, PRUint32 aFlags) gfxFont *font = GetFontAt(0); textRun->SetSpaceGlyph(font, aParams->mContext, 0); - // Note that the gfxGlyphExtents glyph bounds storage for the font will - // always contain an entry for the font's space glyph, so we don't have - // to call FetchGlyphExtents here. return textRun.forget(); } @@ -1284,15 +1103,14 @@ gfxTextRun::DrawToPath(gfxContext *aContext, gfxPoint aPt, void gfxTextRun::AccumulateMetricsForRun(gfxFont *aFont, PRUint32 aStart, PRUint32 aEnd, - PRBool aTight, gfxContext *aRefContext, - PropertyProvider *aProvider, + PRBool aTight, PropertyProvider *aProvider, PRUint32 aSpacingStart, PRUint32 aSpacingEnd, Metrics *aMetrics) { nsAutoTArray spacingBuffer; PRBool haveSpacing = GetAdjustedSpacingArray(aStart, aEnd, aProvider, aSpacingStart, aSpacingEnd, &spacingBuffer); - Metrics metrics = aFont->Measure(this, aStart, aEnd, aTight, aRefContext, + Metrics metrics = aFont->Measure(this, aStart, aEnd, aTight, haveSpacing ? spacingBuffer.Elements() : nsnull); if (IsRightToLeft()) { @@ -1305,7 +1123,7 @@ gfxTextRun::AccumulateMetricsForRun(gfxFont *aFont, void gfxTextRun::AccumulatePartialLigatureMetrics(gfxFont *aFont, - PRUint32 aStart, PRUint32 aEnd, PRBool aTight, gfxContext *aRefContext, + PRUint32 aStart, PRUint32 aEnd, PRBool aTight, PropertyProvider *aProvider, Metrics *aMetrics) { if (aStart >= aEnd) @@ -1318,7 +1136,7 @@ gfxTextRun::AccumulatePartialLigatureMetrics(gfxFont *aFont, // First measure the complete ligature Metrics metrics; AccumulateMetricsForRun(aFont, data.mLigatureStart, data.mLigatureEnd, - aTight, aRefContext, aProvider, aStart, aEnd, &metrics); + aTight, aProvider, aStart, aEnd, &metrics); // Clip the bounding box to the ligature part gfxFloat bboxLeft = metrics.mBoundingBox.X(); @@ -1346,7 +1164,7 @@ gfxTextRun::AccumulatePartialLigatureMetrics(gfxFont *aFont, gfxTextRun::Metrics gfxTextRun::MeasureText(PRUint32 aStart, PRUint32 aLength, - PRBool aTightBoundingBox, gfxContext *aRefContext, + PRBool aTightBoundingBox, PropertyProvider *aProvider) { NS_ASSERTION(aStart + aLength <= mCharacterCount, "Substring out of range"); @@ -1362,7 +1180,7 @@ gfxTextRun::MeasureText(PRUint32 aStart, PRUint32 aLength, ShrinkToLigatureBoundaries(&ligatureRunStart, &ligatureRunEnd); AccumulatePartialLigatureMetrics(font, start, ligatureRunStart, - aTightBoundingBox, aRefContext, aProvider, &accumulatedMetrics); + aTightBoundingBox, aProvider, &accumulatedMetrics); // XXX This sucks. We have to get glyph extents just so we can detect // glyphs outside the font box, even when aTightBoundingBox is false, @@ -1370,12 +1188,12 @@ gfxTextRun::MeasureText(PRUint32 aStart, PRUint32 aLength, // by getting some ascent/descent from the font and using our stored // advance widths. AccumulateMetricsForRun(font, - ligatureRunStart, ligatureRunEnd, aTightBoundingBox, - aRefContext, aProvider, ligatureRunStart, ligatureRunEnd, + ligatureRunStart, ligatureRunEnd, aTightBoundingBox, aProvider, + ligatureRunStart, ligatureRunEnd, &accumulatedMetrics); AccumulatePartialLigatureMetrics(font, ligatureRunEnd, end, - aTightBoundingBox, aRefContext, aProvider, &accumulatedMetrics); + aTightBoundingBox, aProvider, &accumulatedMetrics); } return accumulatedMetrics; @@ -1390,7 +1208,6 @@ gfxTextRun::BreakAndMeasureText(PRUint32 aStart, PRUint32 aMaxLength, PRBool aSuppressInitialBreak, gfxFloat *aTrimWhitespace, Metrics *aMetrics, PRBool aTightBoundingBox, - gfxContext *aRefContext, PRBool *aUsedHyphenation, PRUint32 *aLastBreak) { @@ -1532,8 +1349,7 @@ gfxTextRun::BreakAndMeasureText(PRUint32 aStart, PRUint32 aMaxLength, } if (aMetrics) { - *aMetrics = MeasureText(aStart, charsFit - trimmableChars, - aTightBoundingBox, aRefContext, aProvider); + *aMetrics = MeasureText(aStart, charsFit - trimmableChars, aTightBoundingBox, aProvider); } if (aTrimWhitespace) { *aTrimWhitespace = trimmableAdvance; @@ -1902,55 +1718,3 @@ gfxTextRun::SetSpaceGlyph(gfxFont *aFont, gfxContext *aContext, PRUint32 aCharIn g.SetSimpleGlyph(spaceWidthAppUnits, spaceGlyph); SetCharacterGlyph(aCharIndex, g); } - -void -gfxTextRun::FetchGlyphExtents(gfxContext *aRefContext) -{ - if (!NeedsGlyphExtents(this) && !mDetailedGlyphs) - return; - - PRUint32 i; - CompressedGlyph *charGlyphs = mCharacterGlyphs; - for (i = 0; i < mGlyphRuns.Length(); ++i) { - gfxFont *font = mGlyphRuns[i].mFont; - PRUint32 start = mGlyphRuns[i].mCharacterOffset; - PRUint32 end = i + 1 < mGlyphRuns.Length() - ? mGlyphRuns[i + 1].mCharacterOffset : GetLength(); - PRBool fontIsSetup = PR_FALSE; - PRUint32 j; - gfxGlyphExtents *extents = font->GetOrCreateGlyphExtents(mAppUnitsPerDevUnit); - - for (j = start; j < end; ++j) { - const gfxTextRun::CompressedGlyph *glyphData = &charGlyphs[j]; - if (glyphData->IsSimpleGlyph()) { - // If we're in speed mode, don't set up glyph extents here; we'll - // just return "optimistic" glyph bounds later - if (NeedsGlyphExtents(this)) { - PRUint32 glyphIndex = glyphData->GetSimpleGlyph(); - if (!extents->IsGlyphKnown(glyphIndex)) { - if (!fontIsSetup) { - font->SetupCairoFont(aRefContext); - fontIsSetup = PR_TRUE; - } - font->SetupGlyphExtents(aRefContext, glyphIndex, PR_FALSE, extents); - } - } - } else if (glyphData->IsComplexCluster()) { - const gfxTextRun::DetailedGlyph *details = GetDetailedGlyphs(j); - for (;;) { - PRUint32 glyphIndex = details->mGlyphID; - if (!extents->IsGlyphKnownWithTightExtents(glyphIndex)) { - if (!fontIsSetup) { - font->SetupCairoFont(aRefContext); - fontIsSetup = PR_TRUE; - } - font->SetupGlyphExtents(aRefContext, glyphIndex, PR_TRUE, extents); - } - if (details->mIsLastGlyph) - break; - ++details; - } - } - } - } -} diff --git a/gfx/thebes/src/gfxPangoFonts.cpp b/gfx/thebes/src/gfxPangoFonts.cpp index 1696cd1b644..e7f347611df 100644 --- a/gfx/thebes/src/gfxPangoFonts.cpp +++ b/gfx/thebes/src/gfxPangoFonts.cpp @@ -828,7 +828,6 @@ gfxPangoFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength, AppendUTF16toUTF8(unicodeString, utf8); InitTextRun(run, utf8.get(), utf8.Length(), headerLen, PR_TRUE); } - run->FetchGlyphExtents(aParams->mContext); return run; } @@ -867,7 +866,6 @@ gfxPangoFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength, } #endif InitTextRun(run, utf8.get(), utf8.Length(), headerLen, is8Bit); - run->FetchGlyphExtents(aParams->mContext); return run; } @@ -918,11 +916,10 @@ CreateScaledFont(cairo_t *aCR, cairo_matrix_t *aCTM, PangoFont *aPangoFont) } PRBool -gfxPangoFont::SetupCairoFont(gfxContext *aContext) +gfxPangoFont::SetupCairoFont(cairo_t *aCR) { - cairo_t *cr = aContext->GetCairo(); cairo_matrix_t currentCTM; - cairo_get_matrix(cr, ¤tCTM); + cairo_get_matrix(aCR, ¤tCTM); if (mCairoFont) { // Need to validate that its CTM is OK @@ -936,14 +933,14 @@ gfxPangoFont::SetupCairoFont(gfxContext *aContext) } } if (!mCairoFont) { - mCairoFont = CreateScaledFont(cr, ¤tCTM, GetPangoFont()); + mCairoFont = CreateScaledFont(aCR, ¤tCTM, GetPangoFont()); } if (cairo_scaled_font_status(mCairoFont) != CAIRO_STATUS_SUCCESS) { // Don't cairo_set_scaled_font as that would propagate the error to // the cairo_t, precluding any further drawing. return PR_FALSE; } - cairo_set_scaled_font(cr, mCairoFont); + cairo_set_scaled_font(aCR, mCairoFont); return PR_TRUE; } diff --git a/gfx/thebes/src/gfxWindowsFonts.cpp b/gfx/thebes/src/gfxWindowsFonts.cpp index 69d811a1907..4e7d5bcf5aa 100644 --- a/gfx/thebes/src/gfxWindowsFonts.cpp +++ b/gfx/thebes/src/gfxWindowsFonts.cpp @@ -434,7 +434,7 @@ gfxWindowsFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd, } PRBool -gfxWindowsFont::SetupCairoFont(gfxContext *aContext) +gfxWindowsFont::SetupCairoFont(cairo_t *aCR) { cairo_scaled_font_t *scaledFont = CairoScaledFont(); if (cairo_scaled_font_status(scaledFont) != CAIRO_STATUS_SUCCESS) { @@ -442,7 +442,7 @@ gfxWindowsFont::SetupCairoFont(gfxContext *aContext) // the cairo_t, precluding any further drawing. return PR_FALSE; } - cairo_set_scaled_font(aContext->GetCairo(), scaledFont); + cairo_set_scaled_font(aCR, scaledFont); return PR_TRUE; } @@ -566,8 +566,6 @@ gfxWindowsFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength, else InitTextRunGDI(aParams->mContext, textRun, aString, aLength); - textRun->FetchGlyphExtents(aParams->mContext); - return textRun; } @@ -607,8 +605,6 @@ gfxWindowsFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength, } } - textRun->FetchGlyphExtents(aParams->mContext); - return textRun; } diff --git a/layout/generic/nsBRFrame.cpp b/layout/generic/nsBRFrame.cpp index e4deda3af2c..5c819cbd48f 100644 --- a/layout/generic/nsBRFrame.cpp +++ b/layout/generic/nsBRFrame.cpp @@ -184,8 +184,6 @@ BRFrame::Reflow(nsPresContext* aPresContext, else { aStatus = NS_FRAME_COMPLETE; } - - aMetrics.mOverflowArea = nsRect(0, 0, aMetrics.width, aMetrics.height); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics); return NS_OK; diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index fda6b7d66f9..ffe043488df 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -65,7 +65,6 @@ #include "nsTextFragment.h" #include "nsBidiUtils.h" #include "nsLayoutUtils.h" -#include "nsTextFrame.h" #ifdef DEBUG #undef NOISY_HORIZONTAL_ALIGN @@ -2421,10 +2420,6 @@ nsLineLayout::ApplyFrameJustification(PerSpanData* aPSD, FrameJustificationState aState->mWidthForLettersProcessed = newAllocatedWidthForLetters; } - - if (dw) { - pfd->SetFlag(PFD_RECOMPUTEOVERFLOW, PR_TRUE); - } } else { if (nsnull != pfd->mSpan) { @@ -2648,12 +2643,11 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea) // aggregating it into our combined area. RelativePositionFrames(pfd->mSpan, r); } else { - r = pfd->mCombinedArea; - if (pfd->GetFlag(PFD_RECOMPUTEOVERFLOW)) { - nsTextFrame* f = static_cast(frame); - r = f->RecomputeOverflowRect(); - } - frame->FinishAndStoreOverflow(&r, frame->GetSize()); + // For simple text frames we take the union of the combined area + // and the width/height. I think the combined area should always + // equal the bounds in this case, but this is safe. + nsRect adjustedBounds(0, 0, pfd->mBounds.width, pfd->mBounds.height); + r.UnionRect(pfd->mCombinedArea, adjustedBounds); // If we have something that's not an inline but with a complex frame // hierarchy inside that contains views, they need to be diff --git a/layout/generic/nsLineLayout.h b/layout/generic/nsLineLayout.h index 649f794d39c..0b9684833e5 100644 --- a/layout/generic/nsLineLayout.h +++ b/layout/generic/nsLineLayout.h @@ -502,7 +502,6 @@ protected: #define PFD_ISNONEMPTYTEXTFRAME 0x00000004 #define PFD_ISNONWHITESPACETEXTFRAME 0x00000008 #define PFD_ISLETTERFRAME 0x00000010 -#define PFD_RECOMPUTEOVERFLOW 0x00000020 #define PFD_ISBULLET 0x00000040 #define PFD_SKIPWHENTRIMMINGWHITESPACE 0x00000080 #define PFD_LASTFLAG PFD_SKIPWHENTRIMMINGWHITESPACE diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h deleted file mode 100644 index d7fe59e8ba2..00000000000 --- a/layout/generic/nsTextFrame.h +++ /dev/null @@ -1,346 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Robert O'Callahan - * Roger B. Sidje - * Pierre Phaneuf - * Prabhat Hegde - * Tomi Leppikangas - * Roland Mainz - * Daniel Glazman - * Neil Deakin - * Masayuki Nakano - * Mats Palmgren - * Uri Bernstein - * Stephen Blackheath - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsTextFrame_h__ -#define nsTextFrame_h__ - -#include "nsFrame.h" -#include "nsLineBox.h" -#include "gfxFont.h" -#include "gfxSkipChars.h" - -class nsTextPaintStyle; -class PropertyProvider; - -class nsTextFrame : public nsFrame { -public: - nsTextFrame(nsStyleContext* aContext) : nsFrame(aContext) - { - NS_ASSERTION(mContentOffset == 0, "Bogus content offset"); - } - - // nsIFrame - NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder, - const nsRect& aDirtyRect, - const nsDisplayListSet& aLists); - - NS_IMETHOD Init(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame* aPrevInFlow); - - virtual void Destroy(); - - NS_IMETHOD GetCursor(const nsPoint& aPoint, - nsIFrame::Cursor& aCursor); - - NS_IMETHOD CharacterDataChanged(nsPresContext* aPresContext, - nsIContent* aChild, - PRBool aAppend); - - NS_IMETHOD DidSetStyleContext(); - - virtual nsIFrame* GetNextContinuation() const { - return mNextContinuation; - } - NS_IMETHOD SetNextContinuation(nsIFrame* aNextContinuation) { - NS_ASSERTION (!aNextContinuation || GetType() == aNextContinuation->GetType(), - "setting a next continuation with incorrect type!"); - NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextContinuation, this), - "creating a loop in continuation chain!"); - mNextContinuation = aNextContinuation; - if (aNextContinuation) - aNextContinuation->RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION); - return NS_OK; - } - virtual nsIFrame* GetNextInFlowVirtual() const { return GetNextInFlow(); } - nsIFrame* GetNextInFlow() const { - return mNextContinuation && (mNextContinuation->GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? - mNextContinuation : nsnull; - } - NS_IMETHOD SetNextInFlow(nsIFrame* aNextInFlow) { - NS_ASSERTION (!aNextInFlow || GetType() == aNextInFlow->GetType(), - "setting a next in flow with incorrect type!"); - NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextInFlow, this), - "creating a loop in continuation chain!"); - mNextContinuation = aNextInFlow; - if (aNextInFlow) - aNextInFlow->AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION); - return NS_OK; - } - virtual nsIFrame* GetLastInFlow() const; - virtual nsIFrame* GetLastContinuation() const; - - virtual nsSplittableType GetSplittableType() const { - return NS_FRAME_SPLITTABLE; - } - - /** - * Get the "type" of the frame - * - * @see nsGkAtoms::textFrame - */ - virtual nsIAtom* GetType() const; - - virtual PRBool IsFrameOfType(PRUint32 aFlags) const - { - // Set the frame state bit for text frames to mark them as replaced. - // XXX kipp: temporary - return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced | - nsIFrame::eLineParticipant)); - } - -#ifdef DEBUG - NS_IMETHOD List(FILE* out, PRInt32 aIndent) const; - NS_IMETHOD GetFrameName(nsAString& aResult) const; - NS_IMETHOD_(nsFrameState) GetDebugStateBits() const ; -#endif - - virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint); - - NS_IMETHOD SetSelected(nsPresContext* aPresContext, - nsIDOMRange *aRange, - PRBool aSelected, - nsSpread aSpread); - - virtual PRBool PeekOffsetNoAmount(PRBool aForward, PRInt32* aOffset); - virtual PRBool PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset); - virtual PRBool PeekOffsetWord(PRBool aForward, PRBool aWordSelectEatSpace, PRBool aIsKeyboardSelect, - PRInt32* aOffset, PeekWordState* aState); - - NS_IMETHOD CheckVisibility(nsPresContext* aContext, PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aRecurse, PRBool *aFinished, PRBool *_retval); - - // Update offsets to account for new length. This may clear mTextRun. - void SetLength(PRInt32 aLength); - - NS_IMETHOD GetOffsets(PRInt32 &start, PRInt32 &end)const; - - virtual void AdjustOffsetsForBidi(PRInt32 start, PRInt32 end); - - NS_IMETHOD GetPointFromOffset(PRInt32 inOffset, - nsPoint* outPoint); - - NS_IMETHOD GetChildFrameContainingOffset(PRInt32 inContentOffset, - PRBool inHint, - PRInt32* outFrameContentOffset, - nsIFrame* *outChildFrame); - - virtual PRBool IsVisibleInSelection(nsISelection* aSelection); - - virtual PRBool IsEmpty(); - virtual PRBool IsSelfEmpty() { return IsEmpty(); } - - /** - * @return PR_TRUE if this text frame ends with a newline character. It - * should return PR_FALSE if this is not a text frame. - */ - virtual PRBool HasTerminalNewline() const; - -#ifdef ACCESSIBILITY - NS_IMETHOD GetAccessible(nsIAccessible** aAccessible); -#endif - - virtual void MarkIntrinsicWidthsDirty(); - virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext); - virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext); - virtual void AddInlineMinWidth(nsIRenderingContext *aRenderingContext, - InlineMinWidthData *aData); - virtual void AddInlinePrefWidth(nsIRenderingContext *aRenderingContext, - InlinePrefWidthData *aData); - virtual nsSize ComputeSize(nsIRenderingContext *aRenderingContext, - nsSize aCBSize, nscoord aAvailableWidth, - nsSize aMargin, nsSize aBorder, nsSize aPadding, - PRBool aShrinkWrap); - NS_IMETHOD Reflow(nsPresContext* aPresContext, - nsHTMLReflowMetrics& aMetrics, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); - virtual PRBool CanContinueTextRun() const; - NS_IMETHOD TrimTrailingWhiteSpace(nsPresContext* aPresContext, - nsIRenderingContext& aRC, - nscoord& aDeltaWidth, - PRBool& aLastCharIsJustifiable); - virtual nsresult GetRenderedText(nsAString* aString = nsnull, - gfxSkipChars* aSkipChars = nsnull, - gfxSkipCharsIterator* aSkipIter = nsnull, - PRUint32 aSkippedStartOffset = 0, - PRUint32 aSkippedMaxLength = PR_UINT32_MAX); - - nsRect RecomputeOverflowRect(); - - void AddInlineMinWidthForFlow(nsIRenderingContext *aRenderingContext, - nsIFrame::InlineMinWidthData *aData); - void AddInlinePrefWidthForFlow(nsIRenderingContext *aRenderingContext, - InlinePrefWidthData *aData); - - gfxFloat GetSnappedBaselineY(gfxContext* aContext, gfxFloat aY); - - // primary frame paint method called from nsDisplayText - void PaintText(nsIRenderingContext* aRenderingContext, nsPoint aPt, - const nsRect& aDirtyRect); - // helper: paint quirks-mode CSS text decorations - void PaintTextDecorations(gfxContext* aCtx, const gfxRect& aDirtyRect, - const gfxPoint& aFramePt, - const gfxPoint& aTextBaselinePt, - nsTextPaintStyle& aTextStyle, - PropertyProvider& aProvider); - // helper: paint text frame when we're impacted by at least one selection. - // Return PR_FALSE if the text was not painted and we should continue with - // the fast path. - PRBool PaintTextWithSelection(gfxContext* aCtx, - const gfxPoint& aFramePt, - const gfxPoint& aTextBaselinePt, - const gfxRect& aDirtyRect, - PropertyProvider& aProvider, - nsTextPaintStyle& aTextPaintStyle); - // helper: paint text with foreground and background colors determined - // by selection(s). Also computes a mask of all selection types applying to - // our text, returned in aAllTypes. - void PaintTextWithSelectionColors(gfxContext* aCtx, - const gfxPoint& aFramePt, - const gfxPoint& aTextBaselinePt, - const gfxRect& aDirtyRect, - PropertyProvider& aProvider, - nsTextPaintStyle& aTextPaintStyle, - SelectionDetails* aDetails, - SelectionType* aAllTypes); - // helper: paint text decorations for text selected by aSelectionType - void PaintTextSelectionDecorations(gfxContext* aCtx, - const gfxPoint& aFramePt, - const gfxPoint& aTextBaselinePt, - const gfxRect& aDirtyRect, - PropertyProvider& aProvider, - nsTextPaintStyle& aTextPaintStyle, - SelectionDetails* aDetails, - SelectionType aSelectionType); - - PRInt16 GetSelectionStatus(PRInt16* aSelectionFlags); - -#ifdef DEBUG - void ToCString(nsString& aBuf, PRInt32* aTotalContentLength) const; -#endif - - PRInt32 GetContentOffset() const { return mContentOffset; } - PRInt32 GetContentLength() const { return GetContentEnd() - mContentOffset; } - PRInt32 GetContentEnd() const; - // This returns the length the frame thinks it *should* have after it was - // last reflowed (0 if it hasn't been reflowed yet). This should be used only - // when setting up the text offsets for a new continuation frame. - PRInt32 GetContentLengthHint() const { return mContentLengthHint; } - - // Compute the length of the content mapped by this frame - // and all its in-flow siblings. Basically this means starting at mContentOffset - // and going to the end of the text node or the next bidi continuation - // boundary. - PRInt32 GetInFlowContentLength(); - - // Clears out mTextRun from this frame and all other frames that hold a reference - // to it, then deletes the textrun. - void ClearTextRun(); - /** - * Acquires the text run for this content, if necessary. - * @param aRC the rendering context to use as a reference for creating - * the textrun, if available (if not, we'll create one which will just be slower) - * @param aBlock the block ancestor for this frame, or nsnull if unknown - * @param aLine the line that this frame is on, if any, or nsnull if unknown - * @param aFlowEndInTextRun if non-null, this returns the textrun offset of - * end of the text associated with this frame and its in-flow siblings - * @return a gfxSkipCharsIterator set up to map DOM offsets for this frame - * to offsets into the textrun; its initial offset is set to this frame's - * content offset - */ - gfxSkipCharsIterator EnsureTextRun(nsIRenderingContext* aRC = nsnull, - nsIFrame* aLineContainer = nsnull, - const nsLineList::iterator* aLine = nsnull, - PRUint32* aFlowEndInTextRun = nsnull); - - gfxTextRun* GetTextRun() { return mTextRun; } - void SetTextRun(gfxTextRun* aTextRun) { mTextRun = aTextRun; } - - // Get the DOM content range mapped by this frame after excluding - // whitespace subject to start-of-line and end-of-line trimming. - // The textrun must have been created before calling this. - struct TrimmedOffsets { - PRInt32 mStart; - PRInt32 mLength; - PRInt32 GetEnd() { return mStart + mLength; } - }; - TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag, - PRBool aTrimAfter); - -protected: - virtual ~nsTextFrame(); - - nsIFrame* mNextContinuation; - // The key invariant here is that mContentOffset never decreases along - // a next-continuation chain. And of course mContentOffset is always <= the - // the text node's content length, and the mContentOffset for the first frame - // is always 0. Furthermore the text mapped by a frame is determined by - // GetContentOffset() and GetContentLength()/GetContentEnd(), which get - // the length from the difference between this frame's offset and the next - // frame's offset, or the text length if there is no next frame. This means - // the frames always map the text node without overlapping or leaving any gaps. - PRInt32 mContentOffset; - // This does *not* indicate the length of text currently mapped by the frame; - // instead it's a hint saying that this frame *wants* to map this much text - // so if we create a new continuation, this is where that continuation should - // start. - PRInt32 mContentLengthHint; - nscoord mAscent; - gfxTextRun* mTextRun; - - SelectionDetails* GetSelectionDetails(); - - void AdjustSelectionPointsForBidi(SelectionDetails *sdptr, - PRInt32 textLength, - PRBool isRTLChars, - PRBool isOddLevel, - PRBool isBidiSystem); -}; - -#endif diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 8293e1433f4..237d8b44544 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -81,7 +81,6 @@ #include "nsFrameManager.h" #include "nsTextFrameTextRunCache.h" #include "nsExpirationTracker.h" -#include "nsTextFrame.h" #include "nsICaseConversion.h" #include "nsIUGenCategory.h" #include "nsUnicharUtilCIID.h" @@ -183,6 +182,9 @@ * Kit­ty */ +class nsTextFrame; +class PropertyProvider; + /** * We use an array of these objects to record which text frames * are associated with the textrun. mStartFrame is the start of a list of @@ -293,6 +295,289 @@ protected: nscolor aBackColor); }; +class nsTextFrame : public nsFrame { +public: + nsTextFrame(nsStyleContext* aContext) : nsFrame(aContext) + { + NS_ASSERTION(mContentOffset == 0, "Bogus content offset"); + } + + // nsIFrame + NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder, + const nsRect& aDirtyRect, + const nsDisplayListSet& aLists); + + NS_IMETHOD Init(nsIContent* aContent, + nsIFrame* aParent, + nsIFrame* aPrevInFlow); + + virtual void Destroy(); + + NS_IMETHOD GetCursor(const nsPoint& aPoint, + nsIFrame::Cursor& aCursor); + + NS_IMETHOD CharacterDataChanged(nsPresContext* aPresContext, + nsIContent* aChild, + PRBool aAppend); + + NS_IMETHOD DidSetStyleContext(); + + virtual nsIFrame* GetNextContinuation() const { + return mNextContinuation; + } + NS_IMETHOD SetNextContinuation(nsIFrame* aNextContinuation) { + NS_ASSERTION (!aNextContinuation || GetType() == aNextContinuation->GetType(), + "setting a next continuation with incorrect type!"); + NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextContinuation, this), + "creating a loop in continuation chain!"); + mNextContinuation = aNextContinuation; + if (aNextContinuation) + aNextContinuation->RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION); + return NS_OK; + } + virtual nsIFrame* GetNextInFlowVirtual() const { return GetNextInFlow(); } + nsIFrame* GetNextInFlow() const { + return mNextContinuation && (mNextContinuation->GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? + mNextContinuation : nsnull; + } + NS_IMETHOD SetNextInFlow(nsIFrame* aNextInFlow) { + NS_ASSERTION (!aNextInFlow || GetType() == aNextInFlow->GetType(), + "setting a next in flow with incorrect type!"); + NS_ASSERTION (!nsSplittableFrame::IsInNextContinuationChain(aNextInFlow, this), + "creating a loop in continuation chain!"); + mNextContinuation = aNextInFlow; + if (aNextInFlow) + aNextInFlow->AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION); + return NS_OK; + } + virtual nsIFrame* GetLastInFlow() const; + virtual nsIFrame* GetLastContinuation() const; + + virtual nsSplittableType GetSplittableType() const { + return NS_FRAME_SPLITTABLE; + } + + /** + * Get the "type" of the frame + * + * @see nsGkAtoms::textFrame + */ + virtual nsIAtom* GetType() const; + + virtual PRBool IsFrameOfType(PRUint32 aFlags) const + { + // Set the frame state bit for text frames to mark them as replaced. + // XXX kipp: temporary + return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced | + nsIFrame::eLineParticipant)); + } + +#ifdef DEBUG + NS_IMETHOD List(FILE* out, PRInt32 aIndent) const; + NS_IMETHOD GetFrameName(nsAString& aResult) const; + NS_IMETHOD_(nsFrameState) GetDebugStateBits() const ; +#endif + + virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint); + + NS_IMETHOD SetSelected(nsPresContext* aPresContext, + nsIDOMRange *aRange, + PRBool aSelected, + nsSpread aSpread); + + virtual PRBool PeekOffsetNoAmount(PRBool aForward, PRInt32* aOffset); + virtual PRBool PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset); + virtual PRBool PeekOffsetWord(PRBool aForward, PRBool aWordSelectEatSpace, PRBool aIsKeyboardSelect, + PRInt32* aOffset, PeekWordState* aState); + + NS_IMETHOD CheckVisibility(nsPresContext* aContext, PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aRecurse, PRBool *aFinished, PRBool *_retval); + + // Update offsets to account for new length. This may clear mTextRun. + void SetLength(PRInt32 aLength); + + NS_IMETHOD GetOffsets(PRInt32 &start, PRInt32 &end)const; + + virtual void AdjustOffsetsForBidi(PRInt32 start, PRInt32 end); + + NS_IMETHOD GetPointFromOffset(PRInt32 inOffset, + nsPoint* outPoint); + + NS_IMETHOD GetChildFrameContainingOffset(PRInt32 inContentOffset, + PRBool inHint, + PRInt32* outFrameContentOffset, + nsIFrame* *outChildFrame); + + virtual PRBool IsVisibleInSelection(nsISelection* aSelection); + + virtual PRBool IsEmpty(); + virtual PRBool IsSelfEmpty() { return IsEmpty(); } + + /** + * @return PR_TRUE if this text frame ends with a newline character. It + * should return PR_FALSE if this is not a text frame. + */ + virtual PRBool HasTerminalNewline() const; + +#ifdef ACCESSIBILITY + NS_IMETHOD GetAccessible(nsIAccessible** aAccessible); +#endif + + virtual void MarkIntrinsicWidthsDirty(); + virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext); + virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext); + virtual void AddInlineMinWidth(nsIRenderingContext *aRenderingContext, + InlineMinWidthData *aData); + virtual void AddInlinePrefWidth(nsIRenderingContext *aRenderingContext, + InlinePrefWidthData *aData); + virtual nsSize ComputeSize(nsIRenderingContext *aRenderingContext, + nsSize aCBSize, nscoord aAvailableWidth, + nsSize aMargin, nsSize aBorder, nsSize aPadding, + PRBool aShrinkWrap); + NS_IMETHOD Reflow(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aMetrics, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus); + virtual PRBool CanContinueTextRun() const; + NS_IMETHOD TrimTrailingWhiteSpace(nsPresContext* aPresContext, + nsIRenderingContext& aRC, + nscoord& aDeltaWidth, + PRBool& aLastCharIsJustifiable); + virtual nsresult GetRenderedText(nsAString* aString = nsnull, + gfxSkipChars* aSkipChars = nsnull, + gfxSkipCharsIterator* aSkipIter = nsnull, + PRUint32 aSkippedStartOffset = 0, + PRUint32 aSkippedMaxLength = PR_UINT32_MAX); + + void AddInlineMinWidthForFlow(nsIRenderingContext *aRenderingContext, + nsIFrame::InlineMinWidthData *aData); + void AddInlinePrefWidthForFlow(nsIRenderingContext *aRenderingContext, + InlinePrefWidthData *aData); + + gfxFloat GetSnappedBaselineY(gfxContext* aContext, gfxFloat aY); + + // primary frame paint method called from nsDisplayText + void PaintText(nsIRenderingContext* aRenderingContext, nsPoint aPt, + const nsRect& aDirtyRect); + // helper: paint quirks-mode CSS text decorations + void PaintTextDecorations(gfxContext* aCtx, const gfxRect& aDirtyRect, + const gfxPoint& aFramePt, + const gfxPoint& aTextBaselinePt, + nsTextPaintStyle& aTextStyle, + PropertyProvider& aProvider); + // helper: paint text frame when we're impacted by at least one selection. + // Return PR_FALSE if the text was not painted and we should continue with + // the fast path. + PRBool PaintTextWithSelection(gfxContext* aCtx, + const gfxPoint& aFramePt, + const gfxPoint& aTextBaselinePt, + const gfxRect& aDirtyRect, + PropertyProvider& aProvider, + nsTextPaintStyle& aTextPaintStyle); + // helper: paint text with foreground and background colors determined + // by selection(s). Also computes a mask of all selection types applying to + // our text, returned in aAllTypes. + void PaintTextWithSelectionColors(gfxContext* aCtx, + const gfxPoint& aFramePt, + const gfxPoint& aTextBaselinePt, + const gfxRect& aDirtyRect, + PropertyProvider& aProvider, + nsTextPaintStyle& aTextPaintStyle, + SelectionDetails* aDetails, + SelectionType* aAllTypes); + // helper: paint text decorations for text selected by aSelectionType + void PaintTextSelectionDecorations(gfxContext* aCtx, + const gfxPoint& aFramePt, + const gfxPoint& aTextBaselinePt, + const gfxRect& aDirtyRect, + PropertyProvider& aProvider, + nsTextPaintStyle& aTextPaintStyle, + SelectionDetails* aDetails, + SelectionType aSelectionType); + + PRInt16 GetSelectionStatus(PRInt16* aSelectionFlags); + +#ifdef DEBUG + void ToCString(nsString& aBuf, PRInt32* aTotalContentLength) const; +#endif + + PRInt32 GetContentOffset() const { return mContentOffset; } + PRInt32 GetContentLength() const { return GetContentEnd() - mContentOffset; } + PRInt32 GetContentEnd() const; + // This returns the length the frame thinks it *should* have after it was + // last reflowed (0 if it hasn't been reflowed yet). This should be used only + // when setting up the text offsets for a new continuation frame. + PRInt32 GetContentLengthHint() const { return mContentLengthHint; } + + // Compute the length of the content mapped by this frame + // and all its in-flow siblings. Basically this means starting at mContentOffset + // and going to the end of the text node or the next bidi continuation + // boundary. + PRInt32 GetInFlowContentLength(); + + // Clears out mTextRun from this frame and all other frames that hold a reference + // to it, then deletes the textrun. + void ClearTextRun(); + /** + * Acquires the text run for this content, if necessary. + * @param aRC the rendering context to use as a reference for creating + * the textrun, if available (if not, we'll create one which will just be slower) + * @param aBlock the block ancestor for this frame, or nsnull if unknown + * @param aLine the line that this frame is on, if any, or nsnull if unknown + * @param aFlowEndInTextRun if non-null, this returns the textrun offset of + * end of the text associated with this frame and its in-flow siblings + * @return a gfxSkipCharsIterator set up to map DOM offsets for this frame + * to offsets into the textrun; its initial offset is set to this frame's + * content offset + */ + gfxSkipCharsIterator EnsureTextRun(nsIRenderingContext* aRC = nsnull, + nsIFrame* aLineContainer = nsnull, + const nsLineList::iterator* aLine = nsnull, + PRUint32* aFlowEndInTextRun = nsnull); + + gfxTextRun* GetTextRun() { return mTextRun; } + void SetTextRun(gfxTextRun* aTextRun) { mTextRun = aTextRun; } + + // Get the DOM content range mapped by this frame after excluding + // whitespace subject to start-of-line and end-of-line trimming. + // The textrun must have been created before calling this. + struct TrimmedOffsets { + PRInt32 mStart; + PRInt32 mLength; + PRInt32 GetEnd() { return mStart + mLength; } + }; + TrimmedOffsets GetTrimmedOffsets(const nsTextFragment* aFrag, + PRBool aTrimAfter); + +protected: + virtual ~nsTextFrame(); + + nsIFrame* mNextContinuation; + // The key invariant here is that mContentOffset never decreases along + // a next-continuation chain. And of course mContentOffset is always <= the + // the text node's content length, and the mContentOffset for the first frame + // is always 0. Furthermore the text mapped by a frame is determined by + // GetContentOffset() and GetContentLength()/GetContentEnd(), which get + // the length from the difference between this frame's offset and the next + // frame's offset, or the text length if there is no next frame. This means + // the frames always map the text node without overlapping or leaving any gaps. + PRInt32 mContentOffset; + // This does *not* indicate the length of text currently mapped by the frame; + // instead it's a hint saying that this frame *wants* to map this much text + // so if we create a new continuation, this is where that continuation should + // start. + PRInt32 mContentLengthHint; + nscoord mAscent; + gfxTextRun* mTextRun; + + SelectionDetails* GetSelectionDetails(); + + void AdjustSelectionPointsForBidi(SelectionDetails *sdptr, + PRInt32 textLength, + PRBool isRTLChars, + PRBool isOddLevel, + PRBool isBidiSystem); +}; + static void DestroyUserData(void* aUserData) { @@ -3360,9 +3645,7 @@ public: virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) { return mFrame->GetOverflowRect() + aBuilder->ToReferenceFrame(mFrame); } - virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt) { - return nsRect(aBuilder->ToReferenceFrame(mFrame), mFrame->GetSize()).Contains(aPt) ? mFrame : nsnull; - } + virtual nsIFrame* HitTest(nsDisplayListBuilder* aBuilder, nsPoint aPt) { return mFrame; } virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx, const nsRect& aDirtyRect); NS_DISPLAY_DECL_NAME("Text") @@ -4917,15 +5200,14 @@ nsTextFrame::ComputeSize(nsIRenderingContext *aRenderingContext, static void AddCharToMetrics(gfxTextRun* aCharTextRun, gfxTextRun* aBaseTextRun, - gfxTextRun::Metrics* aMetrics, PRBool aTightBoundingBox, - gfxContext* aContext) + gfxTextRun::Metrics* aMetrics, PRBool aTightBoundingBox) { gfxRect charRect; // assume char does not overflow font metrics!!! gfxFloat width = aCharTextRun->GetAdvanceWidth(0, aCharTextRun->GetLength(), nsnull); if (aTightBoundingBox) { gfxTextRun::Metrics charMetrics = - aCharTextRun->MeasureText(0, aCharTextRun->GetLength(), PR_TRUE, aContext, nsnull); + aCharTextRun->MeasureText(0, aCharTextRun->GetLength(), PR_TRUE, nsnull); charRect = charMetrics.mBoundingBox; } else { charRect = gfxRect(0, -aMetrics->mAscent, width, @@ -5170,15 +5452,13 @@ nsTextFrame::Reflow(nsPresContext* aPresContext, gfxFloat availWidth = aReflowState.availableWidth; PRBool canTrimTrailingWhitespace = !textStyle->WhiteSpaceIsSignificant() && textStyle->WhiteSpaceCanWrap(); - gfxContext* ctx = static_cast - (aReflowState.rendContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT)); PRUint32 transformedCharsFit = mTextRun->BreakAndMeasureText(transformedOffset, transformedLength, (GetStateBits() & TEXT_START_OF_LINE) != 0, availWidth, &provider, suppressInitialBreak, canTrimTrailingWhitespace ? &trimmedWidth : nsnull, - &textMetrics, needTightBoundingBox, ctx, + &textMetrics, needTightBoundingBox, &usedHyphenation, &transformedLastBreak); // The "end" iterator points to the first character after the string mapped // by this frame. Basically, its original-string offset is offset+charsFit @@ -5209,7 +5489,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext, gfxTextRunCache::AutoTextRun hyphenTextRun(GetHyphenTextRun(mTextRun, aReflowState.rendContext)); if (hyphenTextRun.get()) { AddCharToMetrics(hyphenTextRun.get(), - mTextRun, &textMetrics, needTightBoundingBox, ctx); + mTextRun, &textMetrics, needTightBoundingBox); } AddStateBits(TEXT_HYPHEN_BREAK); } @@ -5456,28 +5736,6 @@ nsTextFrame::TrimTrailingWhiteSpace(nsPresContext* aPresContext, return NS_OK; } -nsRect -nsTextFrame::RecomputeOverflowRect() -{ - gfxSkipCharsIterator iter = EnsureTextRun(); - if (!mTextRun) - return nsRect(nsPoint(0,0), GetSize()); - - PropertyProvider provider(this, iter); - provider.InitializeForDisplay(PR_TRUE); - - gfxTextRun::Metrics textMetrics = - mTextRun->MeasureText(provider.GetStart().GetSkippedOffset(), - ComputeTransformedLength(provider), PR_FALSE, nsnull, - &provider); - - nsRect boundingBox = - ConvertGfxRectOutward(textMetrics.mBoundingBox + gfxPoint(0, textMetrics.mAscent)); - boundingBox.UnionRect(boundingBox, - nsRect(nsPoint(0,0), GetSize())); - return boundingBox; -} - static PRUnichar TransformChar(const nsStyleText* aStyle, gfxTextRun* aTextRun, PRUint32 aSkippedOffset, PRUnichar aChar) { @@ -5699,11 +5957,6 @@ nsTextFrame::List(FILE* out, PRInt32 aIndent) const } } fprintf(out, " [content=%p]", static_cast(mContent)); - nsRect* overflowArea = const_cast(this)->GetOverflowAreaProperty(PR_FALSE); - if (overflowArea) { - fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea->x, overflowArea->y, - overflowArea->width, overflowArea->height); - } fprintf(out, " sc=%p", static_cast(mStyleContext)); nsIAtom* pseudoTag = mStyleContext->GetPseudoType(); if (pseudoTag) { diff --git a/layout/svg/base/src/nsSVGGlyphFrame.cpp b/layout/svg/base/src/nsSVGGlyphFrame.cpp index ae207ed855d..e2c8addf6c1 100644 --- a/layout/svg/base/src/nsSVGGlyphFrame.cpp +++ b/layout/svg/base/src/nsSVGGlyphFrame.cpp @@ -409,7 +409,7 @@ nsSVGGlyphFrame::UpdateCoveredRegion() textRun->DrawToPath(gfx, mPosition, 0, text.Length(), nsnull, nsnull); } else { gfxTextRun::Metrics metrics = - textRun->MeasureText(0, text.Length(), PR_FALSE, nsnull, nsnull); + textRun->MeasureText(0, text.Length(), PR_FALSE, nsnull); gfx->Rectangle(metrics.mBoundingBox + mPosition); } } else { @@ -434,7 +434,7 @@ nsSVGGlyphFrame::UpdateCoveredRegion() gfx->Rotate(cp[i].angle); gfxTextRun::Metrics metrics = - textRun->MeasureText(i, 1, PR_FALSE, nsnull, nsnull); + textRun->MeasureText(i, 1, PR_FALSE, nsnull); gfx->Rectangle(metrics.mBoundingBox + gfx->CurrentPoint()); } @@ -867,7 +867,7 @@ nsSVGGlyphFrame::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval) return NS_ERROR_OUT_OF_MEMORY; gfxTextRun::Metrics metrics = - textRun->MeasureText(charnum, 1, PR_FALSE, nsnull, nsnull); + textRun->MeasureText(charnum, 1, PR_FALSE, nsnull); if (cp) { if (cp[charnum].draw == PR_FALSE) { @@ -943,7 +943,7 @@ nsSVGGlyphFrame::GetBaselineOffset(PRUint16 baselineIdentifier) return 0.0f; gfxTextRun::Metrics metrics = - textRun->MeasureText(0, text.Length(), PR_FALSE, nsnull, nsnull); + textRun->MeasureText(0, text.Length(), PR_FALSE, nsnull); switch (baselineIdentifier) { case BASELINE_HANGING: @@ -1171,7 +1171,7 @@ nsSVGGlyphFrame::GetCharNumAtPosition(nsIDOMSVGPoint *point) } gfxTextRun::Metrics metrics = - textRun->MeasureText(charnum, 1, PR_FALSE, nsnull, nsnull); + textRun->MeasureText(charnum, 1, PR_FALSE, nsnull); gfx->Rectangle(metrics.mBoundingBox + gfx->CurrentPoint()); @@ -1293,7 +1293,7 @@ nsSVGGlyphFrame::ContainsPoint(float x, float y) } gfxTextRun::Metrics metrics = - textRun->MeasureText(i, 1, PR_FALSE, nsnull, nsnull); + textRun->MeasureText(i, 1, PR_FALSE, nsnull); gfx->Rectangle(metrics.mBoundingBox + gfx->CurrentPoint());