diff --git a/content/base/src/nsRuleNode.cpp b/content/base/src/nsRuleNode.cpp index 9aef1137437..454e45dafc4 100644 --- a/content/base/src/nsRuleNode.cpp +++ b/content/base/src/nsRuleNode.cpp @@ -940,7 +940,8 @@ static const PropertyCheckData UserInterfaceCheckProperties[] = { static const PropertyCheckData UIResetCheckProperties[] = { CHECKDATA_PROP(nsCSSUserInterface, mUserSelect, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSUserInterface, mResizer, CHECKDATA_VALUE, PR_FALSE), - CHECKDATA_PROP(nsCSSUserInterface, mKeyEquivalent, CHECKDATA_VALUELIST, PR_FALSE) + CHECKDATA_PROP(nsCSSUserInterface, mKeyEquivalent, CHECKDATA_VALUELIST, PR_FALSE), + CHECKDATA_PROP(nsCSSUserInterface, mForceBrokenImageIcon, CHECKDATA_VALUE, PR_FALSE) }; #ifdef INCLUDE_XUL @@ -2760,6 +2761,11 @@ nsRuleNode::ComputeUIResetData(nsStyleStruct* aStartData, const nsCSSStruct& aDa ui->mResizer = parentUI->mResizer; } + // force-broken-image-icons: integer + if (eCSSUnit_Integer == uiData.mForceBrokenImageIcon.GetUnit()) { + ui->mForceBrokenImageIcon = uiData.mForceBrokenImageIcon.GetIntValue(); + } + if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. diff --git a/content/html/style/src/nsCSSDeclaration.cpp b/content/html/style/src/nsCSSDeclaration.cpp index 73ea837a45a..6d2cb5ac108 100644 --- a/content/html/style/src/nsCSSDeclaration.cpp +++ b/content/html/style/src/nsCSSDeclaration.cpp @@ -946,7 +946,8 @@ nsCSSUserInterface::nsCSSUserInterface(const nsCSSUserInterface& aCopy) mKeyEquivalent(nsnull), mUserFocus(aCopy.mUserFocus), mResizer(aCopy.mResizer), - mCursor(nsnull) + mCursor(nsnull), + mForceBrokenImageIcon(aCopy.mForceBrokenImageIcon) { MOZ_COUNT_CTOR(nsCSSUserInterface); CSS_IF_COPY(mCursor, nsCSSValueList); @@ -988,7 +989,9 @@ void nsCSSUserInterface::List(FILE* out, PRInt32 aIndent) const cursor->mValue.AppendToString(buffer, eCSSProperty_cursor); cursor = cursor->mNext; } - + + mForceBrokenImageIcon.AppendToString(buffer,eCSSProperty_force_broken_image_icon); + fputs(NS_LossyConvertUCS2toASCII(buffer).get(), out); } #endif @@ -1894,7 +1897,8 @@ nsCSSDeclaration::AppendValue(nsCSSProperty aProperty, const nsCSSValue& aValue) case eCSSProperty_key_equivalent: case eCSSProperty_user_focus: case eCSSProperty_resizer: - case eCSSProperty_cursor: { + case eCSSProperty_cursor: + case eCSSProperty_force_broken_image_icon: { CSS_ENSURE(UserInterface) { switch (aProperty) { case eCSSProperty_user_input: theUserInterface->mUserInput = aValue; break; @@ -1914,7 +1918,8 @@ nsCSSDeclaration::AppendValue(nsCSSProperty aProperty, const nsCSSValue& aValue) CSS_IF_DELETE(theUserInterface->mCursor->mNext); } break; - + case eCSSProperty_force_broken_image_icon: theUserInterface->mForceBrokenImageIcon = aValue; break; + CSS_BOGUS_DEFAULT; // make compiler happy } } @@ -4567,7 +4572,8 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, nsCSSValue& aValue) case eCSSProperty_key_equivalent: case eCSSProperty_user_focus: case eCSSProperty_resizer: - case eCSSProperty_cursor: { + case eCSSProperty_cursor: + case eCSSProperty_force_broken_image_icon: { CSS_VARONSTACK_GET(UserInterface); if (nsnull != theUserInterface) { switch (aProperty) { @@ -4586,7 +4592,8 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, nsCSSValue& aValue) aValue = theUserInterface->mCursor->mValue; } break; - + case eCSSProperty_force_broken_image_icon: aValue = theUserInterface->mForceBrokenImageIcon; break; + CSS_BOGUS_DEFAULT; // make compiler happy } } diff --git a/content/html/style/src/nsCSSDeclaration.h b/content/html/style/src/nsCSSDeclaration.h index d4c894be13d..4ece2df3c5c 100644 --- a/content/html/style/src/nsCSSDeclaration.h +++ b/content/html/style/src/nsCSSDeclaration.h @@ -240,6 +240,7 @@ struct nsCSSDisplay : public nsCSSStruct { // in nsCSSDeclaration objects but because it's needed on the // stack when the struct is used in WalkRuleTree. nsCSSValue mLang; + // temp fix for bug 24000 nsCSSValue mBreakBefore; nsCSSValue mBreakAfter; @@ -420,6 +421,7 @@ struct nsCSSUserInterface : public nsCSSStruct { // NEW nsCSSValue mResizer; nsCSSValueList* mCursor; + nsCSSValue mForceBrokenImageIcon; }; struct nsCSSAural : public nsCSSStruct { // NEW diff --git a/content/html/style/src/nsCSSParser.cpp b/content/html/style/src/nsCSSParser.cpp index 8df48e08bef..2eb79c08ddf 100644 --- a/content/html/style/src/nsCSSParser.cpp +++ b/content/html/style/src/nsCSSParser.cpp @@ -3760,6 +3760,8 @@ PRBool CSSParserImpl::ParseSingleValueProperty(PRInt32& aErrorCode, case eCSSProperty_height: case eCSSProperty_width: return ParsePositiveVariant(aErrorCode, aValue, VARIANT_AHLP, nsnull); + case eCSSProperty_force_broken_image_icon: + return ParsePositiveVariant(aErrorCode, aValue, VARIANT_INTEGER, nsnull); case eCSSProperty_caption_side: return ParseVariant(aErrorCode, aValue, VARIANT_HK, nsCSSProps::kCaptionSideKTable); diff --git a/content/html/style/src/nsCSSStruct.cpp b/content/html/style/src/nsCSSStruct.cpp index 73ea837a45a..6d2cb5ac108 100644 --- a/content/html/style/src/nsCSSStruct.cpp +++ b/content/html/style/src/nsCSSStruct.cpp @@ -946,7 +946,8 @@ nsCSSUserInterface::nsCSSUserInterface(const nsCSSUserInterface& aCopy) mKeyEquivalent(nsnull), mUserFocus(aCopy.mUserFocus), mResizer(aCopy.mResizer), - mCursor(nsnull) + mCursor(nsnull), + mForceBrokenImageIcon(aCopy.mForceBrokenImageIcon) { MOZ_COUNT_CTOR(nsCSSUserInterface); CSS_IF_COPY(mCursor, nsCSSValueList); @@ -988,7 +989,9 @@ void nsCSSUserInterface::List(FILE* out, PRInt32 aIndent) const cursor->mValue.AppendToString(buffer, eCSSProperty_cursor); cursor = cursor->mNext; } - + + mForceBrokenImageIcon.AppendToString(buffer,eCSSProperty_force_broken_image_icon); + fputs(NS_LossyConvertUCS2toASCII(buffer).get(), out); } #endif @@ -1894,7 +1897,8 @@ nsCSSDeclaration::AppendValue(nsCSSProperty aProperty, const nsCSSValue& aValue) case eCSSProperty_key_equivalent: case eCSSProperty_user_focus: case eCSSProperty_resizer: - case eCSSProperty_cursor: { + case eCSSProperty_cursor: + case eCSSProperty_force_broken_image_icon: { CSS_ENSURE(UserInterface) { switch (aProperty) { case eCSSProperty_user_input: theUserInterface->mUserInput = aValue; break; @@ -1914,7 +1918,8 @@ nsCSSDeclaration::AppendValue(nsCSSProperty aProperty, const nsCSSValue& aValue) CSS_IF_DELETE(theUserInterface->mCursor->mNext); } break; - + case eCSSProperty_force_broken_image_icon: theUserInterface->mForceBrokenImageIcon = aValue; break; + CSS_BOGUS_DEFAULT; // make compiler happy } } @@ -4567,7 +4572,8 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, nsCSSValue& aValue) case eCSSProperty_key_equivalent: case eCSSProperty_user_focus: case eCSSProperty_resizer: - case eCSSProperty_cursor: { + case eCSSProperty_cursor: + case eCSSProperty_force_broken_image_icon: { CSS_VARONSTACK_GET(UserInterface); if (nsnull != theUserInterface) { switch (aProperty) { @@ -4586,7 +4592,8 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, nsCSSValue& aValue) aValue = theUserInterface->mCursor->mValue; } break; - + case eCSSProperty_force_broken_image_icon: aValue = theUserInterface->mForceBrokenImageIcon; break; + CSS_BOGUS_DEFAULT; // make compiler happy } } diff --git a/content/html/style/src/nsCSSStruct.h b/content/html/style/src/nsCSSStruct.h index d4c894be13d..4ece2df3c5c 100644 --- a/content/html/style/src/nsCSSStruct.h +++ b/content/html/style/src/nsCSSStruct.h @@ -240,6 +240,7 @@ struct nsCSSDisplay : public nsCSSStruct { // in nsCSSDeclaration objects but because it's needed on the // stack when the struct is used in WalkRuleTree. nsCSSValue mLang; + // temp fix for bug 24000 nsCSSValue mBreakBefore; nsCSSValue mBreakAfter; @@ -420,6 +421,7 @@ struct nsCSSUserInterface : public nsCSSStruct { // NEW nsCSSValue mResizer; nsCSSValueList* mCursor; + nsCSSValue mForceBrokenImageIcon; }; struct nsCSSAural : public nsCSSStruct { // NEW diff --git a/content/html/style/src/nsCSSStyleRule.cpp b/content/html/style/src/nsCSSStyleRule.cpp index 2331eca212c..d9bbf5d2d5d 100644 --- a/content/html/style/src/nsCSSStyleRule.cpp +++ b/content/html/style/src/nsCSSStyleRule.cpp @@ -2406,6 +2406,9 @@ MapUIForDeclaration(nsCSSDeclaration* aDecl, const nsStyleStructID& aID, nsCSSUs if (aUI.mResizer.GetUnit() == eCSSUnit_Null && ourUI->mResizer.GetUnit() != eCSSUnit_Null) aUI.mResizer = ourUI->mResizer; + + if (aUI.mForceBrokenImageIcon.GetUnit() == eCSSUnit_Null && ourUI->mForceBrokenImageIcon.GetUnit() == eCSSUnit_Integer) + aUI.mForceBrokenImageIcon = ourUI->mForceBrokenImageIcon; } return NS_OK; diff --git a/content/shared/public/nsCSSPropList.h b/content/shared/public/nsCSSPropList.h index 3007f42b36f..77e8553a0d1 100644 --- a/content/shared/public/nsCSSPropList.h +++ b/content/shared/public/nsCSSPropList.h @@ -163,6 +163,7 @@ CSS_PROP(font-stretch, font_stretch, REFLOW) CSS_PROP(font-style, font_style, REFLOW) CSS_PROP(font-variant, font_variant, REFLOW) CSS_PROP(font-weight, font_weight, REFLOW) +CSS_PROP(-moz-force-broken-image-icon, force_broken_image_icon, FRAMECHANGE) // bug 58646 CSS_PROP(height, height, REFLOW) CSS_PROP(-moz-image-region, image_region, REFLOW) CSS_PROP(-x-image-region-bottom, image_region_bottom, REFLOW) diff --git a/content/shared/public/nsStyleStruct.h b/content/shared/public/nsStyleStruct.h index 2303efea81c..6155ecd801c 100644 --- a/content/shared/public/nsStyleStruct.h +++ b/content/shared/public/nsStyleStruct.h @@ -1092,6 +1092,7 @@ struct nsStyleUIReset: public nsStyleStruct { PRUint8 mUserSelect; // [reset] (selection-style) PRUnichar mKeyEquivalent; // [reset] XXX what type should this be? PRUint8 mResizer; // [reset] + PRUint8 mForceBrokenImageIcon; // [reset] (0 if not forcing, otherwise forcing) }; struct nsStyleUserInterface: public nsStyleStruct { diff --git a/content/shared/src/nsStyleStruct.cpp b/content/shared/src/nsStyleStruct.cpp index 59fbef0e21f..605a9bb6068 100644 --- a/content/shared/src/nsStyleStruct.cpp +++ b/content/shared/src/nsStyleStruct.cpp @@ -1389,6 +1389,7 @@ nsStyleUIReset::nsStyleUIReset(void) mUserSelect = NS_STYLE_USER_SELECT_AUTO; mKeyEquivalent = PRUnichar(0); // XXX what type should this be? mResizer = NS_STYLE_RESIZER_AUTO; + mForceBrokenImageIcon = 0; } nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource) @@ -1396,6 +1397,7 @@ nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource) mUserSelect = aSource.mUserSelect; mKeyEquivalent = aSource.mKeyEquivalent; mResizer = aSource.mResizer; + mForceBrokenImageIcon = aSource.mForceBrokenImageIcon; } nsStyleUIReset::~nsStyleUIReset(void) @@ -1404,8 +1406,9 @@ nsStyleUIReset::~nsStyleUIReset(void) PRInt32 nsStyleUIReset::CalcDifference(const nsStyleUIReset& aOther) const { - if (mResizer == aOther.mResizer) { - if (mUserSelect == aOther.mUserSelect) { + if (mForceBrokenImageIcon == aOther.mForceBrokenImageIcon) { + if (mResizer == aOther.mResizer && + mUserSelect == aOther.mUserSelect) { if (mKeyEquivalent == aOther.mKeyEquivalent) { return NS_STYLE_HINT_NONE; } @@ -1413,6 +1416,5 @@ PRInt32 nsStyleUIReset::CalcDifference(const nsStyleUIReset& aOther) const } return NS_STYLE_HINT_VISUAL; } - - return NS_STYLE_HINT_VISUAL; + return NS_STYLE_HINT_FRAMECHANGE; } diff --git a/editor/ui/composer/content/EditorContent.css b/editor/ui/composer/content/EditorContent.css index 210d79b78dd..a5574d8a879 100644 --- a/editor/ui/composer/content/EditorContent.css +++ b/editor/ui/composer/content/EditorContent.css @@ -110,3 +110,6 @@ span[-moz-smiley="s7"] { background-image: url(chrome://editor/content/images/undecided_n.gif); } +img { + -moz-force-broken-image-icon: 1; +} diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 51f3fe7007d..18abb113f75 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -114,6 +114,12 @@ #define NS_ICON_LOADING_IMAGE (0) #define NS_ICON_BROKEN_IMAGE (1) +// sizes (pixels) for image icon, padding and border frame +#define ICON_SIZE (16) +#define ICON_PADDING (3) +#define ALT_BORDER_WIDTH (1) + + // Default alignment value (so we can tell an unset value from a set value) #define ALIGN_UNSET PRUint8(-1) @@ -653,7 +659,7 @@ NS_IMETHODIMP nsImageFrame::OnStopDecode(imgIRequest *aRequest, nsIPresContext * mContent->GetAttr(kNameSpaceID_HTML, nsHTMLAtoms::usemap, usemap); if (usemap.IsEmpty()) { // check if we want to honor the ALT text in the IMG frame, or let the preShell make it into inline text - // - if QuirksMode, and the IMG has a size, then render the ALT text in the ING frame + // - if QuirksMode, and the IMG has a size, then render the ALT text in the IMG frame // UNLESS there is a pref set to force inline alt text PRBool useSizedBox = PR_FALSE; PRBool prefForceInlineAltText = mIconLoad ? mIconLoad->mPrefForceInlineAltText : PR_FALSE; @@ -667,11 +673,24 @@ NS_IMETHODIMP nsImageFrame::OnStopDecode(imgIRequest *aRequest, nsIPresContext * nsCompatibility mode; aPresContext->GetCompatibilityMode(&mode); - // wrap it all up - useSizedBox = !prefForceInlineAltText && - HaveFixedSize(*stylePosition) && - mode == eCompatibility_NavQuirks && - !mImageBlocked; + // check for being in Composer: if we are, we always show the size-box + PRBool forceIcon = PR_FALSE; + + // check for style property that indicates the icon should always be shown + const nsStyleUIReset* styleData; + GetStyleData(eStyleStruct_UIReset, (const nsStyleStruct*&) styleData); + if (styleData->mForceBrokenImageIcon) { + forceIcon = PR_TRUE; + } + + // wrap it all up: use the size box if + // - in editor + // - not forcing inline alt text, have fixed size, in quirks mode, image not blocked + useSizedBox = forceIcon || + (!prefForceInlineAltText && + HaveFixedSize(*stylePosition) && + mode == eCompatibility_NavQuirks && + !mImageBlocked); if (!useSizedBox) { // let the presShell handle converting this into the inline alt text frame @@ -745,18 +764,39 @@ nsImageFrame::GetDesiredSize(nsIPresContext* aPresContext, // check to see if the size is already known by the image container. if (mLoads[0].mIntrinsicSize.width == 0 && mLoads[0].mIntrinsicSize.height == 0) { + PRBool needMinIconSizing = PR_FALSE; + float p2t; + aPresContext->GetPixelsToTwips(&p2t); if (mLoads[0].mRequest) { nsCOMPtr con; mLoads[0].mRequest->GetImage(getter_AddRefs(con)); if (con) { - float p2t; nscoord width, height; - aPresContext->GetPixelsToTwips(&p2t); con->GetWidth(&width); con->GetHeight(&height); mLoads[0].mIntrinsicSize.width = NSIntPixelsToTwips(width, p2t); mLoads[0].mIntrinsicSize.height = NSIntPixelsToTwips(height, p2t); + } else { + // no image container, so we may need to synthesize a minimum size for the image icons + needMinIconSizing = PR_TRUE; + } + } else { + // no request, so we may need to synthesize a minimum size for the image icons + needMinIconSizing = PR_TRUE; + } + + if (needMinIconSizing) { + // XXX: we need this in composer, but it is also good for general quirks mode to always + // XXX: have room for the icon + // check for quirks mode + nsCompatibility mode; + aPresContext->GetCompatibilityMode(&mode); + if (mode == eCompatibility_NavQuirks) { + // image request is null or image size not known, probably an invalid image specified + // - make the image big enough for the icon (it may not be used if inline alt expansion is used instead) + mLoads[0].mIntrinsicSize.width = NSIntPixelsToTwips(ICON_SIZE+(2*(ICON_PADDING+ALT_BORDER_WIDTH)), p2t); + mLoads[0].mIntrinsicSize.height = NSIntPixelsToTwips(ICON_SIZE+(2*(ICON_PADDING+ALT_BORDER_WIDTH)), p2t); } } } @@ -1088,10 +1128,6 @@ struct nsRecessedBorder : public nsStyleBorder { } }; -#define ICON_SIZE (16) -#define ICON_PADDING (6) -#define ALT_BORDER_WIDTH (1) - void nsImageFrame::DisplayAltFeedback(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -1107,6 +1143,12 @@ nsImageFrame::DisplayAltFeedback(nsIPresContext* aPresContext, aPresContext->GetScaledPixelsToTwips(&p2t); borderEdgeWidth = NSIntPixelsToTwips(ALT_BORDER_WIDTH, p2t); + // if inner area is empty, then make it big enough for at least the icon + if (inner.IsEmpty()){ + inner.SizeBy(2*(NSIntPixelsToTwips(ICON_SIZE+ICON_PADDING+ALT_BORDER_WIDTH,p2t)), + 2*(NSIntPixelsToTwips(ICON_SIZE+ICON_PADDING+ALT_BORDER_WIDTH,p2t))); + } + // Make sure we have enough room to actually render the border within // our frame bounds if ((inner.width < 2 * borderEdgeWidth) || (inner.height < 2 * borderEdgeWidth)) { @@ -1249,6 +1291,7 @@ nsImageFrame::Paint(nsIPresContext* aPresContext, if (loadStatus & imgIRequest::STATUS_ERROR || !imgCon) { // No image yet, or image load failed. Draw the alt-text and an icon // indicating the status (unless image is blocked, in which case we show nothing) + #ifndef SUPPRESS_LOADING_ICON if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer && (!mImageBlocked || mIconLoad->mPrefAllImagesBlocked)) { diff --git a/layout/html/base/src/nsImageFrame.cpp b/layout/html/base/src/nsImageFrame.cpp index 51f3fe7007d..18abb113f75 100644 --- a/layout/html/base/src/nsImageFrame.cpp +++ b/layout/html/base/src/nsImageFrame.cpp @@ -114,6 +114,12 @@ #define NS_ICON_LOADING_IMAGE (0) #define NS_ICON_BROKEN_IMAGE (1) +// sizes (pixels) for image icon, padding and border frame +#define ICON_SIZE (16) +#define ICON_PADDING (3) +#define ALT_BORDER_WIDTH (1) + + // Default alignment value (so we can tell an unset value from a set value) #define ALIGN_UNSET PRUint8(-1) @@ -653,7 +659,7 @@ NS_IMETHODIMP nsImageFrame::OnStopDecode(imgIRequest *aRequest, nsIPresContext * mContent->GetAttr(kNameSpaceID_HTML, nsHTMLAtoms::usemap, usemap); if (usemap.IsEmpty()) { // check if we want to honor the ALT text in the IMG frame, or let the preShell make it into inline text - // - if QuirksMode, and the IMG has a size, then render the ALT text in the ING frame + // - if QuirksMode, and the IMG has a size, then render the ALT text in the IMG frame // UNLESS there is a pref set to force inline alt text PRBool useSizedBox = PR_FALSE; PRBool prefForceInlineAltText = mIconLoad ? mIconLoad->mPrefForceInlineAltText : PR_FALSE; @@ -667,11 +673,24 @@ NS_IMETHODIMP nsImageFrame::OnStopDecode(imgIRequest *aRequest, nsIPresContext * nsCompatibility mode; aPresContext->GetCompatibilityMode(&mode); - // wrap it all up - useSizedBox = !prefForceInlineAltText && - HaveFixedSize(*stylePosition) && - mode == eCompatibility_NavQuirks && - !mImageBlocked; + // check for being in Composer: if we are, we always show the size-box + PRBool forceIcon = PR_FALSE; + + // check for style property that indicates the icon should always be shown + const nsStyleUIReset* styleData; + GetStyleData(eStyleStruct_UIReset, (const nsStyleStruct*&) styleData); + if (styleData->mForceBrokenImageIcon) { + forceIcon = PR_TRUE; + } + + // wrap it all up: use the size box if + // - in editor + // - not forcing inline alt text, have fixed size, in quirks mode, image not blocked + useSizedBox = forceIcon || + (!prefForceInlineAltText && + HaveFixedSize(*stylePosition) && + mode == eCompatibility_NavQuirks && + !mImageBlocked); if (!useSizedBox) { // let the presShell handle converting this into the inline alt text frame @@ -745,18 +764,39 @@ nsImageFrame::GetDesiredSize(nsIPresContext* aPresContext, // check to see if the size is already known by the image container. if (mLoads[0].mIntrinsicSize.width == 0 && mLoads[0].mIntrinsicSize.height == 0) { + PRBool needMinIconSizing = PR_FALSE; + float p2t; + aPresContext->GetPixelsToTwips(&p2t); if (mLoads[0].mRequest) { nsCOMPtr con; mLoads[0].mRequest->GetImage(getter_AddRefs(con)); if (con) { - float p2t; nscoord width, height; - aPresContext->GetPixelsToTwips(&p2t); con->GetWidth(&width); con->GetHeight(&height); mLoads[0].mIntrinsicSize.width = NSIntPixelsToTwips(width, p2t); mLoads[0].mIntrinsicSize.height = NSIntPixelsToTwips(height, p2t); + } else { + // no image container, so we may need to synthesize a minimum size for the image icons + needMinIconSizing = PR_TRUE; + } + } else { + // no request, so we may need to synthesize a minimum size for the image icons + needMinIconSizing = PR_TRUE; + } + + if (needMinIconSizing) { + // XXX: we need this in composer, but it is also good for general quirks mode to always + // XXX: have room for the icon + // check for quirks mode + nsCompatibility mode; + aPresContext->GetCompatibilityMode(&mode); + if (mode == eCompatibility_NavQuirks) { + // image request is null or image size not known, probably an invalid image specified + // - make the image big enough for the icon (it may not be used if inline alt expansion is used instead) + mLoads[0].mIntrinsicSize.width = NSIntPixelsToTwips(ICON_SIZE+(2*(ICON_PADDING+ALT_BORDER_WIDTH)), p2t); + mLoads[0].mIntrinsicSize.height = NSIntPixelsToTwips(ICON_SIZE+(2*(ICON_PADDING+ALT_BORDER_WIDTH)), p2t); } } } @@ -1088,10 +1128,6 @@ struct nsRecessedBorder : public nsStyleBorder { } }; -#define ICON_SIZE (16) -#define ICON_PADDING (6) -#define ALT_BORDER_WIDTH (1) - void nsImageFrame::DisplayAltFeedback(nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, @@ -1107,6 +1143,12 @@ nsImageFrame::DisplayAltFeedback(nsIPresContext* aPresContext, aPresContext->GetScaledPixelsToTwips(&p2t); borderEdgeWidth = NSIntPixelsToTwips(ALT_BORDER_WIDTH, p2t); + // if inner area is empty, then make it big enough for at least the icon + if (inner.IsEmpty()){ + inner.SizeBy(2*(NSIntPixelsToTwips(ICON_SIZE+ICON_PADDING+ALT_BORDER_WIDTH,p2t)), + 2*(NSIntPixelsToTwips(ICON_SIZE+ICON_PADDING+ALT_BORDER_WIDTH,p2t))); + } + // Make sure we have enough room to actually render the border within // our frame bounds if ((inner.width < 2 * borderEdgeWidth) || (inner.height < 2 * borderEdgeWidth)) { @@ -1249,6 +1291,7 @@ nsImageFrame::Paint(nsIPresContext* aPresContext, if (loadStatus & imgIRequest::STATUS_ERROR || !imgCon) { // No image yet, or image load failed. Draw the alt-text and an icon // indicating the status (unless image is blocked, in which case we show nothing) + #ifndef SUPPRESS_LOADING_ICON if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer && (!mImageBlocked || mIconLoad->mPrefAllImagesBlocked)) { diff --git a/layout/style/nsCSSDeclaration.cpp b/layout/style/nsCSSDeclaration.cpp index 73ea837a45a..6d2cb5ac108 100644 --- a/layout/style/nsCSSDeclaration.cpp +++ b/layout/style/nsCSSDeclaration.cpp @@ -946,7 +946,8 @@ nsCSSUserInterface::nsCSSUserInterface(const nsCSSUserInterface& aCopy) mKeyEquivalent(nsnull), mUserFocus(aCopy.mUserFocus), mResizer(aCopy.mResizer), - mCursor(nsnull) + mCursor(nsnull), + mForceBrokenImageIcon(aCopy.mForceBrokenImageIcon) { MOZ_COUNT_CTOR(nsCSSUserInterface); CSS_IF_COPY(mCursor, nsCSSValueList); @@ -988,7 +989,9 @@ void nsCSSUserInterface::List(FILE* out, PRInt32 aIndent) const cursor->mValue.AppendToString(buffer, eCSSProperty_cursor); cursor = cursor->mNext; } - + + mForceBrokenImageIcon.AppendToString(buffer,eCSSProperty_force_broken_image_icon); + fputs(NS_LossyConvertUCS2toASCII(buffer).get(), out); } #endif @@ -1894,7 +1897,8 @@ nsCSSDeclaration::AppendValue(nsCSSProperty aProperty, const nsCSSValue& aValue) case eCSSProperty_key_equivalent: case eCSSProperty_user_focus: case eCSSProperty_resizer: - case eCSSProperty_cursor: { + case eCSSProperty_cursor: + case eCSSProperty_force_broken_image_icon: { CSS_ENSURE(UserInterface) { switch (aProperty) { case eCSSProperty_user_input: theUserInterface->mUserInput = aValue; break; @@ -1914,7 +1918,8 @@ nsCSSDeclaration::AppendValue(nsCSSProperty aProperty, const nsCSSValue& aValue) CSS_IF_DELETE(theUserInterface->mCursor->mNext); } break; - + case eCSSProperty_force_broken_image_icon: theUserInterface->mForceBrokenImageIcon = aValue; break; + CSS_BOGUS_DEFAULT; // make compiler happy } } @@ -4567,7 +4572,8 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, nsCSSValue& aValue) case eCSSProperty_key_equivalent: case eCSSProperty_user_focus: case eCSSProperty_resizer: - case eCSSProperty_cursor: { + case eCSSProperty_cursor: + case eCSSProperty_force_broken_image_icon: { CSS_VARONSTACK_GET(UserInterface); if (nsnull != theUserInterface) { switch (aProperty) { @@ -4586,7 +4592,8 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, nsCSSValue& aValue) aValue = theUserInterface->mCursor->mValue; } break; - + case eCSSProperty_force_broken_image_icon: aValue = theUserInterface->mForceBrokenImageIcon; break; + CSS_BOGUS_DEFAULT; // make compiler happy } } diff --git a/layout/style/nsCSSDeclaration.h b/layout/style/nsCSSDeclaration.h index d4c894be13d..4ece2df3c5c 100644 --- a/layout/style/nsCSSDeclaration.h +++ b/layout/style/nsCSSDeclaration.h @@ -240,6 +240,7 @@ struct nsCSSDisplay : public nsCSSStruct { // in nsCSSDeclaration objects but because it's needed on the // stack when the struct is used in WalkRuleTree. nsCSSValue mLang; + // temp fix for bug 24000 nsCSSValue mBreakBefore; nsCSSValue mBreakAfter; @@ -420,6 +421,7 @@ struct nsCSSUserInterface : public nsCSSStruct { // NEW nsCSSValue mResizer; nsCSSValueList* mCursor; + nsCSSValue mForceBrokenImageIcon; }; struct nsCSSAural : public nsCSSStruct { // NEW diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 8df48e08bef..2eb79c08ddf 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -3760,6 +3760,8 @@ PRBool CSSParserImpl::ParseSingleValueProperty(PRInt32& aErrorCode, case eCSSProperty_height: case eCSSProperty_width: return ParsePositiveVariant(aErrorCode, aValue, VARIANT_AHLP, nsnull); + case eCSSProperty_force_broken_image_icon: + return ParsePositiveVariant(aErrorCode, aValue, VARIANT_INTEGER, nsnull); case eCSSProperty_caption_side: return ParseVariant(aErrorCode, aValue, VARIANT_HK, nsCSSProps::kCaptionSideKTable); diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index 3007f42b36f..77e8553a0d1 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -163,6 +163,7 @@ CSS_PROP(font-stretch, font_stretch, REFLOW) CSS_PROP(font-style, font_style, REFLOW) CSS_PROP(font-variant, font_variant, REFLOW) CSS_PROP(font-weight, font_weight, REFLOW) +CSS_PROP(-moz-force-broken-image-icon, force_broken_image_icon, FRAMECHANGE) // bug 58646 CSS_PROP(height, height, REFLOW) CSS_PROP(-moz-image-region, image_region, REFLOW) CSS_PROP(-x-image-region-bottom, image_region_bottom, REFLOW) diff --git a/layout/style/nsCSSStruct.cpp b/layout/style/nsCSSStruct.cpp index 73ea837a45a..6d2cb5ac108 100644 --- a/layout/style/nsCSSStruct.cpp +++ b/layout/style/nsCSSStruct.cpp @@ -946,7 +946,8 @@ nsCSSUserInterface::nsCSSUserInterface(const nsCSSUserInterface& aCopy) mKeyEquivalent(nsnull), mUserFocus(aCopy.mUserFocus), mResizer(aCopy.mResizer), - mCursor(nsnull) + mCursor(nsnull), + mForceBrokenImageIcon(aCopy.mForceBrokenImageIcon) { MOZ_COUNT_CTOR(nsCSSUserInterface); CSS_IF_COPY(mCursor, nsCSSValueList); @@ -988,7 +989,9 @@ void nsCSSUserInterface::List(FILE* out, PRInt32 aIndent) const cursor->mValue.AppendToString(buffer, eCSSProperty_cursor); cursor = cursor->mNext; } - + + mForceBrokenImageIcon.AppendToString(buffer,eCSSProperty_force_broken_image_icon); + fputs(NS_LossyConvertUCS2toASCII(buffer).get(), out); } #endif @@ -1894,7 +1897,8 @@ nsCSSDeclaration::AppendValue(nsCSSProperty aProperty, const nsCSSValue& aValue) case eCSSProperty_key_equivalent: case eCSSProperty_user_focus: case eCSSProperty_resizer: - case eCSSProperty_cursor: { + case eCSSProperty_cursor: + case eCSSProperty_force_broken_image_icon: { CSS_ENSURE(UserInterface) { switch (aProperty) { case eCSSProperty_user_input: theUserInterface->mUserInput = aValue; break; @@ -1914,7 +1918,8 @@ nsCSSDeclaration::AppendValue(nsCSSProperty aProperty, const nsCSSValue& aValue) CSS_IF_DELETE(theUserInterface->mCursor->mNext); } break; - + case eCSSProperty_force_broken_image_icon: theUserInterface->mForceBrokenImageIcon = aValue; break; + CSS_BOGUS_DEFAULT; // make compiler happy } } @@ -4567,7 +4572,8 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, nsCSSValue& aValue) case eCSSProperty_key_equivalent: case eCSSProperty_user_focus: case eCSSProperty_resizer: - case eCSSProperty_cursor: { + case eCSSProperty_cursor: + case eCSSProperty_force_broken_image_icon: { CSS_VARONSTACK_GET(UserInterface); if (nsnull != theUserInterface) { switch (aProperty) { @@ -4586,7 +4592,8 @@ nsCSSDeclaration::GetValue(nsCSSProperty aProperty, nsCSSValue& aValue) aValue = theUserInterface->mCursor->mValue; } break; - + case eCSSProperty_force_broken_image_icon: aValue = theUserInterface->mForceBrokenImageIcon; break; + CSS_BOGUS_DEFAULT; // make compiler happy } } diff --git a/layout/style/nsCSSStruct.h b/layout/style/nsCSSStruct.h index d4c894be13d..4ece2df3c5c 100644 --- a/layout/style/nsCSSStruct.h +++ b/layout/style/nsCSSStruct.h @@ -240,6 +240,7 @@ struct nsCSSDisplay : public nsCSSStruct { // in nsCSSDeclaration objects but because it's needed on the // stack when the struct is used in WalkRuleTree. nsCSSValue mLang; + // temp fix for bug 24000 nsCSSValue mBreakBefore; nsCSSValue mBreakAfter; @@ -420,6 +421,7 @@ struct nsCSSUserInterface : public nsCSSStruct { // NEW nsCSSValue mResizer; nsCSSValueList* mCursor; + nsCSSValue mForceBrokenImageIcon; }; struct nsCSSAural : public nsCSSStruct { // NEW diff --git a/layout/style/nsCSSStyleRule.cpp b/layout/style/nsCSSStyleRule.cpp index 2331eca212c..d9bbf5d2d5d 100644 --- a/layout/style/nsCSSStyleRule.cpp +++ b/layout/style/nsCSSStyleRule.cpp @@ -2406,6 +2406,9 @@ MapUIForDeclaration(nsCSSDeclaration* aDecl, const nsStyleStructID& aID, nsCSSUs if (aUI.mResizer.GetUnit() == eCSSUnit_Null && ourUI->mResizer.GetUnit() != eCSSUnit_Null) aUI.mResizer = ourUI->mResizer; + + if (aUI.mForceBrokenImageIcon.GetUnit() == eCSSUnit_Null && ourUI->mForceBrokenImageIcon.GetUnit() == eCSSUnit_Integer) + aUI.mForceBrokenImageIcon = ourUI->mForceBrokenImageIcon; } return NS_OK; diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 9aef1137437..454e45dafc4 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -940,7 +940,8 @@ static const PropertyCheckData UserInterfaceCheckProperties[] = { static const PropertyCheckData UIResetCheckProperties[] = { CHECKDATA_PROP(nsCSSUserInterface, mUserSelect, CHECKDATA_VALUE, PR_FALSE), CHECKDATA_PROP(nsCSSUserInterface, mResizer, CHECKDATA_VALUE, PR_FALSE), - CHECKDATA_PROP(nsCSSUserInterface, mKeyEquivalent, CHECKDATA_VALUELIST, PR_FALSE) + CHECKDATA_PROP(nsCSSUserInterface, mKeyEquivalent, CHECKDATA_VALUELIST, PR_FALSE), + CHECKDATA_PROP(nsCSSUserInterface, mForceBrokenImageIcon, CHECKDATA_VALUE, PR_FALSE) }; #ifdef INCLUDE_XUL @@ -2760,6 +2761,11 @@ nsRuleNode::ComputeUIResetData(nsStyleStruct* aStartData, const nsCSSStruct& aDa ui->mResizer = parentUI->mResizer; } + // force-broken-image-icons: integer + if (eCSSUnit_Integer == uiData.mForceBrokenImageIcon.GetUnit()) { + ui->mForceBrokenImageIcon = uiData.mForceBrokenImageIcon.GetIntValue(); + } + if (inherited) // We inherited, and therefore can't be cached in the rule node. We have to be put right on the // style context. diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 59fbef0e21f..605a9bb6068 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1389,6 +1389,7 @@ nsStyleUIReset::nsStyleUIReset(void) mUserSelect = NS_STYLE_USER_SELECT_AUTO; mKeyEquivalent = PRUnichar(0); // XXX what type should this be? mResizer = NS_STYLE_RESIZER_AUTO; + mForceBrokenImageIcon = 0; } nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource) @@ -1396,6 +1397,7 @@ nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource) mUserSelect = aSource.mUserSelect; mKeyEquivalent = aSource.mKeyEquivalent; mResizer = aSource.mResizer; + mForceBrokenImageIcon = aSource.mForceBrokenImageIcon; } nsStyleUIReset::~nsStyleUIReset(void) @@ -1404,8 +1406,9 @@ nsStyleUIReset::~nsStyleUIReset(void) PRInt32 nsStyleUIReset::CalcDifference(const nsStyleUIReset& aOther) const { - if (mResizer == aOther.mResizer) { - if (mUserSelect == aOther.mUserSelect) { + if (mForceBrokenImageIcon == aOther.mForceBrokenImageIcon) { + if (mResizer == aOther.mResizer && + mUserSelect == aOther.mUserSelect) { if (mKeyEquivalent == aOther.mKeyEquivalent) { return NS_STYLE_HINT_NONE; } @@ -1413,6 +1416,5 @@ PRInt32 nsStyleUIReset::CalcDifference(const nsStyleUIReset& aOther) const } return NS_STYLE_HINT_VISUAL; } - - return NS_STYLE_HINT_VISUAL; + return NS_STYLE_HINT_FRAMECHANGE; } diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 2303efea81c..6155ecd801c 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1092,6 +1092,7 @@ struct nsStyleUIReset: public nsStyleStruct { PRUint8 mUserSelect; // [reset] (selection-style) PRUnichar mKeyEquivalent; // [reset] XXX what type should this be? PRUint8 mResizer; // [reset] + PRUint8 mForceBrokenImageIcon; // [reset] (0 if not forcing, otherwise forcing) }; struct nsStyleUserInterface: public nsStyleStruct {