layout/generic/nsBulletFrame.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/generic/nsBulletFrame.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1913 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +/* rendering object for list-item bullets */
    1.10 +
    1.11 +#include "nsBulletFrame.h"
    1.12 +
    1.13 +#include "mozilla/MathAlgorithms.h"
    1.14 +#include "nsCOMPtr.h"
    1.15 +#include "nsGkAtoms.h"
    1.16 +#include "nsGenericHTMLElement.h"
    1.17 +#include "nsAttrValueInlines.h"
    1.18 +#include "nsPresContext.h"
    1.19 +#include "nsIPresShell.h"
    1.20 +#include "nsIDocument.h"
    1.21 +#include "nsRenderingContext.h"
    1.22 +#include "prprf.h"
    1.23 +#include "nsDisplayList.h"
    1.24 +#include "nsCounterManager.h"
    1.25 +
    1.26 +#include "imgIContainer.h"
    1.27 +#include "imgRequestProxy.h"
    1.28 +#include "nsIURI.h"
    1.29 +
    1.30 +#include <algorithm>
    1.31 +
    1.32 +#ifdef ACCESSIBILITY
    1.33 +#include "nsAccessibilityService.h"
    1.34 +#endif
    1.35 +
    1.36 +using namespace mozilla;
    1.37 +
    1.38 +NS_DECLARE_FRAME_PROPERTY(FontSizeInflationProperty, nullptr)
    1.39 +
    1.40 +NS_IMPL_FRAMEARENA_HELPERS(nsBulletFrame)
    1.41 +
    1.42 +#ifdef DEBUG
    1.43 +NS_QUERYFRAME_HEAD(nsBulletFrame)
    1.44 +  NS_QUERYFRAME_ENTRY(nsBulletFrame)
    1.45 +NS_QUERYFRAME_TAIL_INHERITING(nsFrame)
    1.46 +#endif
    1.47 +
    1.48 +nsBulletFrame::~nsBulletFrame()
    1.49 +{
    1.50 +}
    1.51 +
    1.52 +void
    1.53 +nsBulletFrame::DestroyFrom(nsIFrame* aDestructRoot)
    1.54 +{
    1.55 +  // Stop image loading first
    1.56 +  if (mImageRequest) {
    1.57 +    // Deregister our image request from the refresh driver
    1.58 +    nsLayoutUtils::DeregisterImageRequest(PresContext(),
    1.59 +                                          mImageRequest,
    1.60 +                                          &mRequestRegistered);
    1.61 +    mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
    1.62 +    mImageRequest = nullptr;
    1.63 +  }
    1.64 +
    1.65 +  if (mListener) {
    1.66 +    mListener->SetFrame(nullptr);
    1.67 +  }
    1.68 +
    1.69 +  // Let base class do the rest
    1.70 +  nsFrame::DestroyFrom(aDestructRoot);
    1.71 +}
    1.72 +
    1.73 +#ifdef DEBUG_FRAME_DUMP
    1.74 +nsresult
    1.75 +nsBulletFrame::GetFrameName(nsAString& aResult) const
    1.76 +{
    1.77 +  return MakeFrameName(NS_LITERAL_STRING("Bullet"), aResult);
    1.78 +}
    1.79 +#endif
    1.80 +
    1.81 +nsIAtom*
    1.82 +nsBulletFrame::GetType() const
    1.83 +{
    1.84 +  return nsGkAtoms::bulletFrame;
    1.85 +}
    1.86 +
    1.87 +bool
    1.88 +nsBulletFrame::IsEmpty()
    1.89 +{
    1.90 +  return IsSelfEmpty();
    1.91 +}
    1.92 +
    1.93 +bool
    1.94 +nsBulletFrame::IsSelfEmpty() 
    1.95 +{
    1.96 +  return StyleList()->mListStyleType == NS_STYLE_LIST_STYLE_NONE;
    1.97 +}
    1.98 +
    1.99 +/* virtual */ void
   1.100 +nsBulletFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
   1.101 +{
   1.102 +  nsFrame::DidSetStyleContext(aOldStyleContext);
   1.103 +
   1.104 +  imgRequestProxy *newRequest = StyleList()->GetListStyleImage();
   1.105 +
   1.106 +  if (newRequest) {
   1.107 +
   1.108 +    if (!mListener) {
   1.109 +      mListener = new nsBulletListener();
   1.110 +      mListener->SetFrame(this);
   1.111 +    }
   1.112 +
   1.113 +    bool needNewRequest = true;
   1.114 +
   1.115 +    if (mImageRequest) {
   1.116 +      // Reload the image, maybe...
   1.117 +      nsCOMPtr<nsIURI> oldURI;
   1.118 +      mImageRequest->GetURI(getter_AddRefs(oldURI));
   1.119 +      nsCOMPtr<nsIURI> newURI;
   1.120 +      newRequest->GetURI(getter_AddRefs(newURI));
   1.121 +      if (oldURI && newURI) {
   1.122 +        bool same;
   1.123 +        newURI->Equals(oldURI, &same);
   1.124 +        if (same) {
   1.125 +          needNewRequest = false;
   1.126 +        }
   1.127 +      }
   1.128 +    }
   1.129 +
   1.130 +    if (needNewRequest) {
   1.131 +      nsRefPtr<imgRequestProxy> oldRequest = mImageRequest;
   1.132 +      newRequest->Clone(mListener, getter_AddRefs(mImageRequest));
   1.133 +
   1.134 +      // Deregister the old request. We wait until after Clone is done in case
   1.135 +      // the old request and the new request are the same underlying image
   1.136 +      // accessed via different URLs.
   1.137 +      if (oldRequest) {
   1.138 +        nsLayoutUtils::DeregisterImageRequest(PresContext(), oldRequest,
   1.139 +                                              &mRequestRegistered);
   1.140 +        oldRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
   1.141 +        oldRequest = nullptr;
   1.142 +      }
   1.143 +
   1.144 +      // Register the new request.
   1.145 +      if (mImageRequest) {
   1.146 +        nsLayoutUtils::RegisterImageRequestIfAnimated(PresContext(),
   1.147 +                                                      mImageRequest,
   1.148 +                                                      &mRequestRegistered);
   1.149 +      }
   1.150 +    }
   1.151 +  } else {
   1.152 +    // No image request on the new style context
   1.153 +    if (mImageRequest) {
   1.154 +      nsLayoutUtils::DeregisterImageRequest(PresContext(), mImageRequest,
   1.155 +                                            &mRequestRegistered);
   1.156 +
   1.157 +      mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
   1.158 +      mImageRequest = nullptr;
   1.159 +    }
   1.160 +  }
   1.161 +
   1.162 +#ifdef ACCESSIBILITY
   1.163 +  // Update the list bullet accessible. If old style list isn't available then
   1.164 +  // no need to update the accessible tree because it's not created yet.
   1.165 +  if (aOldStyleContext) {
   1.166 +    nsAccessibilityService* accService = nsIPresShell::AccService();
   1.167 +    if (accService) {
   1.168 +      const nsStyleList* oldStyleList = aOldStyleContext->PeekStyleList();
   1.169 +      if (oldStyleList) {
   1.170 +        bool hadBullet = oldStyleList->GetListStyleImage() ||
   1.171 +            oldStyleList->mListStyleType != NS_STYLE_LIST_STYLE_NONE;
   1.172 +
   1.173 +        const nsStyleList* newStyleList = StyleList();
   1.174 +        bool hasBullet = newStyleList->GetListStyleImage() ||
   1.175 +            newStyleList->mListStyleType != NS_STYLE_LIST_STYLE_NONE;
   1.176 +
   1.177 +        if (hadBullet != hasBullet) {
   1.178 +          accService->UpdateListBullet(PresContext()->GetPresShell(), mContent,
   1.179 +                                       hasBullet);
   1.180 +        }
   1.181 +      }
   1.182 +    }
   1.183 +  }
   1.184 +#endif
   1.185 +}
   1.186 +
   1.187 +class nsDisplayBulletGeometry : public nsDisplayItemGenericGeometry
   1.188 +{
   1.189 +public:
   1.190 +  nsDisplayBulletGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
   1.191 +    : nsDisplayItemGenericGeometry(aItem, aBuilder)
   1.192 +  {
   1.193 +    nsBulletFrame* f = static_cast<nsBulletFrame*>(aItem->Frame());
   1.194 +    mOrdinal = f->GetOrdinal();
   1.195 +  }
   1.196 +
   1.197 +  int32_t mOrdinal;
   1.198 +};
   1.199 +
   1.200 +class nsDisplayBullet : public nsDisplayItem {
   1.201 +public:
   1.202 +  nsDisplayBullet(nsDisplayListBuilder* aBuilder, nsBulletFrame* aFrame) :
   1.203 +    nsDisplayItem(aBuilder, aFrame) {
   1.204 +    MOZ_COUNT_CTOR(nsDisplayBullet);
   1.205 +  }
   1.206 +#ifdef NS_BUILD_REFCNT_LOGGING
   1.207 +  virtual ~nsDisplayBullet() {
   1.208 +    MOZ_COUNT_DTOR(nsDisplayBullet);
   1.209 +  }
   1.210 +#endif
   1.211 +
   1.212 +  virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
   1.213 +                           bool* aSnap) MOZ_OVERRIDE
   1.214 +  {
   1.215 +    *aSnap = false;
   1.216 +    return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
   1.217 +  }
   1.218 +  virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
   1.219 +                       HitTestState* aState,
   1.220 +                       nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE {
   1.221 +    aOutFrames->AppendElement(mFrame);
   1.222 +  }
   1.223 +  virtual void Paint(nsDisplayListBuilder* aBuilder,
   1.224 +                     nsRenderingContext* aCtx) MOZ_OVERRIDE;
   1.225 +  NS_DISPLAY_DECL_NAME("Bullet", TYPE_BULLET)
   1.226 +
   1.227 +  virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
   1.228 +  {
   1.229 +    bool snap;
   1.230 +    return GetBounds(aBuilder, &snap);
   1.231 +  }
   1.232 +
   1.233 +  virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
   1.234 +  {
   1.235 +    return new nsDisplayBulletGeometry(this, aBuilder);
   1.236 +  }
   1.237 +
   1.238 +  virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
   1.239 +                                         const nsDisplayItemGeometry* aGeometry,
   1.240 +                                         nsRegion *aInvalidRegion) MOZ_OVERRIDE
   1.241 +  {
   1.242 +    const nsDisplayBulletGeometry* geometry = static_cast<const nsDisplayBulletGeometry*>(aGeometry);
   1.243 +    nsBulletFrame* f = static_cast<nsBulletFrame*>(mFrame);
   1.244 +
   1.245 +    if (f->GetOrdinal() != geometry->mOrdinal) {
   1.246 +      bool snap;
   1.247 +      aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &snap));
   1.248 +      return;
   1.249 +    }
   1.250 +
   1.251 +    nsCOMPtr<imgIContainer> image = f->GetImage();
   1.252 +    if (aBuilder->ShouldSyncDecodeImages() && image && !image->IsDecoded()) {
   1.253 +      // If we are going to do a sync decode and we are not decoded then we are
   1.254 +      // going to be drawing something different from what is currently there,
   1.255 +      // so we add our bounds to the invalid region.
   1.256 +      bool snap;
   1.257 +      aInvalidRegion->Or(*aInvalidRegion, GetBounds(aBuilder, &snap));
   1.258 +    }
   1.259 +
   1.260 +    return nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
   1.261 +  }
   1.262 +};
   1.263 +
   1.264 +void nsDisplayBullet::Paint(nsDisplayListBuilder* aBuilder,
   1.265 +                            nsRenderingContext* aCtx)
   1.266 +{
   1.267 +  uint32_t flags = imgIContainer::FLAG_NONE;
   1.268 +  if (aBuilder->ShouldSyncDecodeImages()) {
   1.269 +    flags |= imgIContainer::FLAG_SYNC_DECODE;
   1.270 +  }
   1.271 +  static_cast<nsBulletFrame*>(mFrame)->
   1.272 +    PaintBullet(*aCtx, ToReferenceFrame(), mVisibleRect, flags);
   1.273 +}
   1.274 +
   1.275 +void
   1.276 +nsBulletFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
   1.277 +                                const nsRect&           aDirtyRect,
   1.278 +                                const nsDisplayListSet& aLists)
   1.279 +{
   1.280 +  if (!IsVisibleForPainting(aBuilder))
   1.281 +    return;
   1.282 +
   1.283 +  DO_GLOBAL_REFLOW_COUNT_DSP("nsBulletFrame");
   1.284 +  
   1.285 +  aLists.Content()->AppendNewToTop(
   1.286 +    new (aBuilder) nsDisplayBullet(aBuilder, this));
   1.287 +}
   1.288 +
   1.289 +void
   1.290 +nsBulletFrame::PaintBullet(nsRenderingContext& aRenderingContext, nsPoint aPt,
   1.291 +                           const nsRect& aDirtyRect, uint32_t aFlags)
   1.292 +{
   1.293 +  const nsStyleList* myList = StyleList();
   1.294 +  uint8_t listStyleType = myList->mListStyleType;
   1.295 +
   1.296 +  if (myList->GetListStyleImage() && mImageRequest) {
   1.297 +    uint32_t status;
   1.298 +    mImageRequest->GetImageStatus(&status);
   1.299 +    if (status & imgIRequest::STATUS_LOAD_COMPLETE &&
   1.300 +        !(status & imgIRequest::STATUS_ERROR)) {
   1.301 +      nsCOMPtr<imgIContainer> imageCon;
   1.302 +      mImageRequest->GetImage(getter_AddRefs(imageCon));
   1.303 +      if (imageCon) {
   1.304 +        nsRect dest(mPadding.left, mPadding.top,
   1.305 +                    mRect.width - (mPadding.left + mPadding.right),
   1.306 +                    mRect.height - (mPadding.top + mPadding.bottom));
   1.307 +        nsLayoutUtils::DrawSingleImage(&aRenderingContext,
   1.308 +             imageCon, nsLayoutUtils::GetGraphicsFilterForFrame(this),
   1.309 +             dest + aPt, aDirtyRect, nullptr, aFlags);
   1.310 +        return;
   1.311 +      }
   1.312 +    }
   1.313 +  }
   1.314 +
   1.315 +  nsRefPtr<nsFontMetrics> fm;
   1.316 +  aRenderingContext.SetColor(nsLayoutUtils::GetColor(this, eCSSProperty_color));
   1.317 +
   1.318 +  mTextIsRTL = false;
   1.319 +
   1.320 +  nsAutoString text;
   1.321 +  switch (listStyleType) {
   1.322 +  case NS_STYLE_LIST_STYLE_NONE:
   1.323 +    break;
   1.324 +
   1.325 +  default:
   1.326 +  case NS_STYLE_LIST_STYLE_DISC:
   1.327 +    aRenderingContext.FillEllipse(mPadding.left + aPt.x, mPadding.top + aPt.y,
   1.328 +                                  mRect.width - (mPadding.left + mPadding.right),
   1.329 +                                  mRect.height - (mPadding.top + mPadding.bottom));
   1.330 +    break;
   1.331 +
   1.332 +  case NS_STYLE_LIST_STYLE_CIRCLE:
   1.333 +    aRenderingContext.DrawEllipse(mPadding.left + aPt.x, mPadding.top + aPt.y,
   1.334 +                                  mRect.width - (mPadding.left + mPadding.right),
   1.335 +                                  mRect.height - (mPadding.top + mPadding.bottom));
   1.336 +    break;
   1.337 +
   1.338 +  case NS_STYLE_LIST_STYLE_SQUARE:
   1.339 +    {
   1.340 +      nsRect rect(aPt, mRect.Size());
   1.341 +      rect.Deflate(mPadding);
   1.342 +
   1.343 +      // Snap the height and the width of the rectangle to device pixels,
   1.344 +      // and then center the result within the original rectangle, so that
   1.345 +      // all square bullets at the same font size have the same visual
   1.346 +      // size (bug 376690).
   1.347 +      // FIXME: We should really only do this if we're not transformed
   1.348 +      // (like gfxContext::UserToDevicePixelSnapped does).
   1.349 +      nsPresContext *pc = PresContext();
   1.350 +      nsRect snapRect(rect.x, rect.y, 
   1.351 +                      pc->RoundAppUnitsToNearestDevPixels(rect.width),
   1.352 +                      pc->RoundAppUnitsToNearestDevPixels(rect.height));
   1.353 +      snapRect.MoveBy((rect.width - snapRect.width) / 2,
   1.354 +                      (rect.height - snapRect.height) / 2);
   1.355 +      aRenderingContext.FillRect(snapRect.x, snapRect.y,
   1.356 +                                 snapRect.width, snapRect.height);
   1.357 +    }
   1.358 +    break;
   1.359 +
   1.360 +  case NS_STYLE_LIST_STYLE_DECIMAL:
   1.361 +  case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO:
   1.362 +  case NS_STYLE_LIST_STYLE_CJK_DECIMAL:
   1.363 +  case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
   1.364 +  case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
   1.365 +  case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
   1.366 +  case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
   1.367 +  case NS_STYLE_LIST_STYLE_LOWER_GREEK:
   1.368 +  case NS_STYLE_LIST_STYLE_HEBREW:
   1.369 +  case NS_STYLE_LIST_STYLE_ARMENIAN:
   1.370 +  case NS_STYLE_LIST_STYLE_GEORGIAN:
   1.371 +  case NS_STYLE_LIST_STYLE_CJK_IDEOGRAPHIC:
   1.372 +  case NS_STYLE_LIST_STYLE_HIRAGANA:
   1.373 +  case NS_STYLE_LIST_STYLE_KATAKANA:
   1.374 +  case NS_STYLE_LIST_STYLE_HIRAGANA_IROHA:
   1.375 +  case NS_STYLE_LIST_STYLE_KATAKANA_IROHA:
   1.376 +  case NS_STYLE_LIST_STYLE_JAPANESE_INFORMAL:
   1.377 +  case NS_STYLE_LIST_STYLE_JAPANESE_FORMAL:
   1.378 +  case NS_STYLE_LIST_STYLE_KOREAN_HANGUL_FORMAL:
   1.379 +  case NS_STYLE_LIST_STYLE_KOREAN_HANJA_INFORMAL:
   1.380 +  case NS_STYLE_LIST_STYLE_KOREAN_HANJA_FORMAL:
   1.381 +  case NS_STYLE_LIST_STYLE_SIMP_CHINESE_INFORMAL:
   1.382 +  case NS_STYLE_LIST_STYLE_SIMP_CHINESE_FORMAL:
   1.383 +  case NS_STYLE_LIST_STYLE_TRAD_CHINESE_INFORMAL:
   1.384 +  case NS_STYLE_LIST_STYLE_TRAD_CHINESE_FORMAL:
   1.385 +  case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_INFORMAL: 
   1.386 +  case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_FORMAL: 
   1.387 +  case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_INFORMAL: 
   1.388 +  case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_FORMAL: 
   1.389 +  case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_INFORMAL: 
   1.390 +  case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_FORMAL: 
   1.391 +  case NS_STYLE_LIST_STYLE_MOZ_CJK_HEAVENLY_STEM:
   1.392 +  case NS_STYLE_LIST_STYLE_MOZ_CJK_EARTHLY_BRANCH:
   1.393 +  case NS_STYLE_LIST_STYLE_MOZ_ARABIC_INDIC:
   1.394 +  case NS_STYLE_LIST_STYLE_MOZ_PERSIAN:
   1.395 +  case NS_STYLE_LIST_STYLE_MOZ_URDU:
   1.396 +  case NS_STYLE_LIST_STYLE_MOZ_DEVANAGARI:
   1.397 +  case NS_STYLE_LIST_STYLE_MOZ_GURMUKHI:
   1.398 +  case NS_STYLE_LIST_STYLE_MOZ_GUJARATI:
   1.399 +  case NS_STYLE_LIST_STYLE_MOZ_ORIYA:
   1.400 +  case NS_STYLE_LIST_STYLE_MOZ_KANNADA:
   1.401 +  case NS_STYLE_LIST_STYLE_MOZ_MALAYALAM:
   1.402 +  case NS_STYLE_LIST_STYLE_MOZ_BENGALI:
   1.403 +  case NS_STYLE_LIST_STYLE_MOZ_TAMIL:
   1.404 +  case NS_STYLE_LIST_STYLE_MOZ_TELUGU:
   1.405 +  case NS_STYLE_LIST_STYLE_MOZ_THAI:
   1.406 +  case NS_STYLE_LIST_STYLE_MOZ_LAO:
   1.407 +  case NS_STYLE_LIST_STYLE_MOZ_MYANMAR:
   1.408 +  case NS_STYLE_LIST_STYLE_MOZ_KHMER:
   1.409 +  case NS_STYLE_LIST_STYLE_MOZ_HANGUL:
   1.410 +  case NS_STYLE_LIST_STYLE_MOZ_HANGUL_CONSONANT:
   1.411 +  case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME:
   1.412 +  case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_NUMERIC:
   1.413 +  case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_AM:
   1.414 +  case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ER:
   1.415 +  case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ET:
   1.416 +    nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
   1.417 +                                          GetFontSizeInflation());
   1.418 +    GetListItemText(*myList, text);
   1.419 +    aRenderingContext.SetFont(fm);
   1.420 +    nscoord ascent = fm->MaxAscent();
   1.421 +    aRenderingContext.SetTextRunRTL(mTextIsRTL);
   1.422 +    aRenderingContext.DrawString(text, mPadding.left + aPt.x,
   1.423 +                                 mPadding.top + aPt.y + ascent);
   1.424 +    break;
   1.425 +  }
   1.426 +}
   1.427 +
   1.428 +int32_t
   1.429 +nsBulletFrame::SetListItemOrdinal(int32_t aNextOrdinal,
   1.430 +                                  bool* aChanged,
   1.431 +                                  int32_t aIncrement)
   1.432 +{
   1.433 +  MOZ_ASSERT(aIncrement == 1 || aIncrement == -1,
   1.434 +             "We shouldn't have weird increments here");
   1.435 +
   1.436 +  // Assume that the ordinal comes from the caller
   1.437 +  int32_t oldOrdinal = mOrdinal;
   1.438 +  mOrdinal = aNextOrdinal;
   1.439 +
   1.440 +  // Try to get value directly from the list-item, if it specifies a
   1.441 +  // value attribute. Note: we do this with our parent's content
   1.442 +  // because our parent is the list-item.
   1.443 +  nsIContent* parentContent = mParent->GetContent();
   1.444 +  if (parentContent) {
   1.445 +    nsGenericHTMLElement *hc =
   1.446 +      nsGenericHTMLElement::FromContent(parentContent);
   1.447 +    if (hc) {
   1.448 +      const nsAttrValue* attr = hc->GetParsedAttr(nsGkAtoms::value);
   1.449 +      if (attr && attr->Type() == nsAttrValue::eInteger) {
   1.450 +        // Use ordinal specified by the value attribute
   1.451 +        mOrdinal = attr->GetIntegerValue();
   1.452 +      }
   1.453 +    }
   1.454 +  }
   1.455 +
   1.456 +  *aChanged = oldOrdinal != mOrdinal;
   1.457 +
   1.458 +  return nsCounterManager::IncrementCounter(mOrdinal, aIncrement);
   1.459 +}
   1.460 +
   1.461 +
   1.462 +// XXX change roman/alpha to use unsigned math so that maxint and
   1.463 +// maxnegint will work
   1.464 +
   1.465 +/**
   1.466 + * For all functions below, a return value of true means that we
   1.467 + * could represent mOrder in the desired numbering system.  false
   1.468 + * means we had to fall back to decimal
   1.469 + */
   1.470 +static bool DecimalToText(int32_t ordinal, nsString& result)
   1.471 +{
   1.472 +   char cbuf[40];
   1.473 +   PR_snprintf(cbuf, sizeof(cbuf), "%ld", ordinal);
   1.474 +   result.AppendASCII(cbuf);
   1.475 +   return true;
   1.476 +}
   1.477 +static bool DecimalLeadingZeroToText(int32_t ordinal, nsString& result)
   1.478 +{
   1.479 +   char cbuf[40];
   1.480 +   PR_snprintf(cbuf, sizeof(cbuf), "%02ld", ordinal);
   1.481 +   result.AppendASCII(cbuf);
   1.482 +   return true;
   1.483 +}
   1.484 +static bool OtherDecimalToText(int32_t ordinal, char16_t zeroChar, nsString& result)
   1.485 +{
   1.486 +   char16_t diff = zeroChar - char16_t('0');
   1.487 +   // We're going to be appending to whatever is in "result" already, so make
   1.488 +   // sure to only munge the new bits.  Note that we can't just grab the pointer
   1.489 +   // to the new stuff here, since appending to the string can realloc.
   1.490 +   size_t offset = result.Length();
   1.491 +   DecimalToText(ordinal, result);
   1.492 +   char16_t* p = result.BeginWriting() + offset;
   1.493 +   if (ordinal < 0) {
   1.494 +     // skip the leading '-'
   1.495 +     ++p;
   1.496 +   }     
   1.497 +   for(; '\0' != *p ; p++) 
   1.498 +      *p += diff;
   1.499 +   return true;
   1.500 +}
   1.501 +static bool TamilToText(int32_t ordinal,  nsString& result)
   1.502 +{
   1.503 +   if (ordinal < 1 || ordinal > 9999) {
   1.504 +     // Can't do those in this system.
   1.505 +     return false;
   1.506 +   }
   1.507 +   char16_t diff = 0x0BE6 - char16_t('0');
   1.508 +   // We're going to be appending to whatever is in "result" already, so make
   1.509 +   // sure to only munge the new bits.  Note that we can't just grab the pointer
   1.510 +   // to the new stuff here, since appending to the string can realloc.
   1.511 +   size_t offset = result.Length();
   1.512 +   DecimalToText(ordinal, result); 
   1.513 +   char16_t* p = result.BeginWriting() + offset;
   1.514 +   for(; '\0' != *p ; p++) 
   1.515 +      if(*p != char16_t('0'))
   1.516 +         *p += diff;
   1.517 +   return true;
   1.518 +}
   1.519 +
   1.520 +
   1.521 +static const char gLowerRomanCharsA[] = "ixcm";
   1.522 +static const char gUpperRomanCharsA[] = "IXCM";
   1.523 +static const char gLowerRomanCharsB[] = "vld";
   1.524 +static const char gUpperRomanCharsB[] = "VLD";
   1.525 +
   1.526 +static bool RomanToText(int32_t ordinal, nsString& result, const char* achars, const char* bchars)
   1.527 +{
   1.528 +  if (ordinal < 1 || ordinal > 3999) {
   1.529 +    return false;
   1.530 +  }
   1.531 +  nsAutoString addOn, decStr;
   1.532 +  decStr.AppendInt(ordinal, 10);
   1.533 +  int len = decStr.Length();
   1.534 +  const char16_t* dp = decStr.get();
   1.535 +  const char16_t* end = dp + len;
   1.536 +  int romanPos = len;
   1.537 +  int n;
   1.538 +
   1.539 +  for (; dp < end; dp++) {
   1.540 +    romanPos--;
   1.541 +    addOn.SetLength(0);
   1.542 +    switch(*dp) {
   1.543 +      case '3':
   1.544 +        addOn.Append(char16_t(achars[romanPos]));
   1.545 +        // FALLTHROUGH
   1.546 +      case '2':
   1.547 +        addOn.Append(char16_t(achars[romanPos]));
   1.548 +        // FALLTHROUGH
   1.549 +      case '1':
   1.550 +        addOn.Append(char16_t(achars[romanPos]));
   1.551 +        break;
   1.552 +      case '4':
   1.553 +        addOn.Append(char16_t(achars[romanPos]));
   1.554 +        // FALLTHROUGH
   1.555 +      case '5': case '6':
   1.556 +      case '7': case '8':
   1.557 +        addOn.Append(char16_t(bchars[romanPos]));
   1.558 +        for(n=0;'5'+n<*dp;n++) {
   1.559 +          addOn.Append(char16_t(achars[romanPos]));
   1.560 +        }
   1.561 +        break;
   1.562 +      case '9':
   1.563 +        addOn.Append(char16_t(achars[romanPos]));
   1.564 +        addOn.Append(char16_t(achars[romanPos+1]));
   1.565 +        break;
   1.566 +      default:
   1.567 +        break;
   1.568 +    }
   1.569 +    result.Append(addOn);
   1.570 +  }
   1.571 +  return true;
   1.572 +}
   1.573 +
   1.574 +#define ALPHA_SIZE 26
   1.575 +static const char16_t gLowerAlphaChars[ALPHA_SIZE]  = 
   1.576 +{
   1.577 +0x0061, 0x0062, 0x0063, 0x0064, 0x0065, // A   B   C   D   E
   1.578 +0x0066, 0x0067, 0x0068, 0x0069, 0x006A, // F   G   H   I   J
   1.579 +0x006B, 0x006C, 0x006D, 0x006E, 0x006F, // K   L   M   N   O
   1.580 +0x0070, 0x0071, 0x0072, 0x0073, 0x0074, // P   Q   R   S   T
   1.581 +0x0075, 0x0076, 0x0077, 0x0078, 0x0079, // U   V   W   X   Y
   1.582 +0x007A                                  // Z
   1.583 +};
   1.584 +
   1.585 +static const char16_t gUpperAlphaChars[ALPHA_SIZE]  = 
   1.586 +{
   1.587 +0x0041, 0x0042, 0x0043, 0x0044, 0x0045, // A   B   C   D   E
   1.588 +0x0046, 0x0047, 0x0048, 0x0049, 0x004A, // F   G   H   I   J
   1.589 +0x004B, 0x004C, 0x004D, 0x004E, 0x004F, // K   L   M   N   O
   1.590 +0x0050, 0x0051, 0x0052, 0x0053, 0x0054, // P   Q   R   S   T
   1.591 +0x0055, 0x0056, 0x0057, 0x0058, 0x0059, // U   V   W   X   Y
   1.592 +0x005A                                  // Z
   1.593 +};
   1.594 +
   1.595 +
   1.596 +#define KATAKANA_CHARS_SIZE 48
   1.597 +// Page 94 Writing Systems of The World
   1.598 +// after modification by momoi
   1.599 +static const char16_t gKatakanaChars[KATAKANA_CHARS_SIZE] =
   1.600 +{
   1.601 +0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, //  a    i   u    e    o
   1.602 +0x30AB, 0x30AD, 0x30AF, 0x30B1, 0x30B3, // ka   ki  ku   ke   ko
   1.603 +0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, // sa  shi  su   se   so
   1.604 +0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, // ta  chi tsu   te   to
   1.605 +0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, // na   ni  nu   ne   no
   1.606 +0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, // ha   hi  hu   he   ho
   1.607 +0x30DE, 0x30DF, 0x30E0, 0x30E1, 0x30E2, // ma   mi  mu   me   mo
   1.608 +0x30E4,         0x30E6,         0x30E8, // ya       yu        yo 
   1.609 +0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, // ra   ri  ru   re   ro
   1.610 +0x30EF, 0x30F0,         0x30F1, 0x30F2, // wa (w)i     (w)e (w)o
   1.611 +0x30F3                                  //  n
   1.612 +};
   1.613 +
   1.614 +#define HIRAGANA_CHARS_SIZE 48 
   1.615 +static const char16_t gHiraganaChars[HIRAGANA_CHARS_SIZE] =
   1.616 +{
   1.617 +0x3042, 0x3044, 0x3046, 0x3048, 0x304A, //  a    i    u    e    o
   1.618 +0x304B, 0x304D, 0x304F, 0x3051, 0x3053, // ka   ki   ku   ke   ko
   1.619 +0x3055, 0x3057, 0x3059, 0x305B, 0x305D, // sa  shi   su   se   so
   1.620 +0x305F, 0x3061, 0x3064, 0x3066, 0x3068, // ta  chi  tsu   te   to
   1.621 +0x306A, 0x306B, 0x306C, 0x306D, 0x306E, // na   ni   nu   ne   no
   1.622 +0x306F, 0x3072, 0x3075, 0x3078, 0x307B, // ha   hi   hu   he   ho
   1.623 +0x307E, 0x307F, 0x3080, 0x3081, 0x3082, // ma   mi   mu   me   mo
   1.624 +0x3084,         0x3086,         0x3088, // ya        yu       yo 
   1.625 +0x3089, 0x308A, 0x308B, 0x308C, 0x308D, // ra   ri   ru   re   ro
   1.626 +0x308F, 0x3090,         0x3091, 0x3092, // wa (w)i      (w)e (w)o
   1.627 +0x3093                                  // n
   1.628 +};
   1.629 +
   1.630 +
   1.631 +#define HIRAGANA_IROHA_CHARS_SIZE 47
   1.632 +// Page 94 Writing Systems of The World
   1.633 +static const char16_t gHiraganaIrohaChars[HIRAGANA_IROHA_CHARS_SIZE] =
   1.634 +{
   1.635 +0x3044, 0x308D, 0x306F, 0x306B, 0x307B, //  i   ro   ha   ni   ho
   1.636 +0x3078, 0x3068, 0x3061, 0x308A, 0x306C, // he   to  chi   ri   nu
   1.637 +0x308B, 0x3092, 0x308F, 0x304B, 0x3088, // ru (w)o   wa   ka   yo
   1.638 +0x305F, 0x308C, 0x305D, 0x3064, 0x306D, // ta   re   so  tsu   ne
   1.639 +0x306A, 0x3089, 0x3080, 0x3046, 0x3090, // na   ra   mu    u (w)i
   1.640 +0x306E, 0x304A, 0x304F, 0x3084, 0x307E, // no    o   ku   ya   ma
   1.641 +0x3051, 0x3075, 0x3053, 0x3048, 0x3066, // ke   hu   ko    e   te
   1.642 +0x3042, 0x3055, 0x304D, 0x3086, 0x3081, //  a   sa   ki   yu   me
   1.643 +0x307F, 0x3057, 0x3091, 0x3072, 0x3082, // mi  shi (w)e   hi   mo 
   1.644 +0x305B, 0x3059                          // se   su
   1.645 +};
   1.646 +
   1.647 +#define KATAKANA_IROHA_CHARS_SIZE 47
   1.648 +static const char16_t gKatakanaIrohaChars[KATAKANA_IROHA_CHARS_SIZE] =
   1.649 +{
   1.650 +0x30A4, 0x30ED, 0x30CF, 0x30CB, 0x30DB, //  i   ro   ha   ni   ho
   1.651 +0x30D8, 0x30C8, 0x30C1, 0x30EA, 0x30CC, // he   to  chi   ri   nu
   1.652 +0x30EB, 0x30F2, 0x30EF, 0x30AB, 0x30E8, // ru (w)o   wa   ka   yo
   1.653 +0x30BF, 0x30EC, 0x30BD, 0x30C4, 0x30CD, // ta   re   so  tsu   ne
   1.654 +0x30CA, 0x30E9, 0x30E0, 0x30A6, 0x30F0, // na   ra   mu    u (w)i
   1.655 +0x30CE, 0x30AA, 0x30AF, 0x30E4, 0x30DE, // no    o   ku   ya   ma
   1.656 +0x30B1, 0x30D5, 0x30B3, 0x30A8, 0x30C6, // ke   hu   ko    e   te
   1.657 +0x30A2, 0x30B5, 0x30AD, 0x30E6, 0x30E1, //  a   sa   ki   yu   me
   1.658 +0x30DF, 0x30B7, 0x30F1, 0x30D2, 0x30E2, // mi  shi (w)e   hi   mo 
   1.659 +0x30BB, 0x30B9                          // se   su
   1.660 +};
   1.661 +
   1.662 +#define LOWER_GREEK_CHARS_SIZE 24
   1.663 +// Note: 0x03C2 GREEK FINAL SIGMA is not used in here....
   1.664 +static const char16_t gLowerGreekChars[LOWER_GREEK_CHARS_SIZE] =
   1.665 +{
   1.666 +0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, // alpha  beta  gamma  delta  epsilon
   1.667 +0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, // zeta   eta   theta  iota   kappa   
   1.668 +0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, // lamda  mu    nu     xi     omicron 
   1.669 +0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5, // pi     rho   sigma  tau    upsilon 
   1.670 +0x03C6, 0x03C7, 0x03C8, 0x03C9          // phi    chi   psi    omega    
   1.671 +};
   1.672 +
   1.673 +#define CJK_HEAVENLY_STEM_CHARS_SIZE 10 
   1.674 +static const char16_t gCJKHeavenlyStemChars[CJK_HEAVENLY_STEM_CHARS_SIZE] =
   1.675 +{
   1.676 +0x7532, 0x4e59, 0x4e19, 0x4e01, 0x620a,
   1.677 +0x5df1, 0x5e9a, 0x8f9b, 0x58ec, 0x7678
   1.678 +};
   1.679 +#define CJK_EARTHLY_BRANCH_CHARS_SIZE 12 
   1.680 +static const char16_t gCJKEarthlyBranchChars[CJK_EARTHLY_BRANCH_CHARS_SIZE] =
   1.681 +{
   1.682 +0x5b50, 0x4e11, 0x5bc5, 0x536f, 0x8fb0, 0x5df3,
   1.683 +0x5348, 0x672a, 0x7533, 0x9149, 0x620c, 0x4ea5
   1.684 +};
   1.685 +#define HANGUL_CHARS_SIZE 14 
   1.686 +static const char16_t gHangulChars[HANGUL_CHARS_SIZE] =
   1.687 +{
   1.688 +0xac00, 0xb098, 0xb2e4, 0xb77c, 0xb9c8, 0xbc14,
   1.689 +0xc0ac, 0xc544, 0xc790, 0xcc28, 0xce74, 0xd0c0,
   1.690 +0xd30c, 0xd558
   1.691 +};
   1.692 +#define HANGUL_CONSONANT_CHARS_SIZE 14 
   1.693 +static const char16_t gHangulConsonantChars[HANGUL_CONSONANT_CHARS_SIZE] =
   1.694 +{                                      
   1.695 +0x3131, 0x3134, 0x3137, 0x3139, 0x3141, 0x3142,
   1.696 +0x3145, 0x3147, 0x3148, 0x314a, 0x314b, 0x314c,
   1.697 +0x314d, 0x314e
   1.698 +};
   1.699 +
   1.700 +// Ge'ez set of Ethiopic ordered list. There are other locale-dependent sets.
   1.701 +// For the time being, let's implement two Ge'ez sets only
   1.702 +// per Momoi san's suggestion in bug 102252. 
   1.703 +// For details, refer to http://www.ethiopic.org/Collation/OrderedLists.html.
   1.704 +#define ETHIOPIC_HALEHAME_CHARS_SIZE 26
   1.705 +static const char16_t gEthiopicHalehameChars[ETHIOPIC_HALEHAME_CHARS_SIZE] =
   1.706 +{                                      
   1.707 +0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228,
   1.708 +0x1230, 0x1240, 0x1260, 0x1270, 0x1280, 0x1290,
   1.709 +0x12a0, 0x12a8, 0x12c8, 0x12d0, 0x12d8, 0x12e8,
   1.710 +0x12f0, 0x1308, 0x1320, 0x1330, 0x1338, 0x1340,
   1.711 +0x1348, 0x1350
   1.712 +};
   1.713 +#define ETHIOPIC_HALEHAME_AM_CHARS_SIZE 33
   1.714 +static const char16_t gEthiopicHalehameAmChars[ETHIOPIC_HALEHAME_AM_CHARS_SIZE] =
   1.715 +{                                      
   1.716 +0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228,
   1.717 +0x1230, 0x1238, 0x1240, 0x1260, 0x1270, 0x1278,
   1.718 +0x1280, 0x1290, 0x1298, 0x12a0, 0x12a8, 0x12b8,
   1.719 +0x12c8, 0x12d0, 0x12d8, 0x12e0, 0x12e8, 0x12f0,
   1.720 +0x1300, 0x1308, 0x1320, 0x1328, 0x1330, 0x1338,
   1.721 +0x1340, 0x1348, 0x1350
   1.722 +};
   1.723 +#define ETHIOPIC_HALEHAME_TI_ER_CHARS_SIZE 31
   1.724 +static const char16_t gEthiopicHalehameTiErChars[ETHIOPIC_HALEHAME_TI_ER_CHARS_SIZE] =
   1.725 +{                                      
   1.726 +0x1200, 0x1208, 0x1210, 0x1218, 0x1228, 0x1230,
   1.727 +0x1238, 0x1240, 0x1250, 0x1260, 0x1270, 0x1278,
   1.728 +0x1290, 0x1298, 0x12a0, 0x12a8, 0x12b8, 0x12c8,
   1.729 +0x12d0, 0x12d8, 0x12e0, 0x12e8, 0x12f0, 0x1300,
   1.730 +0x1308, 0x1320, 0x1328, 0x1330, 0x1338, 0x1348,
   1.731 +0x1350
   1.732 +};
   1.733 +#define ETHIOPIC_HALEHAME_TI_ET_CHARS_SIZE 34
   1.734 +static const char16_t gEthiopicHalehameTiEtChars[ETHIOPIC_HALEHAME_TI_ET_CHARS_SIZE] =
   1.735 +{                                      
   1.736 +0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228,
   1.737 +0x1230, 0x1238, 0x1240, 0x1250, 0x1260, 0x1270,
   1.738 +0x1278, 0x1280, 0x1290, 0x1298, 0x12a0, 0x12a8,
   1.739 +0x12b8, 0x12c8, 0x12d0, 0x12d8, 0x12e0, 0x12e8,
   1.740 +0x12f0, 0x1300, 0x1308, 0x1320, 0x1328, 0x1330,
   1.741 +0x1338, 0x1340, 0x1348, 0x1350
   1.742 +};
   1.743 +
   1.744 +
   1.745 +// We know cjk-ideographic need 31 characters to display 99,999,999,999,999,999
   1.746 +// georgian needs 6 at most
   1.747 +// armenian needs 12 at most
   1.748 +// hebrew may need more...
   1.749 +
   1.750 +#define NUM_BUF_SIZE 34 
   1.751 +
   1.752 +static bool CharListToText(int32_t ordinal, nsString& result, const char16_t* chars, int32_t aBase)
   1.753 +{
   1.754 +  char16_t buf[NUM_BUF_SIZE];
   1.755 +  int32_t idx = NUM_BUF_SIZE;
   1.756 +  if (ordinal < 1) {
   1.757 +    return false;
   1.758 +  }
   1.759 +  do {
   1.760 +    ordinal--; // a == 0
   1.761 +    int32_t cur = ordinal % aBase;
   1.762 +    buf[--idx] = chars[cur];
   1.763 +    ordinal /= aBase ;
   1.764 +  } while ( ordinal > 0);
   1.765 +  result.Append(buf+idx,NUM_BUF_SIZE-idx);
   1.766 +  return true;
   1.767 +}
   1.768 +
   1.769 +static const char16_t gCJKDecimalChars[10] =
   1.770 +{
   1.771 +  0x3007, 0x4e00, 0x4e8c, 0x4e09, 0x56db,
   1.772 +  0x4e94, 0x516d, 0x4e03, 0x516b, 0x4e5d
   1.773 +};
   1.774 +static bool CharListDecimalToText(int32_t ordinal, nsString& result, const char16_t* chars)
   1.775 +{
   1.776 +  if (ordinal < 0) {
   1.777 +    return false;
   1.778 +  }
   1.779 +  char16_t buf[NUM_BUF_SIZE];
   1.780 +  int32_t idx = NUM_BUF_SIZE;
   1.781 +  do {
   1.782 +    buf[--idx] = chars[ordinal % 10];
   1.783 +    ordinal /= 10;
   1.784 +  } while (ordinal > 0);
   1.785 +  result.Append(buf + idx, NUM_BUF_SIZE - idx);
   1.786 +  return true;
   1.787 +}
   1.788 +
   1.789 +enum CJKIdeographicLang {
   1.790 +  CHINESE, KOREAN, JAPANESE
   1.791 +};
   1.792 +struct CJKIdeographicData {
   1.793 +  const char16_t *negative;
   1.794 +  char16_t digit[10];
   1.795 +  char16_t unit[3];
   1.796 +  char16_t unit10K[2];
   1.797 +  uint8_t lang;
   1.798 +  bool informal;
   1.799 +};
   1.800 +static const char16_t gJapaneseNegative[] = {
   1.801 +  0x30de, 0x30a4, 0x30ca, 0x30b9, 0x0000
   1.802 +};
   1.803 +static const CJKIdeographicData gDataJapaneseInformal = {
   1.804 +  gJapaneseNegative,          // negative
   1.805 +  {                           // digit
   1.806 +    0x3007, 0x4e00, 0x4e8c, 0x4e09, 0x56db,
   1.807 +    0x4e94, 0x516d, 0x4e03, 0x516b, 0x4e5d
   1.808 +  },
   1.809 +  { 0x5341, 0x767e, 0x5343 }, // unit
   1.810 +  { 0x4e07, 0x5104 },         // unit10K
   1.811 +  JAPANESE,                   // lang
   1.812 +  true                        // informal
   1.813 +};
   1.814 +static const CJKIdeographicData gDataJapaneseFormal = {
   1.815 +  gJapaneseNegative,          // negative
   1.816 +  {                           // digit
   1.817 +    0x96f6, 0x58f1, 0x5f10, 0x53c2, 0x56db,
   1.818 +    0x4f0d, 0x516d, 0x4e03, 0x516b, 0x4e5d
   1.819 +  },
   1.820 +  { 0x62fe, 0x767e, 0x9621 }, // unit
   1.821 +  { 0x842c, 0x5104 },         // unit10K
   1.822 +  JAPANESE,                   // lang
   1.823 +  false                       // informal
   1.824 +};
   1.825 +static const char16_t gKoreanNegative[] = {
   1.826 +  0xb9c8, 0xc774, 0xb108, 0xc2a4, 0x0020, 0x0000
   1.827 +};
   1.828 +static const CJKIdeographicData gDataKoreanHangulFormal = {
   1.829 +  gKoreanNegative,            // negative
   1.830 +  {                           // digit
   1.831 +    0xc601, 0xc77c, 0xc774, 0xc0bc, 0xc0ac,
   1.832 +    0xc624, 0xc721, 0xce60, 0xd314, 0xad6c
   1.833 +  },
   1.834 +  { 0xc2ed, 0xbc31, 0xcc9c }, // unit
   1.835 +  { 0xb9cc, 0xc5b5 },         // unit10K
   1.836 +  KOREAN,                     // lang
   1.837 +  false                       // informal
   1.838 +};
   1.839 +static const CJKIdeographicData gDataKoreanHanjaInformal = {
   1.840 +  gKoreanNegative,            // negative
   1.841 +  {                           // digit
   1.842 +    0x96f6, 0x4e00, 0x4e8c, 0x4e09, 0x56db,
   1.843 +    0x4e94, 0x516d, 0x4e03, 0x516b, 0x4e5d
   1.844 +  },
   1.845 +  { 0x5341, 0x767e, 0x5343 }, // unit
   1.846 +  { 0x842c, 0x5104 },         // unit10K
   1.847 +  KOREAN,                     // lang
   1.848 +  true                        // informal
   1.849 +};
   1.850 +static const CJKIdeographicData gDataKoreanHanjaFormal = {
   1.851 +  gKoreanNegative,            // negative
   1.852 +  {                           // digit
   1.853 +    0x96f6, 0x58f9, 0x8cb3, 0x53c3, 0x56db,
   1.854 +    0x4e94, 0x516d, 0x4e03, 0x516b, 0x4e5d
   1.855 +  },
   1.856 +  { 0x62fe, 0x767e, 0x4edf }, // unit
   1.857 +  { 0x842c, 0x5104 },         // unit10K
   1.858 +  KOREAN,                     // lang
   1.859 +  false                       // informal
   1.860 +};
   1.861 +static const char16_t gSimpChineseNegative[] = {
   1.862 +  0x8d1f, 0x0000
   1.863 +};
   1.864 +static const CJKIdeographicData gDataSimpChineseInformal = {
   1.865 +  gSimpChineseNegative,       // negative
   1.866 +  {                           // digit
   1.867 +    0x96f6, 0x4e00, 0x4e8c, 0x4e09, 0x56db,
   1.868 +    0x4e94, 0x516d, 0x4e03, 0x516b, 0x4e5d
   1.869 +  },
   1.870 +  { 0x5341, 0x767e, 0x5343 }, // unit
   1.871 +  { 0x4e07, 0x4ebf },         // unit10K
   1.872 +  CHINESE,                    // lang
   1.873 +  true                        // informal
   1.874 +};
   1.875 +static const CJKIdeographicData gDataSimpChineseFormal = {
   1.876 +  gSimpChineseNegative,       // negative
   1.877 +  {                           // digit
   1.878 +    0x96f6, 0x58f9, 0x8d30, 0x53c1, 0x8086,
   1.879 +    0x4f0d, 0x9646, 0x67d2, 0x634c, 0x7396
   1.880 +  },
   1.881 +  { 0x62fe, 0x4f70, 0x4edf }, // unit
   1.882 +  { 0x4e07, 0x4ebf },         // unit10K
   1.883 +  CHINESE,                    // lang
   1.884 +  false                       // informal
   1.885 +};
   1.886 +static const char16_t gTradChineseNegative[] = {
   1.887 +  0x8ca0, 0x0000
   1.888 +};
   1.889 +static const CJKIdeographicData gDataTradChineseInformal = {
   1.890 +  gTradChineseNegative,       // negative
   1.891 +  {                           // digit
   1.892 +    0x96f6, 0x4e00, 0x4e8c, 0x4e09, 0x56db,
   1.893 +    0x4e94, 0x516d, 0x4e03, 0x516b, 0x4e5d
   1.894 +  },
   1.895 +  { 0x5341, 0x767e, 0x5343 }, // unit
   1.896 +  { 0x842c, 0x5104 },         // unit10K
   1.897 +  CHINESE,                    // lang
   1.898 +  true                        // informal
   1.899 +};
   1.900 +static const CJKIdeographicData gDataTradChineseFormal = {
   1.901 +  gTradChineseNegative,       // negative
   1.902 +  {                           // digit
   1.903 +    0x96f6, 0x58f9, 0x8cb3, 0x53c3, 0x8086,
   1.904 +    0x4f0d, 0x9678, 0x67d2, 0x634c, 0x7396
   1.905 +  },
   1.906 +  { 0x62fe, 0x4f70, 0x4edf }, // unit
   1.907 +  { 0x842c, 0x5104 },         // unit10K
   1.908 +  CHINESE,                    // lang
   1.909 +  false                       // informal
   1.910 +};
   1.911 +
   1.912 +static const bool CJKIdeographicToText(int32_t aOrdinal, nsString& result,
   1.913 +                                       const CJKIdeographicData& data)
   1.914 +{
   1.915 +  char16_t buf[NUM_BUF_SIZE];
   1.916 +  int32_t idx = NUM_BUF_SIZE;
   1.917 +  int32_t pos = 0;
   1.918 +  bool isNegative = (aOrdinal < 0);
   1.919 +  bool needZero = (aOrdinal == 0);
   1.920 +  int32_t unitidx = 0, unit10Kidx = 0;
   1.921 +  uint32_t ordinal = mozilla::Abs(aOrdinal);
   1.922 +  do {
   1.923 +    unitidx = pos % 4;
   1.924 +    if (unitidx == 0) {
   1.925 +      unit10Kidx = pos / 4;
   1.926 +    }
   1.927 +    int32_t cur = ordinal % 10;
   1.928 +    if (cur == 0) {
   1.929 +      if (needZero) {
   1.930 +        needZero = false;
   1.931 +        buf[--idx] = data.digit[0];
   1.932 +      }
   1.933 +    } else {
   1.934 +      if (data.lang == CHINESE) {
   1.935 +        needZero = true;
   1.936 +      }
   1.937 +      if (unit10Kidx != 0) {
   1.938 +        if (data.lang == KOREAN && idx != NUM_BUF_SIZE) {
   1.939 +          buf[--idx] = ' ';
   1.940 +        }
   1.941 +        buf[--idx] = data.unit10K[unit10Kidx - 1];
   1.942 +      }
   1.943 +      if (unitidx != 0) {
   1.944 +        buf[--idx] = data.unit[unitidx - 1];
   1.945 +      }
   1.946 +      if (cur != 1) {
   1.947 +        buf[--idx] = data.digit[cur];
   1.948 +      } else {
   1.949 +        bool needOne = true;
   1.950 +        if (data.informal) {
   1.951 +          switch (data.lang) {
   1.952 +            case CHINESE:
   1.953 +              if (unitidx == 1 &&
   1.954 +                  (ordinal == 1 || (pos > 4 && ordinal % 1000 == 1))) {
   1.955 +                needOne = false;
   1.956 +              }
   1.957 +              break;
   1.958 +            case JAPANESE:
   1.959 +              if (unitidx > 0 &&
   1.960 +                  (unitidx != 3 || (pos == 3 && ordinal == 1))) {
   1.961 +                needOne = false;
   1.962 +              }
   1.963 +              break;
   1.964 +            case KOREAN:
   1.965 +              if (unitidx > 0 || (pos == 4 && (ordinal % 1000) == 1)) {
   1.966 +                needOne = false;
   1.967 +              }
   1.968 +              break;
   1.969 +          }
   1.970 +        }
   1.971 +        if (needOne) {
   1.972 +          buf[--idx] = data.digit[1];
   1.973 +        }
   1.974 +      }
   1.975 +      unit10Kidx = 0;
   1.976 +    }
   1.977 +    ordinal /= 10;
   1.978 +    pos++;
   1.979 +  } while (ordinal > 0);
   1.980 +  if (isNegative) {
   1.981 +    result.Append(data.negative);
   1.982 +  }
   1.983 +  result.Append(buf + idx, NUM_BUF_SIZE - idx);
   1.984 +  return true;
   1.985 +}
   1.986 +
   1.987 +#define HEBREW_GERESH       0x05F3
   1.988 +static const char16_t gHebrewDigit[22] = 
   1.989 +{
   1.990 +//   1       2       3       4       5       6       7       8       9
   1.991 +0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8,
   1.992 +//  10      20      30      40      50      60      70      80      90
   1.993 +0x05D9, 0x05DB, 0x05DC, 0x05DE, 0x05E0, 0x05E1, 0x05E2, 0x05E4, 0x05E6,
   1.994 +// 100     200     300     400
   1.995 +0x05E7, 0x05E8, 0x05E9, 0x05EA
   1.996 +};
   1.997 +
   1.998 +static bool HebrewToText(int32_t ordinal, nsString& result)
   1.999 +{
  1.1000 +  if (ordinal < 1 || ordinal > 999999) {
  1.1001 +    return false;
  1.1002 +  }
  1.1003 +  bool outputSep = false;
  1.1004 +  nsAutoString allText, thousandsGroup;
  1.1005 +  do {
  1.1006 +    thousandsGroup.Truncate();
  1.1007 +    int32_t n3 = ordinal % 1000;
  1.1008 +    // Process digit for 100 - 900
  1.1009 +    for(int32_t n1 = 400; n1 > 0; )
  1.1010 +    {
  1.1011 +      if( n3 >= n1)
  1.1012 +      {
  1.1013 +        n3 -= n1;
  1.1014 +        thousandsGroup.Append(gHebrewDigit[(n1/100)-1+18]);
  1.1015 +      } else {
  1.1016 +        n1 -= 100;
  1.1017 +      } // if
  1.1018 +    } // for
  1.1019 +
  1.1020 +    // Process digit for 10 - 90
  1.1021 +    int32_t n2;
  1.1022 +    if( n3 >= 10 )
  1.1023 +    {
  1.1024 +      // Special process for 15 and 16
  1.1025 +      if(( 15 == n3 ) || (16 == n3)) {
  1.1026 +        // Special rule for religious reason...
  1.1027 +        // 15 is represented by 9 and 6, not 10 and 5
  1.1028 +        // 16 is represented by 9 and 7, not 10 and 6
  1.1029 +        n2 = 9;
  1.1030 +        thousandsGroup.Append(gHebrewDigit[ n2 - 1]);
  1.1031 +      } else {
  1.1032 +        n2 = n3 - (n3 % 10);
  1.1033 +        thousandsGroup.Append(gHebrewDigit[(n2/10)-1+9]);
  1.1034 +      } // if
  1.1035 +      n3 -= n2;
  1.1036 +    } // if
  1.1037 +  
  1.1038 +    // Process digit for 1 - 9 
  1.1039 +    if ( n3 > 0)
  1.1040 +      thousandsGroup.Append(gHebrewDigit[n3-1]);
  1.1041 +    if (outputSep) 
  1.1042 +      thousandsGroup.Append((char16_t)HEBREW_GERESH);
  1.1043 +    if (allText.IsEmpty())
  1.1044 +      allText = thousandsGroup;
  1.1045 +    else
  1.1046 +      allText = thousandsGroup + allText;
  1.1047 +    ordinal /= 1000;
  1.1048 +    outputSep = true;
  1.1049 +  } while (ordinal >= 1);
  1.1050 +
  1.1051 +  result.Append(allText);
  1.1052 +  return true;
  1.1053 +}
  1.1054 +
  1.1055 +
  1.1056 +static bool ArmenianToText(int32_t ordinal, nsString& result)
  1.1057 +{
  1.1058 +  if (ordinal < 1 || ordinal > 9999) { // zero or reach the limit of Armenian numbering system
  1.1059 +    return false;
  1.1060 +  }
  1.1061 +
  1.1062 +  char16_t buf[NUM_BUF_SIZE];
  1.1063 +  int32_t idx = NUM_BUF_SIZE;
  1.1064 +  int32_t d = 0;
  1.1065 +  do {
  1.1066 +    int32_t cur = ordinal % 10;
  1.1067 +    if (cur > 0)
  1.1068 +    {
  1.1069 +      char16_t u = 0x0530 + (d * 9) + cur;
  1.1070 +      buf[--idx] = u;
  1.1071 +    }
  1.1072 +    ++d;
  1.1073 +    ordinal /= 10;
  1.1074 +  } while (ordinal > 0);
  1.1075 +  result.Append(buf + idx, NUM_BUF_SIZE - idx);
  1.1076 +  return true;
  1.1077 +}
  1.1078 +
  1.1079 +
  1.1080 +static const char16_t gGeorgianValue [ 37 ] = { // 4 * 9 + 1 = 37
  1.1081 +//      1       2       3       4       5       6       7       8       9
  1.1082 +   0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10F1, 0x10D7,
  1.1083 +//     10      20      30      40      50      60      70      80      90
  1.1084 +   0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10F2, 0x10DD, 0x10DE, 0x10DF,
  1.1085 +//    100     200     300     400     500     600     700     800     900
  1.1086 +   0x10E0, 0x10E1, 0x10E2, 0x10F3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, 0x10E8,
  1.1087 +//   1000    2000    3000    4000    5000    6000    7000    8000    9000
  1.1088 +   0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10F4, 0x10EF, 0x10F0,
  1.1089 +//  10000
  1.1090 +   0x10F5
  1.1091 +};
  1.1092 +static bool GeorgianToText(int32_t ordinal, nsString& result)
  1.1093 +{
  1.1094 +  if (ordinal < 1 || ordinal > 19999) { // zero or reach the limit of Georgian numbering system
  1.1095 +    return false;
  1.1096 +  }
  1.1097 +
  1.1098 +  char16_t buf[NUM_BUF_SIZE];
  1.1099 +  int32_t idx = NUM_BUF_SIZE;
  1.1100 +  int32_t d = 0;
  1.1101 +  do {
  1.1102 +    int32_t cur = ordinal % 10;
  1.1103 +    if (cur > 0)
  1.1104 +    {
  1.1105 +      char16_t u = gGeorgianValue[(d * 9 ) + ( cur - 1)];
  1.1106 +      buf[--idx] = u;
  1.1107 +    }
  1.1108 +    ++d;
  1.1109 +    ordinal /= 10;
  1.1110 +  } while (ordinal > 0);
  1.1111 +  result.Append(buf + idx, NUM_BUF_SIZE - idx);
  1.1112 +  return true;
  1.1113 +}
  1.1114 +
  1.1115 +// Convert ordinal to Ethiopic numeric representation.
  1.1116 +// The detail is available at http://www.ethiopic.org/Numerals/
  1.1117 +// The algorithm used here is based on the pseudo-code put up there by
  1.1118 +// Daniel Yacob <yacob@geez.org>.
  1.1119 +// Another reference is Unicode 3.0 standard section 11.1.
  1.1120 +#define ETHIOPIC_ONE             0x1369
  1.1121 +#define ETHIOPIC_TEN             0x1372
  1.1122 +#define ETHIOPIC_HUNDRED         0x137B
  1.1123 +#define ETHIOPIC_TEN_THOUSAND    0x137C
  1.1124 +
  1.1125 +static bool EthiopicToText(int32_t ordinal, nsString& result)
  1.1126 +{
  1.1127 +  if (ordinal < 1) {
  1.1128 +    return false;
  1.1129 +  }
  1.1130 +  nsAutoString asciiNumberString;      // decimal string representation of ordinal
  1.1131 +  DecimalToText(ordinal, asciiNumberString);
  1.1132 +  uint8_t asciiStringLength = asciiNumberString.Length();
  1.1133 +
  1.1134 +  // If number length is odd, add a leading "0"
  1.1135 +  // the leading "0" preconditions the string to always have the
  1.1136 +  // leading tens place populated, this avoids a check within the loop.
  1.1137 +  // If we didn't add the leading "0", decrement asciiStringLength so
  1.1138 +  // it will be equivalent to a zero-based index in both cases.
  1.1139 +  if (asciiStringLength & 1) {
  1.1140 +    asciiNumberString.Insert(NS_LITERAL_STRING("0"), 0);
  1.1141 +  } else {
  1.1142 +    asciiStringLength--;
  1.1143 +  }
  1.1144 +
  1.1145 +  // Iterate from the highest digits to lowest
  1.1146 +  // indexFromLeft       indexes digits (0 = most significant)
  1.1147 +  // groupIndexFromRight indexes pairs of digits (0 = least significant)
  1.1148 +  for (uint8_t indexFromLeft = 0, groupIndexFromRight = asciiStringLength >> 1;
  1.1149 +       indexFromLeft <= asciiStringLength;
  1.1150 +       indexFromLeft += 2, groupIndexFromRight--) {
  1.1151 +    uint8_t tensValue  = asciiNumberString.CharAt(indexFromLeft) & 0x0F;
  1.1152 +    uint8_t unitsValue = asciiNumberString.CharAt(indexFromLeft + 1) & 0x0F;
  1.1153 +    uint8_t groupValue = tensValue * 10 + unitsValue;
  1.1154 +
  1.1155 +    bool oddGroup = (groupIndexFromRight & 1);
  1.1156 +
  1.1157 +    // we want to clear ETHIOPIC_ONE when it is superfluous
  1.1158 +    if (ordinal > 1 &&
  1.1159 +        groupValue == 1 &&                  // one without a leading ten
  1.1160 +        (oddGroup || indexFromLeft == 0)) { // preceding (100) or leading the sequence
  1.1161 +      unitsValue = 0;
  1.1162 +    }
  1.1163 +
  1.1164 +    // put it all together...
  1.1165 +    if (tensValue) {
  1.1166 +      // map onto Ethiopic "tens":
  1.1167 +      result.Append((char16_t) (tensValue +  ETHIOPIC_TEN - 1));
  1.1168 +    }
  1.1169 +    if (unitsValue) {
  1.1170 +      //map onto Ethiopic "units":
  1.1171 +      result.Append((char16_t) (unitsValue + ETHIOPIC_ONE - 1));
  1.1172 +    }
  1.1173 +    // Add a separator for all even groups except the last,
  1.1174 +    // and for odd groups with non-zero value.
  1.1175 +    if (oddGroup) {
  1.1176 +      if (groupValue) {
  1.1177 +        result.Append((char16_t) ETHIOPIC_HUNDRED);
  1.1178 +      }
  1.1179 +    } else {
  1.1180 +      if (groupIndexFromRight) {
  1.1181 +        result.Append((char16_t) ETHIOPIC_TEN_THOUSAND);
  1.1182 +      }
  1.1183 +    }
  1.1184 +  }
  1.1185 +  return true;
  1.1186 +}
  1.1187 +
  1.1188 +
  1.1189 +/* static */ void
  1.1190 +nsBulletFrame::AppendCounterText(int32_t aListStyleType,
  1.1191 +                                 int32_t aOrdinal,
  1.1192 +                                 nsString& result,
  1.1193 +                                 bool& isRTL)
  1.1194 +{
  1.1195 +  bool success = true;
  1.1196 +  int32_t fallback = NS_STYLE_LIST_STYLE_DECIMAL;
  1.1197 +  isRTL = false;
  1.1198 +  
  1.1199 +  switch (aListStyleType) {
  1.1200 +    case NS_STYLE_LIST_STYLE_NONE: // used by counters code only
  1.1201 +      break;
  1.1202 +
  1.1203 +    case NS_STYLE_LIST_STYLE_DISC: // used by counters code only
  1.1204 +      // XXX We really need to do this the same way we do list bullets.
  1.1205 +      result.Append(char16_t(0x2022));
  1.1206 +      break;
  1.1207 +
  1.1208 +    case NS_STYLE_LIST_STYLE_CIRCLE: // used by counters code only
  1.1209 +      // XXX We really need to do this the same way we do list bullets.
  1.1210 +      result.Append(char16_t(0x25E6));
  1.1211 +      break;
  1.1212 +
  1.1213 +    case NS_STYLE_LIST_STYLE_SQUARE: // used by counters code only
  1.1214 +      // XXX We really need to do this the same way we do list bullets.
  1.1215 +      result.Append(char16_t(0x25FE));
  1.1216 +      break;
  1.1217 +
  1.1218 +    case NS_STYLE_LIST_STYLE_DECIMAL:
  1.1219 +    default: // CSS2 say "A users  agent that does not recognize a numbering system
  1.1220 +      // should use 'decimal'
  1.1221 +      success = DecimalToText(aOrdinal, result);
  1.1222 +      NS_ASSERTION(success, "DecimalToText must never fail");
  1.1223 +      break;
  1.1224 +
  1.1225 +    case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO:
  1.1226 +      success = DecimalLeadingZeroToText(aOrdinal, result);
  1.1227 +      break;
  1.1228 +
  1.1229 +    case NS_STYLE_LIST_STYLE_CJK_DECIMAL:
  1.1230 +      success = CharListDecimalToText(aOrdinal, result, gCJKDecimalChars);
  1.1231 +      break;
  1.1232 +
  1.1233 +    case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
  1.1234 +      success = RomanToText(aOrdinal, result,
  1.1235 +                            gLowerRomanCharsA, gLowerRomanCharsB);
  1.1236 +      break;
  1.1237 +    case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
  1.1238 +      success = RomanToText(aOrdinal, result,
  1.1239 +                            gUpperRomanCharsA, gUpperRomanCharsB);
  1.1240 +      break;
  1.1241 +
  1.1242 +    case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
  1.1243 +      success = CharListToText(aOrdinal, result, gLowerAlphaChars, ALPHA_SIZE);
  1.1244 +      break;
  1.1245 +
  1.1246 +    case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
  1.1247 +      success = CharListToText(aOrdinal, result, gUpperAlphaChars, ALPHA_SIZE);
  1.1248 +      break;
  1.1249 +
  1.1250 +    case NS_STYLE_LIST_STYLE_KATAKANA:
  1.1251 +      success = CharListToText(aOrdinal, result, gKatakanaChars,
  1.1252 +                               KATAKANA_CHARS_SIZE);
  1.1253 +      break;
  1.1254 +
  1.1255 +    case NS_STYLE_LIST_STYLE_HIRAGANA:
  1.1256 +      success = CharListToText(aOrdinal, result, gHiraganaChars,
  1.1257 +                               HIRAGANA_CHARS_SIZE);
  1.1258 +      break;
  1.1259 +    
  1.1260 +    case NS_STYLE_LIST_STYLE_KATAKANA_IROHA:
  1.1261 +      success = CharListToText(aOrdinal, result, gKatakanaIrohaChars,
  1.1262 +                               KATAKANA_IROHA_CHARS_SIZE);
  1.1263 +      break;
  1.1264 + 
  1.1265 +    case NS_STYLE_LIST_STYLE_HIRAGANA_IROHA:
  1.1266 +      success = CharListToText(aOrdinal, result, gHiraganaIrohaChars,
  1.1267 +                               HIRAGANA_IROHA_CHARS_SIZE);
  1.1268 +      break;
  1.1269 +
  1.1270 +    case NS_STYLE_LIST_STYLE_LOWER_GREEK:
  1.1271 +      success = CharListToText(aOrdinal, result, gLowerGreekChars ,
  1.1272 +                               LOWER_GREEK_CHARS_SIZE);
  1.1273 +      break;
  1.1274 +
  1.1275 +    case NS_STYLE_LIST_STYLE_CJK_IDEOGRAPHIC: 
  1.1276 +    case NS_STYLE_LIST_STYLE_TRAD_CHINESE_INFORMAL:
  1.1277 +    case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_INFORMAL: 
  1.1278 +      fallback = NS_STYLE_LIST_STYLE_CJK_DECIMAL;
  1.1279 +      success =
  1.1280 +        CJKIdeographicToText(aOrdinal, result, gDataTradChineseInformal);
  1.1281 +      break;
  1.1282 +
  1.1283 +    case NS_STYLE_LIST_STYLE_TRAD_CHINESE_FORMAL:
  1.1284 +    case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_FORMAL: 
  1.1285 +      fallback = NS_STYLE_LIST_STYLE_CJK_DECIMAL;
  1.1286 +      success = CJKIdeographicToText(aOrdinal, result, gDataTradChineseFormal);
  1.1287 +      break;
  1.1288 +
  1.1289 +    case NS_STYLE_LIST_STYLE_SIMP_CHINESE_INFORMAL:
  1.1290 +    case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_INFORMAL: 
  1.1291 +      fallback = NS_STYLE_LIST_STYLE_CJK_DECIMAL;
  1.1292 +      success =
  1.1293 +        CJKIdeographicToText(aOrdinal, result, gDataSimpChineseInformal);
  1.1294 +      break;
  1.1295 +
  1.1296 +    case NS_STYLE_LIST_STYLE_SIMP_CHINESE_FORMAL:
  1.1297 +    case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_FORMAL: 
  1.1298 +      fallback = NS_STYLE_LIST_STYLE_CJK_DECIMAL;
  1.1299 +      success = CJKIdeographicToText(aOrdinal, result, gDataSimpChineseFormal);
  1.1300 +      break;
  1.1301 +
  1.1302 +    case NS_STYLE_LIST_STYLE_JAPANESE_INFORMAL:
  1.1303 +    case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_INFORMAL: 
  1.1304 +      fallback = NS_STYLE_LIST_STYLE_CJK_DECIMAL;
  1.1305 +      success = CJKIdeographicToText(aOrdinal, result, gDataJapaneseInformal);
  1.1306 +      break;
  1.1307 +
  1.1308 +    case NS_STYLE_LIST_STYLE_JAPANESE_FORMAL:
  1.1309 +    case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_FORMAL: 
  1.1310 +      fallback = NS_STYLE_LIST_STYLE_CJK_DECIMAL;
  1.1311 +      success = CJKIdeographicToText(aOrdinal, result, gDataJapaneseFormal);
  1.1312 +      break;
  1.1313 +
  1.1314 +    case NS_STYLE_LIST_STYLE_KOREAN_HANGUL_FORMAL:
  1.1315 +      fallback = NS_STYLE_LIST_STYLE_CJK_DECIMAL;
  1.1316 +      success =
  1.1317 +        CJKIdeographicToText(aOrdinal, result, gDataKoreanHangulFormal);
  1.1318 +      break;
  1.1319 +
  1.1320 +    case NS_STYLE_LIST_STYLE_KOREAN_HANJA_INFORMAL:
  1.1321 +      fallback = NS_STYLE_LIST_STYLE_CJK_DECIMAL;
  1.1322 +      success =
  1.1323 +        CJKIdeographicToText(aOrdinal, result, gDataKoreanHanjaInformal);
  1.1324 +      break;
  1.1325 +
  1.1326 +    case NS_STYLE_LIST_STYLE_KOREAN_HANJA_FORMAL:
  1.1327 +      fallback = NS_STYLE_LIST_STYLE_CJK_DECIMAL;
  1.1328 +      success = CJKIdeographicToText(aOrdinal, result, gDataKoreanHanjaFormal);
  1.1329 +      break;
  1.1330 +
  1.1331 +    case NS_STYLE_LIST_STYLE_HEBREW: 
  1.1332 +      isRTL = true;
  1.1333 +      success = HebrewToText(aOrdinal, result);
  1.1334 +      break;
  1.1335 +
  1.1336 +    case NS_STYLE_LIST_STYLE_ARMENIAN: 
  1.1337 +      success = ArmenianToText(aOrdinal, result);
  1.1338 +      break;
  1.1339 +
  1.1340 +    case NS_STYLE_LIST_STYLE_GEORGIAN: 
  1.1341 +      success = GeorgianToText(aOrdinal, result);
  1.1342 +      break;
  1.1343 + 
  1.1344 +    case NS_STYLE_LIST_STYLE_MOZ_ARABIC_INDIC:
  1.1345 +      success = OtherDecimalToText(aOrdinal, 0x0660, result);
  1.1346 +      break;
  1.1347 + 
  1.1348 +    case NS_STYLE_LIST_STYLE_MOZ_PERSIAN:
  1.1349 +    case NS_STYLE_LIST_STYLE_MOZ_URDU:
  1.1350 +      success = OtherDecimalToText(aOrdinal, 0x06f0, result);
  1.1351 +      break;
  1.1352 + 
  1.1353 +    case NS_STYLE_LIST_STYLE_MOZ_DEVANAGARI:
  1.1354 +      success = OtherDecimalToText(aOrdinal, 0x0966, result);
  1.1355 +      break;
  1.1356 + 
  1.1357 +    case NS_STYLE_LIST_STYLE_MOZ_GURMUKHI:
  1.1358 +      success = OtherDecimalToText(aOrdinal, 0x0a66, result);
  1.1359 +      break;
  1.1360 + 
  1.1361 +    case NS_STYLE_LIST_STYLE_MOZ_GUJARATI:
  1.1362 +      success = OtherDecimalToText(aOrdinal, 0x0AE6, result);
  1.1363 +      break;
  1.1364 + 
  1.1365 +    case NS_STYLE_LIST_STYLE_MOZ_ORIYA:
  1.1366 +      success = OtherDecimalToText(aOrdinal, 0x0B66, result);
  1.1367 +      break;
  1.1368 + 
  1.1369 +    case NS_STYLE_LIST_STYLE_MOZ_KANNADA:
  1.1370 +      success = OtherDecimalToText(aOrdinal, 0x0CE6, result);
  1.1371 +      break;
  1.1372 + 
  1.1373 +    case NS_STYLE_LIST_STYLE_MOZ_MALAYALAM:
  1.1374 +      success = OtherDecimalToText(aOrdinal, 0x0D66, result);
  1.1375 +      break;
  1.1376 + 
  1.1377 +    case NS_STYLE_LIST_STYLE_MOZ_THAI:
  1.1378 +      success = OtherDecimalToText(aOrdinal, 0x0E50, result);
  1.1379 +      break;
  1.1380 + 
  1.1381 +    case NS_STYLE_LIST_STYLE_MOZ_LAO:
  1.1382 +      success = OtherDecimalToText(aOrdinal, 0x0ED0, result);
  1.1383 +      break;
  1.1384 + 
  1.1385 +    case NS_STYLE_LIST_STYLE_MOZ_MYANMAR:
  1.1386 +      success = OtherDecimalToText(aOrdinal, 0x1040, result);
  1.1387 +      break;
  1.1388 + 
  1.1389 +    case NS_STYLE_LIST_STYLE_MOZ_KHMER:
  1.1390 +      success = OtherDecimalToText(aOrdinal, 0x17E0, result);
  1.1391 +      break;
  1.1392 + 
  1.1393 +    case NS_STYLE_LIST_STYLE_MOZ_BENGALI:
  1.1394 +      success = OtherDecimalToText(aOrdinal, 0x09E6, result);
  1.1395 +      break;
  1.1396 + 
  1.1397 +    case NS_STYLE_LIST_STYLE_MOZ_TELUGU:
  1.1398 +      success = OtherDecimalToText(aOrdinal, 0x0C66, result);
  1.1399 +      break;
  1.1400 + 
  1.1401 +    case NS_STYLE_LIST_STYLE_MOZ_TAMIL:
  1.1402 +      success = TamilToText(aOrdinal, result);
  1.1403 +      break;
  1.1404 +
  1.1405 +    case NS_STYLE_LIST_STYLE_MOZ_CJK_HEAVENLY_STEM:
  1.1406 +      fallback = NS_STYLE_LIST_STYLE_CJK_DECIMAL;
  1.1407 +      success = CharListToText(aOrdinal, result, gCJKHeavenlyStemChars,
  1.1408 +                               CJK_HEAVENLY_STEM_CHARS_SIZE);
  1.1409 +      break;
  1.1410 +
  1.1411 +    case NS_STYLE_LIST_STYLE_MOZ_CJK_EARTHLY_BRANCH:
  1.1412 +      fallback = NS_STYLE_LIST_STYLE_CJK_DECIMAL;
  1.1413 +      success = CharListToText(aOrdinal, result, gCJKEarthlyBranchChars,
  1.1414 +                               CJK_EARTHLY_BRANCH_CHARS_SIZE);
  1.1415 +      break;
  1.1416 +
  1.1417 +    case NS_STYLE_LIST_STYLE_MOZ_HANGUL:
  1.1418 +      success = CharListToText(aOrdinal, result, gHangulChars, HANGUL_CHARS_SIZE);
  1.1419 +      break;
  1.1420 +
  1.1421 +    case NS_STYLE_LIST_STYLE_MOZ_HANGUL_CONSONANT:
  1.1422 +      success = CharListToText(aOrdinal, result, gHangulConsonantChars,
  1.1423 +                               HANGUL_CONSONANT_CHARS_SIZE);
  1.1424 +      break;
  1.1425 +
  1.1426 +    case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME:
  1.1427 +      success = CharListToText(aOrdinal, result, gEthiopicHalehameChars,
  1.1428 +                               ETHIOPIC_HALEHAME_CHARS_SIZE);
  1.1429 +      break;
  1.1430 +
  1.1431 +    case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_NUMERIC:
  1.1432 +      success = EthiopicToText(aOrdinal, result);
  1.1433 +      break;
  1.1434 +
  1.1435 +    case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_AM:
  1.1436 +      success = CharListToText(aOrdinal, result, gEthiopicHalehameAmChars,
  1.1437 +                               ETHIOPIC_HALEHAME_AM_CHARS_SIZE);
  1.1438 +      break;
  1.1439 +
  1.1440 +    case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ER:
  1.1441 +      success = CharListToText(aOrdinal, result, gEthiopicHalehameTiErChars,
  1.1442 +                               ETHIOPIC_HALEHAME_TI_ER_CHARS_SIZE);
  1.1443 +      break;
  1.1444 +
  1.1445 +    case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ET:
  1.1446 +      success = CharListToText(aOrdinal, result, gEthiopicHalehameTiEtChars,
  1.1447 +                               ETHIOPIC_HALEHAME_TI_ET_CHARS_SIZE);
  1.1448 +      break;
  1.1449 +  }
  1.1450 +  if (!success) {
  1.1451 +    AppendCounterText(fallback, aOrdinal, result, isRTL);
  1.1452 +  }
  1.1453 +}
  1.1454 +
  1.1455 +/* static */ void
  1.1456 +nsBulletFrame::GetListItemSuffix(int32_t aListStyleType,
  1.1457 +                                 nsString& aResult,
  1.1458 +                                 bool& aSuppressPadding)
  1.1459 +{
  1.1460 +  aResult = '.';
  1.1461 +  aSuppressPadding = false;
  1.1462 +
  1.1463 +  switch (aListStyleType) {
  1.1464 +    case NS_STYLE_LIST_STYLE_NONE: // used by counters code only
  1.1465 +    case NS_STYLE_LIST_STYLE_DISC: // used by counters code only
  1.1466 +    case NS_STYLE_LIST_STYLE_CIRCLE: // used by counters code only
  1.1467 +    case NS_STYLE_LIST_STYLE_SQUARE: // used by counters code only
  1.1468 +      aResult.Truncate();
  1.1469 +      break;
  1.1470 +
  1.1471 +    case NS_STYLE_LIST_STYLE_CJK_DECIMAL:
  1.1472 +    case NS_STYLE_LIST_STYLE_CJK_IDEOGRAPHIC:
  1.1473 +    case NS_STYLE_LIST_STYLE_TRAD_CHINESE_INFORMAL:
  1.1474 +    case NS_STYLE_LIST_STYLE_TRAD_CHINESE_FORMAL:
  1.1475 +    case NS_STYLE_LIST_STYLE_SIMP_CHINESE_INFORMAL:
  1.1476 +    case NS_STYLE_LIST_STYLE_SIMP_CHINESE_FORMAL:
  1.1477 +    case NS_STYLE_LIST_STYLE_JAPANESE_INFORMAL:
  1.1478 +    case NS_STYLE_LIST_STYLE_JAPANESE_FORMAL:
  1.1479 +    case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_INFORMAL:
  1.1480 +    case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_FORMAL:
  1.1481 +    case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_INFORMAL:
  1.1482 +    case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_FORMAL:
  1.1483 +    case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_INFORMAL:
  1.1484 +    case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_FORMAL:
  1.1485 +    case NS_STYLE_LIST_STYLE_MOZ_CJK_HEAVENLY_STEM:
  1.1486 +    case NS_STYLE_LIST_STYLE_MOZ_CJK_EARTHLY_BRANCH:
  1.1487 +      aResult = 0x3001;
  1.1488 +      aSuppressPadding = true;
  1.1489 +      break;
  1.1490 +
  1.1491 +    case NS_STYLE_LIST_STYLE_KOREAN_HANGUL_FORMAL:
  1.1492 +    case NS_STYLE_LIST_STYLE_KOREAN_HANJA_INFORMAL:
  1.1493 +    case NS_STYLE_LIST_STYLE_KOREAN_HANJA_FORMAL:
  1.1494 +    case NS_STYLE_LIST_STYLE_MOZ_HANGUL:
  1.1495 +    case NS_STYLE_LIST_STYLE_MOZ_HANGUL_CONSONANT:
  1.1496 +      aResult = ',';
  1.1497 +      break;
  1.1498 +  }
  1.1499 +}
  1.1500 +
  1.1501 +void
  1.1502 +nsBulletFrame::GetListItemText(const nsStyleList& aListStyle,
  1.1503 +                               nsString& result)
  1.1504 +{
  1.1505 +  const nsStyleVisibility* vis = StyleVisibility();
  1.1506 +
  1.1507 +  NS_ASSERTION(aListStyle.mListStyleType != NS_STYLE_LIST_STYLE_NONE &&
  1.1508 +               aListStyle.mListStyleType != NS_STYLE_LIST_STYLE_DISC &&
  1.1509 +               aListStyle.mListStyleType != NS_STYLE_LIST_STYLE_CIRCLE &&
  1.1510 +               aListStyle.mListStyleType != NS_STYLE_LIST_STYLE_SQUARE,
  1.1511 +               "we should be using specialized code for these types");
  1.1512 +
  1.1513 +  result.Truncate();
  1.1514 +  AppendCounterText(aListStyle.mListStyleType, mOrdinal, result, mTextIsRTL);
  1.1515 +
  1.1516 +  nsAutoString suffix;
  1.1517 +  GetListItemSuffix(aListStyle.mListStyleType, suffix, mSuppressPadding);
  1.1518 +
  1.1519 +  // We're not going to do proper Bidi reordering on the list item marker, but
  1.1520 +  // just display the whole thing as RTL or LTR, so we fake reordering by
  1.1521 +  // appending the suffix to the end of the list item marker if the
  1.1522 +  // directionality of the characters is the same as the style direction or
  1.1523 +  // prepending it to the beginning if they are different.
  1.1524 +  result = (mTextIsRTL == (vis->mDirection == NS_STYLE_DIRECTION_RTL)) ?
  1.1525 +          result + suffix : suffix + result;
  1.1526 +}
  1.1527 +
  1.1528 +#define MIN_BULLET_SIZE 1
  1.1529 +
  1.1530 +
  1.1531 +void
  1.1532 +nsBulletFrame::GetDesiredSize(nsPresContext*  aCX,
  1.1533 +                              nsRenderingContext *aRenderingContext,
  1.1534 +                              nsHTMLReflowMetrics& aMetrics,
  1.1535 +                              float aFontSizeInflation)
  1.1536 +{
  1.1537 +  // Reset our padding.  If we need it, we'll set it below.
  1.1538 +  mPadding.SizeTo(0, 0, 0, 0);
  1.1539 +  
  1.1540 +  const nsStyleList* myList = StyleList();
  1.1541 +  nscoord ascent;
  1.1542 +
  1.1543 +  RemoveStateBits(BULLET_FRAME_IMAGE_LOADING);
  1.1544 +
  1.1545 +  if (myList->GetListStyleImage() && mImageRequest) {
  1.1546 +    uint32_t status;
  1.1547 +    mImageRequest->GetImageStatus(&status);
  1.1548 +    if (status & imgIRequest::STATUS_SIZE_AVAILABLE &&
  1.1549 +        !(status & imgIRequest::STATUS_ERROR)) {
  1.1550 +      // auto size the image
  1.1551 +      aMetrics.Width() = mIntrinsicSize.width;
  1.1552 +      aMetrics.SetTopAscent(aMetrics.Height() = mIntrinsicSize.height);
  1.1553 +
  1.1554 +      AddStateBits(BULLET_FRAME_IMAGE_LOADING);
  1.1555 +
  1.1556 +      return;
  1.1557 +    }
  1.1558 +  }
  1.1559 +
  1.1560 +  // If we're getting our desired size and don't have an image, reset
  1.1561 +  // mIntrinsicSize to (0,0).  Otherwise, if we used to have an image, it
  1.1562 +  // changed, and the new one is coming in, but we're reflowing before it's
  1.1563 +  // fully there, we'll end up with mIntrinsicSize not matching our size, but
  1.1564 +  // won't trigger a reflow in OnStartContainer (because mIntrinsicSize will
  1.1565 +  // match the image size).
  1.1566 +  mIntrinsicSize.SizeTo(0, 0);
  1.1567 +
  1.1568 +  nsRefPtr<nsFontMetrics> fm;
  1.1569 +  nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
  1.1570 +                                        aFontSizeInflation);
  1.1571 +  nscoord bulletSize;
  1.1572 +
  1.1573 +  nsAutoString text;
  1.1574 +  switch (myList->mListStyleType) {
  1.1575 +    case NS_STYLE_LIST_STYLE_NONE:
  1.1576 +      aMetrics.Width() = aMetrics.Height() = 0;
  1.1577 +      aMetrics.SetTopAscent(0);
  1.1578 +      break;
  1.1579 +
  1.1580 +    case NS_STYLE_LIST_STYLE_DISC:
  1.1581 +    case NS_STYLE_LIST_STYLE_CIRCLE:
  1.1582 +    case NS_STYLE_LIST_STYLE_SQUARE:
  1.1583 +      ascent = fm->MaxAscent();
  1.1584 +      bulletSize = std::max(nsPresContext::CSSPixelsToAppUnits(MIN_BULLET_SIZE),
  1.1585 +                          NSToCoordRound(0.8f * (float(ascent) / 2.0f)));
  1.1586 +      mPadding.bottom = NSToCoordRound(float(ascent) / 8.0f);
  1.1587 +      aMetrics.Width() = aMetrics.Height() = bulletSize;
  1.1588 +      aMetrics.SetTopAscent(bulletSize + mPadding.bottom);
  1.1589 +      break;
  1.1590 +
  1.1591 +    default:
  1.1592 +    case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO:
  1.1593 +    case NS_STYLE_LIST_STYLE_DECIMAL:
  1.1594 +    case NS_STYLE_LIST_STYLE_CJK_DECIMAL:
  1.1595 +    case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
  1.1596 +    case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
  1.1597 +    case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
  1.1598 +    case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
  1.1599 +    case NS_STYLE_LIST_STYLE_KATAKANA:
  1.1600 +    case NS_STYLE_LIST_STYLE_HIRAGANA:
  1.1601 +    case NS_STYLE_LIST_STYLE_KATAKANA_IROHA:
  1.1602 +    case NS_STYLE_LIST_STYLE_HIRAGANA_IROHA:
  1.1603 +    case NS_STYLE_LIST_STYLE_LOWER_GREEK:
  1.1604 +    case NS_STYLE_LIST_STYLE_HEBREW: 
  1.1605 +    case NS_STYLE_LIST_STYLE_ARMENIAN: 
  1.1606 +    case NS_STYLE_LIST_STYLE_GEORGIAN: 
  1.1607 +    case NS_STYLE_LIST_STYLE_CJK_IDEOGRAPHIC: 
  1.1608 +    case NS_STYLE_LIST_STYLE_JAPANESE_INFORMAL:
  1.1609 +    case NS_STYLE_LIST_STYLE_JAPANESE_FORMAL:
  1.1610 +    case NS_STYLE_LIST_STYLE_KOREAN_HANGUL_FORMAL:
  1.1611 +    case NS_STYLE_LIST_STYLE_KOREAN_HANJA_INFORMAL:
  1.1612 +    case NS_STYLE_LIST_STYLE_KOREAN_HANJA_FORMAL:
  1.1613 +    case NS_STYLE_LIST_STYLE_SIMP_CHINESE_INFORMAL:
  1.1614 +    case NS_STYLE_LIST_STYLE_SIMP_CHINESE_FORMAL:
  1.1615 +    case NS_STYLE_LIST_STYLE_TRAD_CHINESE_INFORMAL:
  1.1616 +    case NS_STYLE_LIST_STYLE_TRAD_CHINESE_FORMAL:
  1.1617 +    case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_INFORMAL: 
  1.1618 +    case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_FORMAL: 
  1.1619 +    case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_INFORMAL: 
  1.1620 +    case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_FORMAL: 
  1.1621 +    case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_INFORMAL: 
  1.1622 +    case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_FORMAL: 
  1.1623 +    case NS_STYLE_LIST_STYLE_MOZ_CJK_HEAVENLY_STEM:
  1.1624 +    case NS_STYLE_LIST_STYLE_MOZ_CJK_EARTHLY_BRANCH:
  1.1625 +    case NS_STYLE_LIST_STYLE_MOZ_ARABIC_INDIC:
  1.1626 +    case NS_STYLE_LIST_STYLE_MOZ_PERSIAN:
  1.1627 +    case NS_STYLE_LIST_STYLE_MOZ_URDU:
  1.1628 +    case NS_STYLE_LIST_STYLE_MOZ_DEVANAGARI:
  1.1629 +    case NS_STYLE_LIST_STYLE_MOZ_GURMUKHI:
  1.1630 +    case NS_STYLE_LIST_STYLE_MOZ_GUJARATI:
  1.1631 +    case NS_STYLE_LIST_STYLE_MOZ_ORIYA:
  1.1632 +    case NS_STYLE_LIST_STYLE_MOZ_KANNADA:
  1.1633 +    case NS_STYLE_LIST_STYLE_MOZ_MALAYALAM:
  1.1634 +    case NS_STYLE_LIST_STYLE_MOZ_BENGALI:
  1.1635 +    case NS_STYLE_LIST_STYLE_MOZ_TAMIL:
  1.1636 +    case NS_STYLE_LIST_STYLE_MOZ_TELUGU:
  1.1637 +    case NS_STYLE_LIST_STYLE_MOZ_THAI:
  1.1638 +    case NS_STYLE_LIST_STYLE_MOZ_LAO:
  1.1639 +    case NS_STYLE_LIST_STYLE_MOZ_MYANMAR:
  1.1640 +    case NS_STYLE_LIST_STYLE_MOZ_KHMER:
  1.1641 +    case NS_STYLE_LIST_STYLE_MOZ_HANGUL:
  1.1642 +    case NS_STYLE_LIST_STYLE_MOZ_HANGUL_CONSONANT:
  1.1643 +    case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME:
  1.1644 +    case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_NUMERIC:
  1.1645 +    case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_AM:
  1.1646 +    case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ER:
  1.1647 +    case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ET:
  1.1648 +      GetListItemText(*myList, text);
  1.1649 +      aMetrics.Height() = fm->MaxHeight();
  1.1650 +      aRenderingContext->SetFont(fm);
  1.1651 +      aMetrics.Width() =
  1.1652 +        nsLayoutUtils::GetStringWidth(this, aRenderingContext,
  1.1653 +                                      text.get(), text.Length());
  1.1654 +      aMetrics.SetTopAscent(fm->MaxAscent());
  1.1655 +      break;
  1.1656 +  }
  1.1657 +}
  1.1658 +
  1.1659 +nsresult
  1.1660 +nsBulletFrame::Reflow(nsPresContext* aPresContext,
  1.1661 +                      nsHTMLReflowMetrics& aMetrics,
  1.1662 +                      const nsHTMLReflowState& aReflowState,
  1.1663 +                      nsReflowStatus& aStatus)
  1.1664 +{
  1.1665 +  DO_GLOBAL_REFLOW_COUNT("nsBulletFrame");
  1.1666 +  DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
  1.1667 +
  1.1668 +  float inflation = nsLayoutUtils::FontSizeInflationFor(this);
  1.1669 +  SetFontSizeInflation(inflation);
  1.1670 +
  1.1671 +  // Get the base size
  1.1672 +  // This will also set mSuppressPadding appropriately (via GetListItemText())
  1.1673 +  // for the builtin counter styles with ideographic comma as suffix where the
  1.1674 +  // default padding from ua.css is not desired.
  1.1675 +  GetDesiredSize(aPresContext, aReflowState.rendContext, aMetrics, inflation);
  1.1676 +
  1.1677 +  // Add in the border and padding; split the top/bottom between the
  1.1678 +  // ascent and descent to make things look nice
  1.1679 +  const nsMargin& borderPadding = aReflowState.ComputedPhysicalBorderPadding();
  1.1680 +  if (!mSuppressPadding ||
  1.1681 +      aPresContext->HasAuthorSpecifiedRules(this,
  1.1682 +                                            NS_AUTHOR_SPECIFIED_PADDING)) {
  1.1683 +    mPadding.top += NSToCoordRound(borderPadding.top * inflation);
  1.1684 +    mPadding.right += NSToCoordRound(borderPadding.right * inflation);
  1.1685 +    mPadding.bottom += NSToCoordRound(borderPadding.bottom * inflation);
  1.1686 +    mPadding.left += NSToCoordRound(borderPadding.left * inflation);
  1.1687 +  }
  1.1688 +  aMetrics.Width() += mPadding.left + mPadding.right;
  1.1689 +  aMetrics.Height() += mPadding.top + mPadding.bottom;
  1.1690 +  aMetrics.SetTopAscent(aMetrics.TopAscent() + mPadding.top);
  1.1691 +
  1.1692 +  // XXX this is a bit of a hack, we're assuming that no glyphs used for bullets
  1.1693 +  // overflow their font-boxes. It'll do for now; to fix it for real, we really
  1.1694 +  // should rewrite all the text-handling code here to use gfxTextRun (bug
  1.1695 +  // 397294).
  1.1696 +  aMetrics.SetOverflowAreasToDesiredBounds();
  1.1697 +
  1.1698 +  aStatus = NS_FRAME_COMPLETE;
  1.1699 +  NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
  1.1700 +  return NS_OK;
  1.1701 +}
  1.1702 +
  1.1703 +/* virtual */ nscoord
  1.1704 +nsBulletFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
  1.1705 +{
  1.1706 +  nsHTMLReflowMetrics metrics(GetWritingMode());
  1.1707 +  DISPLAY_MIN_WIDTH(this, metrics.Width());
  1.1708 +  GetDesiredSize(PresContext(), aRenderingContext, metrics, 1.0f);
  1.1709 +  return metrics.Width();
  1.1710 +}
  1.1711 +
  1.1712 +/* virtual */ nscoord
  1.1713 +nsBulletFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
  1.1714 +{
  1.1715 +  nsHTMLReflowMetrics metrics(GetWritingMode());
  1.1716 +  DISPLAY_PREF_WIDTH(this, metrics.Width());
  1.1717 +  GetDesiredSize(PresContext(), aRenderingContext, metrics, 1.0f);
  1.1718 +  return metrics.Width();
  1.1719 +}
  1.1720 +
  1.1721 +NS_IMETHODIMP
  1.1722 +nsBulletFrame::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
  1.1723 +{
  1.1724 +  if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
  1.1725 +    nsCOMPtr<imgIContainer> image;
  1.1726 +    aRequest->GetImage(getter_AddRefs(image));
  1.1727 +    return OnStartContainer(aRequest, image);
  1.1728 +  }
  1.1729 +
  1.1730 +  if (aType == imgINotificationObserver::FRAME_UPDATE) {
  1.1731 +    // The image has changed.
  1.1732 +    // Invalidate the entire content area. Maybe it's not optimal but it's simple and
  1.1733 +    // always correct, and I'll be a stunned mullet if it ever matters for performance
  1.1734 +    InvalidateFrame();
  1.1735 +  }
  1.1736 +
  1.1737 +  if (aType == imgINotificationObserver::IS_ANIMATED) {
  1.1738 +    // Register the image request with the refresh driver now that we know it's
  1.1739 +    // animated.
  1.1740 +    if (aRequest == mImageRequest) {
  1.1741 +      nsLayoutUtils::RegisterImageRequest(PresContext(), mImageRequest,
  1.1742 +                                          &mRequestRegistered);
  1.1743 +    }
  1.1744 +  }
  1.1745 +
  1.1746 +  return NS_OK;
  1.1747 +}
  1.1748 +
  1.1749 +nsresult nsBulletFrame::OnStartContainer(imgIRequest *aRequest,
  1.1750 +                                         imgIContainer *aImage)
  1.1751 +{
  1.1752 +  if (!aImage) return NS_ERROR_INVALID_ARG;
  1.1753 +  if (!aRequest) return NS_ERROR_INVALID_ARG;
  1.1754 +
  1.1755 +  uint32_t status;
  1.1756 +  aRequest->GetImageStatus(&status);
  1.1757 +  if (status & imgIRequest::STATUS_ERROR) {
  1.1758 +    return NS_OK;
  1.1759 +  }
  1.1760 +  
  1.1761 +  nscoord w, h;
  1.1762 +  aImage->GetWidth(&w);
  1.1763 +  aImage->GetHeight(&h);
  1.1764 +
  1.1765 +  nsPresContext* presContext = PresContext();
  1.1766 +
  1.1767 +  nsSize newsize(nsPresContext::CSSPixelsToAppUnits(w),
  1.1768 +                 nsPresContext::CSSPixelsToAppUnits(h));
  1.1769 +
  1.1770 +  if (mIntrinsicSize != newsize) {
  1.1771 +    mIntrinsicSize = newsize;
  1.1772 +
  1.1773 +    // Now that the size is available (or an error occurred), trigger
  1.1774 +    // a reflow of the bullet frame.
  1.1775 +    nsIPresShell *shell = presContext->GetPresShell();
  1.1776 +    if (shell) {
  1.1777 +      shell->FrameNeedsReflow(this, nsIPresShell::eStyleChange,
  1.1778 +                              NS_FRAME_IS_DIRTY);
  1.1779 +    }
  1.1780 +  }
  1.1781 +
  1.1782 +  // Handle animations
  1.1783 +  aImage->SetAnimationMode(presContext->ImageAnimationMode());
  1.1784 +  // Ensure the animation (if any) is started. Note: There is no
  1.1785 +  // corresponding call to Decrement for this. This Increment will be
  1.1786 +  // 'cleaned up' by the Request when it is destroyed, but only then.
  1.1787 +  aRequest->IncrementAnimationConsumers();
  1.1788 +  
  1.1789 +  return NS_OK;
  1.1790 +}
  1.1791 +
  1.1792 +void
  1.1793 +nsBulletFrame::GetLoadGroup(nsPresContext *aPresContext, nsILoadGroup **aLoadGroup)
  1.1794 +{
  1.1795 +  if (!aPresContext)
  1.1796 +    return;
  1.1797 +
  1.1798 +  NS_PRECONDITION(nullptr != aLoadGroup, "null OUT parameter pointer");
  1.1799 +
  1.1800 +  nsIPresShell *shell = aPresContext->GetPresShell();
  1.1801 +
  1.1802 +  if (!shell)
  1.1803 +    return;
  1.1804 +
  1.1805 +  nsIDocument *doc = shell->GetDocument();
  1.1806 +  if (!doc)
  1.1807 +    return;
  1.1808 +
  1.1809 +  *aLoadGroup = doc->GetDocumentLoadGroup().take();
  1.1810 +}
  1.1811 +
  1.1812 +union VoidPtrOrFloat {
  1.1813 +  VoidPtrOrFloat() : p(nullptr) {}
  1.1814 +
  1.1815 +  void *p;
  1.1816 +  float f;
  1.1817 +};
  1.1818 +
  1.1819 +float
  1.1820 +nsBulletFrame::GetFontSizeInflation() const
  1.1821 +{
  1.1822 +  if (!HasFontSizeInflation()) {
  1.1823 +    return 1.0f;
  1.1824 +  }
  1.1825 +  VoidPtrOrFloat u;
  1.1826 +  u.p = Properties().Get(FontSizeInflationProperty());
  1.1827 +  return u.f;
  1.1828 +}
  1.1829 +
  1.1830 +void
  1.1831 +nsBulletFrame::SetFontSizeInflation(float aInflation)
  1.1832 +{
  1.1833 +  if (aInflation == 1.0f) {
  1.1834 +    if (HasFontSizeInflation()) {
  1.1835 +      RemoveStateBits(BULLET_FRAME_HAS_FONT_INFLATION);
  1.1836 +      Properties().Delete(FontSizeInflationProperty());
  1.1837 +    }
  1.1838 +    return;
  1.1839 +  }
  1.1840 +
  1.1841 +  AddStateBits(BULLET_FRAME_HAS_FONT_INFLATION);
  1.1842 +  VoidPtrOrFloat u;
  1.1843 +  u.f = aInflation;
  1.1844 +  Properties().Set(FontSizeInflationProperty(), u.p);
  1.1845 +}
  1.1846 +
  1.1847 +already_AddRefed<imgIContainer>
  1.1848 +nsBulletFrame::GetImage() const
  1.1849 +{
  1.1850 +  if (mImageRequest && StyleList()->GetListStyleImage()) {
  1.1851 +    nsCOMPtr<imgIContainer> imageCon;
  1.1852 +    mImageRequest->GetImage(getter_AddRefs(imageCon));
  1.1853 +    return imageCon.forget();
  1.1854 +  }
  1.1855 +
  1.1856 +  return nullptr;
  1.1857 +}
  1.1858 +
  1.1859 +nscoord
  1.1860 +nsBulletFrame::GetBaseline() const
  1.1861 +{
  1.1862 +  nscoord ascent = 0, bottomPadding;
  1.1863 +  if (GetStateBits() & BULLET_FRAME_IMAGE_LOADING) {
  1.1864 +    ascent = GetRect().height;
  1.1865 +  } else {
  1.1866 +    nsRefPtr<nsFontMetrics> fm;
  1.1867 +    nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
  1.1868 +                                          GetFontSizeInflation());
  1.1869 +    const nsStyleList* myList = StyleList();
  1.1870 +    switch (myList->mListStyleType) {
  1.1871 +      case NS_STYLE_LIST_STYLE_NONE:
  1.1872 +        break;
  1.1873 +
  1.1874 +      case NS_STYLE_LIST_STYLE_DISC:
  1.1875 +      case NS_STYLE_LIST_STYLE_CIRCLE:
  1.1876 +      case NS_STYLE_LIST_STYLE_SQUARE:
  1.1877 +        ascent = fm->MaxAscent();
  1.1878 +        bottomPadding = NSToCoordRound(float(ascent) / 8.0f);
  1.1879 +        ascent = std::max(nsPresContext::CSSPixelsToAppUnits(MIN_BULLET_SIZE),
  1.1880 +                        NSToCoordRound(0.8f * (float(ascent) / 2.0f)));
  1.1881 +        ascent += bottomPadding;
  1.1882 +        break;
  1.1883 +
  1.1884 +      default:
  1.1885 +        ascent = fm->MaxAscent();
  1.1886 +        break;
  1.1887 +    }
  1.1888 +  }
  1.1889 +  return ascent + GetUsedBorderAndPadding().top;
  1.1890 +}
  1.1891 +
  1.1892 +
  1.1893 +
  1.1894 +
  1.1895 +
  1.1896 +
  1.1897 +
  1.1898 +
  1.1899 +NS_IMPL_ISUPPORTS(nsBulletListener, imgINotificationObserver)
  1.1900 +
  1.1901 +nsBulletListener::nsBulletListener() :
  1.1902 +  mFrame(nullptr)
  1.1903 +{
  1.1904 +}
  1.1905 +
  1.1906 +nsBulletListener::~nsBulletListener()
  1.1907 +{
  1.1908 +}
  1.1909 +
  1.1910 +NS_IMETHODIMP
  1.1911 +nsBulletListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData)
  1.1912 +{
  1.1913 +  if (!mFrame)
  1.1914 +    return NS_ERROR_FAILURE;
  1.1915 +  return mFrame->Notify(aRequest, aType, aData);
  1.1916 +}

mercurial