1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is Mozilla Communicator client code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 /* rendering object for list-item bullets */
41 #include "nsBulletFrame.h"
42 #include "nsGkAtoms.h"
43 #include "nsHTMLParts.h"
44 #include "nsHTMLContainerFrame.h"
45 #include "nsIFontMetrics.h"
46 #include "nsGenericHTMLElement.h"
47 #include "nsPresContext.h"
48 #include "nsIPresShell.h"
49 #include "nsIDocument.h"
50 #include "nsIRenderingContext.h"
51 #include "nsILoadGroup.h"
53 #include "nsNetUtil.h"
55 #include "nsDisplayList.h"
57 #include "imgILoader.h"
58 #include "imgIContainer.h"
59 #include "nsStubImageDecoderObserver.h"
61 #include "nsIServiceManager.h"
62 #include "nsIComponentManager.h"
63 #include "nsContentUtils.h"
65 class nsBulletListener
: public nsStubImageDecoderObserver
69 virtual ~nsBulletListener();
72 // imgIDecoderObserver (override nsStubImageDecoderObserver)
73 NS_IMETHOD
OnStartContainer(imgIRequest
*aRequest
, imgIContainer
*aImage
);
74 NS_IMETHOD
OnDataAvailable(imgIRequest
*aRequest
, gfxIImageFrame
*aFrame
,
76 NS_IMETHOD
OnStopDecode(imgIRequest
*aRequest
, nsresult status
,
77 const PRUnichar
*statusArg
);
78 // imgIContainerObserver (override nsStubImageDecoderObserver)
79 NS_IMETHOD
FrameChanged(imgIContainer
*aContainer
, gfxIImageFrame
*newframe
,
82 void SetFrame(nsBulletFrame
*frame
) { mFrame
= frame
; }
85 nsBulletFrame
*mFrame
;
89 nsBulletFrame::~nsBulletFrame()
94 nsBulletFrame::Destroy()
96 // Stop image loading first
98 mImageRequest
->Cancel(NS_ERROR_FAILURE
);
99 mImageRequest
= nsnull
;
103 reinterpret_cast<nsBulletListener
*>(mListener
.get())->SetFrame(nsnull
);
105 // Let base class do the rest
111 nsBulletFrame::GetFrameName(nsAString
& aResult
) const
113 return MakeFrameName(NS_LITERAL_STRING("Bullet"), aResult
);
118 nsBulletFrame::GetType() const
120 return nsGkAtoms::bulletFrame
;
124 nsBulletFrame::IsEmpty()
126 return IsSelfEmpty();
130 nsBulletFrame::IsSelfEmpty()
132 return GetStyleList()->mListStyleType
== NS_STYLE_LIST_STYLE_NONE
;
136 nsBulletFrame::DidSetStyleContext()
138 imgIRequest
*newRequest
= GetStyleList()->mListStyleImage
;
143 nsBulletListener
*listener
;
144 NS_NEWXPCOM(listener
, nsBulletListener
);
146 listener
->SetFrame(this);
147 listener
->QueryInterface(NS_GET_IID(imgIDecoderObserver
), getter_AddRefs(mListener
));
148 NS_ASSERTION(mListener
, "queryinterface for the listener failed");
149 NS_RELEASE(listener
);
152 PRBool needNewRequest
= PR_TRUE
;
155 // Reload the image, maybe...
156 nsCOMPtr
<nsIURI
> oldURI
;
157 mImageRequest
->GetURI(getter_AddRefs(oldURI
));
158 nsCOMPtr
<nsIURI
> newURI
;
159 newRequest
->GetURI(getter_AddRefs(newURI
));
160 if (oldURI
&& newURI
) {
162 newURI
->Equals(oldURI
, &same
);
164 needNewRequest
= PR_FALSE
;
166 mImageRequest
->Cancel(NS_ERROR_FAILURE
);
167 mImageRequest
= nsnull
;
172 if (needNewRequest
) {
173 newRequest
->Clone(mListener
, getter_AddRefs(mImageRequest
));
176 // No image request on the new style context
178 mImageRequest
->Cancel(NS_ERROR_FAILURE
);
179 mImageRequest
= nsnull
;
186 class nsDisplayBullet
: public nsDisplayItem
{
188 nsDisplayBullet(nsBulletFrame
* aFrame
) : nsDisplayItem(aFrame
) {
189 MOZ_COUNT_CTOR(nsDisplayBullet
);
191 #ifdef NS_BUILD_REFCNT_LOGGING
192 virtual ~nsDisplayBullet() {
193 MOZ_COUNT_DTOR(nsDisplayBullet
);
197 virtual nsIFrame
* HitTest(nsDisplayListBuilder
* aBuilder
, nsPoint aPt
,
198 HitTestState
* aState
) { return mFrame
; }
199 virtual void Paint(nsDisplayListBuilder
* aBuilder
, nsIRenderingContext
* aCtx
,
200 const nsRect
& aDirtyRect
);
201 NS_DISPLAY_DECL_NAME("Bullet")
204 void nsDisplayBullet::Paint(nsDisplayListBuilder
* aBuilder
,
205 nsIRenderingContext
* aCtx
, const nsRect
& aDirtyRect
)
207 static_cast<nsBulletFrame
*>(mFrame
)->
208 PaintBullet(*aCtx
, aBuilder
->ToReferenceFrame(mFrame
), aDirtyRect
);
212 nsBulletFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
213 const nsRect
& aDirtyRect
,
214 const nsDisplayListSet
& aLists
)
216 if (!IsVisibleForPainting(aBuilder
))
219 DO_GLOBAL_REFLOW_COUNT_DSP("nsBulletFrame");
221 return aLists
.Content()->AppendNewToTop(new (aBuilder
) nsDisplayBullet(this));
225 nsBulletFrame::PaintBullet(nsIRenderingContext
& aRenderingContext
, nsPoint aPt
,
226 const nsRect
& aDirtyRect
)
228 const nsStyleList
* myList
= GetStyleList();
229 PRUint8 listStyleType
= myList
->mListStyleType
;
231 if (myList
->mListStyleImage
&& mImageRequest
) {
233 mImageRequest
->GetImageStatus(&status
);
234 if (status
& imgIRequest::STATUS_LOAD_COMPLETE
&&
235 !(status
& imgIRequest::STATUS_ERROR
)) {
236 nsCOMPtr
<imgIContainer
> imageCon
;
237 mImageRequest
->GetImage(getter_AddRefs(imageCon
));
239 nsRect
dest(mPadding
.left
, mPadding
.top
,
240 mRect
.width
- (mPadding
.left
+ mPadding
.right
),
241 mRect
.height
- (mPadding
.top
+ mPadding
.bottom
));
242 nsLayoutUtils::DrawImage(&aRenderingContext
, imageCon
,
243 dest
+ aPt
, aDirtyRect
);
249 const nsStyleColor
* myColor
= GetStyleColor();
251 nsCOMPtr
<nsIFontMetrics
> fm
;
252 aRenderingContext
.SetColor(myColor
->mColor
);
254 mTextIsRTL
= PR_FALSE
;
257 switch (listStyleType
) {
258 case NS_STYLE_LIST_STYLE_NONE
:
262 case NS_STYLE_LIST_STYLE_DISC
:
263 aRenderingContext
.FillEllipse(mPadding
.left
+ aPt
.x
, mPadding
.top
+ aPt
.y
,
264 mRect
.width
- (mPadding
.left
+ mPadding
.right
),
265 mRect
.height
- (mPadding
.top
+ mPadding
.bottom
));
268 case NS_STYLE_LIST_STYLE_CIRCLE
:
269 aRenderingContext
.DrawEllipse(mPadding
.left
+ aPt
.x
, mPadding
.top
+ aPt
.y
,
270 mRect
.width
- (mPadding
.left
+ mPadding
.right
),
271 mRect
.height
- (mPadding
.top
+ mPadding
.bottom
));
274 case NS_STYLE_LIST_STYLE_SQUARE
:
275 aRenderingContext
.FillRect(mPadding
.left
+ aPt
.x
, mPadding
.top
+ aPt
.y
,
276 mRect
.width
- (mPadding
.left
+ mPadding
.right
),
277 mRect
.height
- (mPadding
.top
+ mPadding
.bottom
));
280 case NS_STYLE_LIST_STYLE_DECIMAL
:
281 case NS_STYLE_LIST_STYLE_OLD_DECIMAL
:
282 case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO
:
283 case NS_STYLE_LIST_STYLE_LOWER_ROMAN
:
284 case NS_STYLE_LIST_STYLE_UPPER_ROMAN
:
285 case NS_STYLE_LIST_STYLE_LOWER_ALPHA
:
286 case NS_STYLE_LIST_STYLE_UPPER_ALPHA
:
287 case NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN
:
288 case NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN
:
289 case NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA
:
290 case NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA
:
291 case NS_STYLE_LIST_STYLE_LOWER_GREEK
:
292 case NS_STYLE_LIST_STYLE_HEBREW
:
293 case NS_STYLE_LIST_STYLE_ARMENIAN
:
294 case NS_STYLE_LIST_STYLE_GEORGIAN
:
295 case NS_STYLE_LIST_STYLE_CJK_IDEOGRAPHIC
:
296 case NS_STYLE_LIST_STYLE_HIRAGANA
:
297 case NS_STYLE_LIST_STYLE_KATAKANA
:
298 case NS_STYLE_LIST_STYLE_HIRAGANA_IROHA
:
299 case NS_STYLE_LIST_STYLE_KATAKANA_IROHA
:
300 case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_INFORMAL
:
301 case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_FORMAL
:
302 case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_INFORMAL
:
303 case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_FORMAL
:
304 case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_INFORMAL
:
305 case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_FORMAL
:
306 case NS_STYLE_LIST_STYLE_MOZ_CJK_HEAVENLY_STEM
:
307 case NS_STYLE_LIST_STYLE_MOZ_CJK_EARTHLY_BRANCH
:
308 case NS_STYLE_LIST_STYLE_MOZ_ARABIC_INDIC
:
309 case NS_STYLE_LIST_STYLE_MOZ_PERSIAN
:
310 case NS_STYLE_LIST_STYLE_MOZ_URDU
:
311 case NS_STYLE_LIST_STYLE_MOZ_DEVANAGARI
:
312 case NS_STYLE_LIST_STYLE_MOZ_GURMUKHI
:
313 case NS_STYLE_LIST_STYLE_MOZ_GUJARATI
:
314 case NS_STYLE_LIST_STYLE_MOZ_ORIYA
:
315 case NS_STYLE_LIST_STYLE_MOZ_KANNADA
:
316 case NS_STYLE_LIST_STYLE_MOZ_MALAYALAM
:
317 case NS_STYLE_LIST_STYLE_MOZ_BENGALI
:
318 case NS_STYLE_LIST_STYLE_MOZ_TAMIL
:
319 case NS_STYLE_LIST_STYLE_MOZ_TELUGU
:
320 case NS_STYLE_LIST_STYLE_MOZ_THAI
:
321 case NS_STYLE_LIST_STYLE_MOZ_LAO
:
322 case NS_STYLE_LIST_STYLE_MOZ_MYANMAR
:
323 case NS_STYLE_LIST_STYLE_MOZ_KHMER
:
324 case NS_STYLE_LIST_STYLE_MOZ_HANGUL
:
325 case NS_STYLE_LIST_STYLE_MOZ_HANGUL_CONSONANT
:
326 case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME
:
327 case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_NUMERIC
:
328 case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_AM
:
329 case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ER
:
330 case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ET
:
331 nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm
));
332 GetListItemText(*myList
, text
);
333 aRenderingContext
.SetFont(fm
);
335 fm
->GetMaxAscent(ascent
);
336 aRenderingContext
.SetTextRunRTL(mTextIsRTL
);
337 aRenderingContext
.DrawString(text
, mPadding
.left
+ aPt
.x
,
338 mPadding
.top
+ aPt
.y
+ ascent
);
344 nsBulletFrame::SetListItemOrdinal(PRInt32 aNextOrdinal
,
347 // Assume that the ordinal comes from the caller
348 PRInt32 oldOrdinal
= mOrdinal
;
349 mOrdinal
= aNextOrdinal
;
351 // Try to get value directly from the list-item, if it specifies a
352 // value attribute. Note: we do this with our parent's content
353 // because our parent is the list-item.
354 nsIContent
* parentContent
= mParent
->GetContent();
356 nsGenericHTMLElement
*hc
=
357 nsGenericHTMLElement::FromContent(parentContent
);
359 const nsAttrValue
* attr
= hc
->GetParsedAttr(nsGkAtoms::value
);
360 if (attr
&& attr
->Type() == nsAttrValue::eInteger
) {
361 // Use ordinal specified by the value attribute
362 mOrdinal
= attr
->GetIntegerValue();
367 *aChanged
= oldOrdinal
!= mOrdinal
;
373 // XXX change roman/alpha to use unsigned math so that maxint and
374 // maxnegint will work
377 * For all functions below, a return value of PR_TRUE means that we
378 * could represent mOrder in the desired numbering system. PR_FALSE
379 * means we had to fall back to decimal
381 static PRBool
DecimalToText(PRInt32 ordinal
, nsString
& result
)
384 PR_snprintf(cbuf
, sizeof(cbuf
), "%ld", ordinal
);
385 result
.AppendASCII(cbuf
);
388 static PRBool
DecimalLeadingZeroToText(PRInt32 ordinal
, nsString
& result
)
391 PR_snprintf(cbuf
, sizeof(cbuf
), "%02ld", ordinal
);
392 result
.AppendASCII(cbuf
);
395 static PRBool
OtherDecimalToText(PRInt32 ordinal
, PRUnichar zeroChar
, nsString
& result
)
397 PRUnichar diff
= zeroChar
- PRUnichar('0');
398 DecimalToText(ordinal
, result
);
399 PRUnichar
* p
= result
.BeginWriting();
401 // skip the leading '-'
404 for(; nsnull
!= *p
; p
++)
408 static PRBool
TamilToText(PRInt32 ordinal
, nsString
& result
)
410 PRUnichar diff
= 0x0BE6 - PRUnichar('0');
411 DecimalToText(ordinal
, result
);
412 if (ordinal
< 1 || ordinal
> 9999) {
413 // Can't do those in this system.
416 PRUnichar
* p
= result
.BeginWriting();
417 for(; nsnull
!= *p
; p
++)
418 if(*p
!= PRUnichar('0'))
424 static const char gLowerRomanCharsA
[] = "ixcm";
425 static const char gUpperRomanCharsA
[] = "IXCM";
426 static const char gLowerRomanCharsB
[] = "vld";
427 static const char gUpperRomanCharsB
[] = "VLD";
429 static PRBool
RomanToText(PRInt32 ordinal
, nsString
& result
, const char* achars
, const char* bchars
)
431 if (ordinal
< 1 || ordinal
> 3999) {
432 DecimalToText(ordinal
, result
);
435 nsAutoString addOn
, decStr
;
436 decStr
.AppendInt(ordinal
, 10);
437 PRIntn len
= decStr
.Length();
438 const PRUnichar
* dp
= decStr
.get();
439 const PRUnichar
* end
= dp
+ len
;
440 PRIntn romanPos
= len
;
443 for (; dp
< end
; dp
++) {
447 case '3': addOn
.Append(PRUnichar(achars
[romanPos
]));
448 case '2': addOn
.Append(PRUnichar(achars
[romanPos
]));
449 case '1': addOn
.Append(PRUnichar(achars
[romanPos
]));
452 addOn
.Append(PRUnichar(achars
[romanPos
]));
456 addOn
.Append(PRUnichar(bchars
[romanPos
]));
457 for(n
=0;n
<(*dp
-'5');n
++) {
458 addOn
.Append(PRUnichar(achars
[romanPos
]));
462 addOn
.Append(PRUnichar(achars
[romanPos
]));
463 addOn
.Append(PRUnichar(achars
[romanPos
+1]));
468 result
.Append(addOn
);
473 #define ALPHA_SIZE 26
474 static const PRUnichar gLowerAlphaChars
[ALPHA_SIZE
] =
476 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, // A B C D E
477 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, // F G H I J
478 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, // K L M N O
479 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, // P Q R S T
480 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, // U V W X Y
484 static const PRUnichar gUpperAlphaChars
[ALPHA_SIZE
] =
486 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, // A B C D E
487 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, // F G H I J
488 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, // K L M N O
489 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, // P Q R S T
490 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, // U V W X Y
495 #define KATAKANA_CHARS_SIZE 48
496 // Page 94 Writing Systems of The World
497 // after modification by momoi
498 static const PRUnichar gKatakanaChars
[KATAKANA_CHARS_SIZE
] =
500 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, // a i u e o
501 0x30AB, 0x30AD, 0x30AF, 0x30B1, 0x30B3, // ka ki ku ke ko
502 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, // sa shi su se so
503 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, // ta chi tsu te to
504 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, // na ni nu ne no
505 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, // ha hi hu he ho
506 0x30DE, 0x30DF, 0x30E0, 0x30E1, 0x30E2, // ma mi mu me mo
507 0x30E4, 0x30E6, 0x30E8, // ya yu yo
508 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, // ra ri ru re ro
509 0x30EF, 0x30F0, 0x30F1, 0x30F2, // wa (w)i (w)e (w)o
513 #define HIRAGANA_CHARS_SIZE 48
514 static const PRUnichar gHiraganaChars
[HIRAGANA_CHARS_SIZE
] =
516 0x3042, 0x3044, 0x3046, 0x3048, 0x304A, // a i u e o
517 0x304B, 0x304D, 0x304F, 0x3051, 0x3053, // ka ki ku ke ko
518 0x3055, 0x3057, 0x3059, 0x305B, 0x305D, // sa shi su se so
519 0x305F, 0x3061, 0x3064, 0x3066, 0x3068, // ta chi tsu te to
520 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, // na ni nu ne no
521 0x306F, 0x3072, 0x3075, 0x3078, 0x307B, // ha hi hu he ho
522 0x307E, 0x307F, 0x3080, 0x3081, 0x3082, // ma mi mu me mo
523 0x3084, 0x3086, 0x3088, // ya yu yo
524 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, // ra ri ru re ro
525 0x308F, 0x3090, 0x3091, 0x3092, // wa (w)i (w)e (w)o
530 #define HIRAGANA_IROHA_CHARS_SIZE 47
531 // Page 94 Writing Systems of The World
532 static const PRUnichar gHiraganaIrohaChars
[HIRAGANA_IROHA_CHARS_SIZE
] =
534 0x3044, 0x308D, 0x306F, 0x306B, 0x307B, // i ro ha ni ho
535 0x3078, 0x3068, 0x3061, 0x308A, 0x306C, // he to chi ri nu
536 0x308B, 0x3092, 0x308F, 0x304B, 0x3088, // ru (w)o wa ka yo
537 0x305F, 0x308C, 0x305D, 0x3064, 0x306D, // ta re so tsu ne
538 0x306A, 0x3089, 0x3080, 0x3046, 0x3090, // na ra mu u (w)i
539 0x306E, 0x304A, 0x304F, 0x3084, 0x307E, // no o ku ya ma
540 0x3051, 0x3075, 0x3053, 0x3048, 0x3066, // ke hu ko e te
541 0x3042, 0x3055, 0x304D, 0x3086, 0x3081, // a sa ki yu me
542 0x307F, 0x3057, 0x3091, 0x3072, 0x3082, // mi shi (w)e hi mo
543 0x305B, 0x3059 // se su
546 #define KATAKANA_IROHA_CHARS_SIZE 47
547 static const PRUnichar gKatakanaIrohaChars
[KATAKANA_IROHA_CHARS_SIZE
] =
549 0x30A4, 0x30ED, 0x30CF, 0x30CB, 0x30DB, // i ro ha ni ho
550 0x30D8, 0x30C8, 0x30C1, 0x30EA, 0x30CC, // he to chi ri nu
551 0x30EB, 0x30F2, 0x30EF, 0x30AB, 0x30E8, // ru (w)o wa ka yo
552 0x30BF, 0x30EC, 0x30BD, 0x30C4, 0x30CD, // ta re so tsu ne
553 0x30CA, 0x30E9, 0x30E0, 0x30A6, 0x30F0, // na ra mu u (w)i
554 0x30CE, 0x30AA, 0x30AF, 0x30E4, 0x30DE, // no o ku ya ma
555 0x30B1, 0x30D5, 0x30B3, 0x30A8, 0x30C6, // ke hu ko e te
556 0x30A2, 0x30B5, 0x30AD, 0x30E6, 0x30E1, // a sa ki yu me
557 0x30DF, 0x30B7, 0x30F1, 0x30D2, 0x30E2, // mi shi (w)e hi mo
558 0x30BB, 0x30B9 // se su
561 #define LOWER_GREEK_CHARS_SIZE 24
562 // Note: 0x03C2 GREEK FINAL SIGMA is not used in here....
563 static const PRUnichar gLowerGreekChars
[LOWER_GREEK_CHARS_SIZE
] =
565 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, // alpha beta gamma delta epsilon
566 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, // zeta eta theta iota kappa
567 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, // lamda mu nu xi omicron
568 0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5, // pi rho sigma tau upsilon
569 0x03C6, 0x03C7, 0x03C8, 0x03C9 // phi chi psi omega
572 #define CJK_HEAVENLY_STEM_CHARS_SIZE 10
573 static const PRUnichar gCJKHeavenlyStemChars
[CJK_HEAVENLY_STEM_CHARS_SIZE
] =
575 0x7532, 0x4e59, 0x4e19, 0x4e01, 0x620a,
576 0x5df1, 0x5e9a, 0x8f9b, 0x58ec, 0x7678
578 #define CJK_EARTHLY_BRANCH_CHARS_SIZE 12
579 static const PRUnichar gCJKEarthlyBranchChars
[CJK_EARTHLY_BRANCH_CHARS_SIZE
] =
581 0x5b50, 0x4e11, 0x5bc5, 0x536f, 0x8fb0, 0x5df3,
582 0x5348, 0x672a, 0x7533, 0x9149, 0x620c, 0x4ea5
584 #define HANGUL_CHARS_SIZE 14
585 static const PRUnichar gHangulChars
[HANGUL_CHARS_SIZE
] =
587 0xac00, 0xb098, 0xb2e4, 0xb77c, 0xb9c8, 0xbc14,
588 0xc0ac, 0xc544, 0xc790, 0xcc28, 0xce74, 0xd0c0,
591 #define HANGUL_CONSONANT_CHARS_SIZE 14
592 static const PRUnichar gHangulConsonantChars
[HANGUL_CONSONANT_CHARS_SIZE
] =
594 0x3131, 0x3134, 0x3137, 0x3139, 0x3141, 0x3142,
595 0x3145, 0x3147, 0x3148, 0x314a, 0x314b, 0x314c,
599 // Ge'ez set of Ethiopic ordered list. There are other locale-dependent sets.
600 // For the time being, let's implement two Ge'ez sets only
601 // per Momoi san's suggestion in bug 102252.
602 // For details, refer to http://www.ethiopic.org/Collation/OrderedLists.html.
603 #define ETHIOPIC_HALEHAME_CHARS_SIZE 26
604 static const PRUnichar gEthiopicHalehameChars
[ETHIOPIC_HALEHAME_CHARS_SIZE
] =
606 0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228,
607 0x1230, 0x1240, 0x1260, 0x1270, 0x1280, 0x1290,
608 0x12a0, 0x12a8, 0x12c8, 0x12d0, 0x12d8, 0x12e8,
609 0x12f0, 0x1308, 0x1320, 0x1330, 0x1338, 0x1340,
612 #define ETHIOPIC_HALEHAME_AM_CHARS_SIZE 33
613 static const PRUnichar gEthiopicHalehameAmChars
[ETHIOPIC_HALEHAME_AM_CHARS_SIZE
] =
615 0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228,
616 0x1230, 0x1238, 0x1240, 0x1260, 0x1270, 0x1278,
617 0x1280, 0x1290, 0x1298, 0x12a0, 0x12a8, 0x12b8,
618 0x12c8, 0x12d0, 0x12d8, 0x12e0, 0x12e8, 0x12f0,
619 0x1300, 0x1308, 0x1320, 0x1328, 0x1330, 0x1338,
620 0x1340, 0x1348, 0x1350
622 #define ETHIOPIC_HALEHAME_TI_ER_CHARS_SIZE 31
623 static const PRUnichar gEthiopicHalehameTiErChars
[ETHIOPIC_HALEHAME_TI_ER_CHARS_SIZE
] =
625 0x1200, 0x1208, 0x1210, 0x1218, 0x1228, 0x1230,
626 0x1238, 0x1240, 0x1250, 0x1260, 0x1270, 0x1278,
627 0x1290, 0x1298, 0x12a0, 0x12a8, 0x12b8, 0x12c8,
628 0x12d0, 0x12d8, 0x12e0, 0x12e8, 0x12f0, 0x1300,
629 0x1308, 0x1320, 0x1328, 0x1330, 0x1338, 0x1348,
632 #define ETHIOPIC_HALEHAME_TI_ET_CHARS_SIZE 34
633 static const PRUnichar gEthiopicHalehameTiEtChars
[ETHIOPIC_HALEHAME_TI_ET_CHARS_SIZE
] =
635 0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228,
636 0x1230, 0x1238, 0x1240, 0x1250, 0x1260, 0x1270,
637 0x1278, 0x1280, 0x1290, 0x1298, 0x12a0, 0x12a8,
638 0x12b8, 0x12c8, 0x12d0, 0x12d8, 0x12e0, 0x12e8,
639 0x12f0, 0x1300, 0x1308, 0x1320, 0x1328, 0x1330,
640 0x1338, 0x1340, 0x1348, 0x1350
644 // We know cjk-ideographic need 31 characters to display 99,999,999,999,999,999
645 // georgian needs 6 at most
646 // armenian needs 12 at most
647 // hebrew may need more...
649 #define NUM_BUF_SIZE 34
651 static PRBool
CharListToText(PRInt32 ordinal
, nsString
& result
, const PRUnichar
* chars
, PRInt32 aBase
)
653 PRUnichar buf
[NUM_BUF_SIZE
];
654 PRInt32 idx
= NUM_BUF_SIZE
;
656 DecimalToText(ordinal
, result
);
661 PRInt32 cur
= ordinal
% aBase
;
662 buf
[--idx
] = chars
[cur
];
664 } while ( ordinal
> 0);
665 result
.Append(buf
+idx
,NUM_BUF_SIZE
-idx
);
670 static const PRUnichar gCJKIdeographicDigit1
[10] =
672 0x96f6, 0x4e00, 0x4e8c, 0x4e09, 0x56db, // 0 - 4
673 0x4e94, 0x516d, 0x4e03, 0x516b, 0x4e5d // 5 - 9
675 static const PRUnichar gCJKIdeographicDigit2
[10] =
677 0x96f6, 0x58f9, 0x8cb3, 0x53c3, 0x8086, // 0 - 4
678 0x4f0d, 0x9678, 0x67d2, 0x634c, 0x7396 // 5 - 9
680 static const PRUnichar gCJKIdeographicDigit3
[10] =
682 0x96f6, 0x58f9, 0x8d30, 0x53c1, 0x8086, // 0 - 4
683 0x4f0d, 0x9646, 0x67d2, 0x634c, 0x7396 // 5 - 9
685 static const PRUnichar gCJKIdeographicUnit1
[4] =
687 0x000, 0x5341, 0x767e, 0x5343
689 static const PRUnichar gCJKIdeographicUnit2
[4] =
691 0x000, 0x62FE, 0x4F70, 0x4EDF
693 static const PRUnichar gCJKIdeographic10KUnit1
[4] =
695 0x000, 0x842c, 0x5104, 0x5146
697 static const PRUnichar gCJKIdeographic10KUnit2
[4] =
699 0x000, 0x4E07, 0x4ebf, 0x5146
701 static const PRUnichar gCJKIdeographic10KUnit3
[4] =
703 0x000, 0x4E07, 0x5104, 0x5146
706 static const PRBool
CJKIdeographicToText(PRInt32 ordinal
, nsString
& result
,
707 const PRUnichar
* digits
,
708 const PRUnichar
*unit
,
709 const PRUnichar
* unit10k
)
711 // In theory, we need the following if condiction,
712 // However, the limit, 10 ^ 16, is greater than the max of PRUint32
713 // so we don't really need to test it here.
714 // if( ordinal > 9999999999999999)
716 // PR_snprintf(cbuf, sizeof(cbuf), "%ld", ordinal);
717 // result.Append(cbuf);
722 DecimalToText(ordinal
, result
);
725 PRUnichar c10kUnit
= 0;
727 PRUnichar cDigit
= 0;
729 PRUnichar buf
[NUM_BUF_SIZE
];
730 PRInt32 idx
= NUM_BUF_SIZE
;
731 PRBool bOutputZero
= ( 0 == ordinal
);
734 c10kUnit
= unit10k
[ud
/4];
736 PRInt32 cur
= ordinal
% 10;
737 cDigit
= digits
[cur
];
742 bOutputZero
= PR_FALSE
;
749 bOutputZero
= PR_TRUE
;
753 buf
[--idx
] = c10kUnit
;
757 ( (1 != cur
) || (1 != (ud
%4)) || ( ordinal
> 10)) )
765 } while( ordinal
> 0);
766 result
.Append(buf
+idx
,NUM_BUF_SIZE
-idx
);
771 #define HEBREW_GERESH 0x05F3
772 static const PRUnichar gHebrewDigit
[22] =
775 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8,
776 // 10 20 30 40 50 60 70 80 90
777 0x05D9, 0x05DB, 0x05DC, 0x05DE, 0x05E0, 0x05E1, 0x05E2, 0x05E4, 0x05E6,
779 0x05E7, 0x05E8, 0x05E9, 0x05EA
782 static PRBool
HebrewToText(PRInt32 ordinal
, nsString
& result
)
784 if (ordinal
< 1 || ordinal
> 999999) {
785 DecimalToText(ordinal
, result
);
788 PRBool outputSep
= PR_FALSE
;
789 nsAutoString allText
, thousandsGroup
;
791 thousandsGroup
.Truncate();
792 PRInt32 n3
= ordinal
% 1000;
793 // Process digit for 100 - 900
794 for(PRInt32 n1
= 400; n1
> 0; )
799 thousandsGroup
.Append(gHebrewDigit
[(n1
/100)-1+18]);
805 // Process digit for 10 - 90
809 // Special process for 15 and 16
810 if(( 15 == n3
) || (16 == n3
)) {
811 // Special rule for religious reason...
812 // 15 is represented by 9 and 6, not 10 and 5
813 // 16 is represented by 9 and 7, not 10 and 6
815 thousandsGroup
.Append(gHebrewDigit
[ n2
- 1]);
818 thousandsGroup
.Append(gHebrewDigit
[(n2
/10)-1+9]);
823 // Process digit for 1 - 9
825 thousandsGroup
.Append(gHebrewDigit
[n3
-1]);
827 thousandsGroup
.Append((PRUnichar
)HEBREW_GERESH
);
828 if (allText
.IsEmpty())
829 allText
= thousandsGroup
;
831 allText
= thousandsGroup
+ allText
;
834 } while (ordinal
>= 1);
836 result
.Append(allText
);
841 static PRBool
ArmenianToText(PRInt32 ordinal
, nsString
& result
)
843 // XXXbz this system goes out to a lot further than 9999... we should fix
844 // that. This algorithm seems broken in general. There's this business of
845 // "7000" being special and then there's the combining accent we're supposed
847 if (ordinal
< 1 || ordinal
> 9999) { // zero or reach the limit of Armenian numbering system
848 DecimalToText(ordinal
, result
);
852 PRUnichar buf
[NUM_BUF_SIZE
];
853 PRInt32 idx
= NUM_BUF_SIZE
;
856 PRInt32 cur
= ordinal
% 10;
859 PRUnichar u
= 0x0530 + (d
* 9) + cur
;
864 } while (ordinal
> 0);
865 result
.Append(buf
+ idx
, NUM_BUF_SIZE
- idx
);
870 static const PRUnichar gGeorgianValue
[ 37 ] = { // 4 * 9 + 1 = 37
872 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10F1, 0x10D7,
873 // 10 20 30 40 50 60 70 80 90
874 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10F2, 0x10DD, 0x10DE, 0x10DF,
875 // 100 200 300 400 500 600 700 800 900
876 0x10E0, 0x10E1, 0x10E2, 0x10F3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, 0x10E8,
877 // 1000 2000 3000 4000 5000 6000 7000 8000 9000
878 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10F4, 0x10EF, 0x10F0,
882 static PRBool
GeorgianToText(PRInt32 ordinal
, nsString
& result
)
884 if (ordinal
< 1 || ordinal
> 19999) { // zero or reach the limit of Georgian numbering system
885 DecimalToText(ordinal
, result
);
889 PRUnichar buf
[NUM_BUF_SIZE
];
890 PRInt32 idx
= NUM_BUF_SIZE
;
893 PRInt32 cur
= ordinal
% 10;
896 PRUnichar u
= gGeorgianValue
[(d
* 9 ) + ( cur
- 1)];
901 } while (ordinal
> 0);
902 result
.Append(buf
+ idx
, NUM_BUF_SIZE
- idx
);
906 // Convert ordinal to Ethiopic numeric representation.
907 // The detail is available at http://www.ethiopic.org/Numerals/
908 // The algorithm used here is based on the pseudo-code put up there by
909 // Daniel Yacob <yacob@geez.org>.
910 // Another reference is Unicode 3.0 standard section 11.1.
911 #define ETHIOPIC_ONE 0x1369
912 #define ETHIOPIC_TEN 0x1372
913 #define ETHIOPIC_HUNDRED 0x137B
914 #define ETHIOPIC_TEN_THOUSAND 0x137C
916 static PRBool
EthiopicToText(PRInt32 ordinal
, nsString
& result
)
918 nsAutoString asciiNumberString
; // decimal string representation of ordinal
919 DecimalToText(ordinal
, asciiNumberString
);
921 result
.Append(asciiNumberString
);
924 PRUint8 asciiStringLength
= asciiNumberString
.Length();
926 // If number length is odd, add a leading "0"
927 // the leading "0" preconditions the string to always have the
928 // leading tens place populated, this avoids a check within the loop.
929 // If we didn't add the leading "0", decrement asciiStringLength so
930 // it will be equivalent to a zero-based index in both cases.
931 if (asciiStringLength
& 1) {
932 asciiNumberString
.Insert(NS_LITERAL_STRING("0"), 0);
937 // Iterate from the highest digits to lowest
938 // indexFromLeft indexes digits (0 = most significant)
939 // groupIndexFromRight indexes pairs of digits (0 = least significant)
940 for (PRUint8 indexFromLeft
= 0, groupIndexFromRight
= asciiStringLength
>> 1;
941 indexFromLeft
<= asciiStringLength
;
942 indexFromLeft
+= 2, groupIndexFromRight
--) {
943 PRUint8 tensValue
= asciiNumberString
.CharAt(indexFromLeft
) & 0x0F;
944 PRUint8 unitsValue
= asciiNumberString
.CharAt(indexFromLeft
+ 1) & 0x0F;
945 PRUint8 groupValue
= tensValue
* 10 + unitsValue
;
947 PRBool oddGroup
= (groupIndexFromRight
& 1);
949 // we want to clear ETHIOPIC_ONE when it is superfluous
951 groupValue
== 1 && // one without a leading ten
952 (oddGroup
|| indexFromLeft
== 0)) { // preceding (100) or leading the sequence
956 // put it all together...
958 // map onto Ethiopic "tens":
959 result
.Append((PRUnichar
) (tensValue
+ ETHIOPIC_TEN
- 1));
962 //map onto Ethiopic "units":
963 result
.Append((PRUnichar
) (unitsValue
+ ETHIOPIC_ONE
- 1));
965 // Add a separator for all even groups except the last,
966 // and for odd groups with non-zero value.
969 result
.Append((PRUnichar
) ETHIOPIC_HUNDRED
);
972 if (groupIndexFromRight
) {
973 result
.Append((PRUnichar
) ETHIOPIC_TEN_THOUSAND
);
982 nsBulletFrame::AppendCounterText(PRInt32 aListStyleType
,
988 switch (aListStyleType
) {
989 case NS_STYLE_LIST_STYLE_NONE
: // used by counters code only
992 case NS_STYLE_LIST_STYLE_DISC
: // used by counters code only
993 // XXX We really need to do this the same way we do list bullets.
994 result
.Append(PRUnichar(0x2022));
997 case NS_STYLE_LIST_STYLE_CIRCLE
: // used by counters code only
998 // XXX We really need to do this the same way we do list bullets.
999 result
.Append(PRUnichar(0x25E6));
1002 case NS_STYLE_LIST_STYLE_SQUARE
: // used by counters code only
1003 // XXX We really need to do this the same way we do list bullets.
1004 result
.Append(PRUnichar(0x25FE));
1007 case NS_STYLE_LIST_STYLE_DECIMAL
:
1008 case NS_STYLE_LIST_STYLE_OLD_DECIMAL
:
1009 default: // CSS2 say "A users agent that does not recognize a numbering system
1010 // should use 'decimal'
1011 success
= DecimalToText(aOrdinal
, result
);
1014 case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO
:
1015 success
= DecimalLeadingZeroToText(aOrdinal
, result
);
1018 case NS_STYLE_LIST_STYLE_LOWER_ROMAN
:
1019 case NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN
:
1020 success
= RomanToText(aOrdinal
, result
,
1021 gLowerRomanCharsA
, gLowerRomanCharsB
);
1023 case NS_STYLE_LIST_STYLE_UPPER_ROMAN
:
1024 case NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN
:
1025 success
= RomanToText(aOrdinal
, result
,
1026 gUpperRomanCharsA
, gUpperRomanCharsB
);
1029 case NS_STYLE_LIST_STYLE_LOWER_ALPHA
:
1030 case NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA
:
1031 success
= CharListToText(aOrdinal
, result
, gLowerAlphaChars
, ALPHA_SIZE
);
1034 case NS_STYLE_LIST_STYLE_UPPER_ALPHA
:
1035 case NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA
:
1036 success
= CharListToText(aOrdinal
, result
, gUpperAlphaChars
, ALPHA_SIZE
);
1039 case NS_STYLE_LIST_STYLE_KATAKANA
:
1040 success
= CharListToText(aOrdinal
, result
, gKatakanaChars
,
1041 KATAKANA_CHARS_SIZE
);
1044 case NS_STYLE_LIST_STYLE_HIRAGANA
:
1045 success
= CharListToText(aOrdinal
, result
, gHiraganaChars
,
1046 HIRAGANA_CHARS_SIZE
);
1049 case NS_STYLE_LIST_STYLE_KATAKANA_IROHA
:
1050 success
= CharListToText(aOrdinal
, result
, gKatakanaIrohaChars
,
1051 KATAKANA_IROHA_CHARS_SIZE
);
1054 case NS_STYLE_LIST_STYLE_HIRAGANA_IROHA
:
1055 success
= CharListToText(aOrdinal
, result
, gHiraganaIrohaChars
,
1056 HIRAGANA_IROHA_CHARS_SIZE
);
1059 case NS_STYLE_LIST_STYLE_LOWER_GREEK
:
1060 success
= CharListToText(aOrdinal
, result
, gLowerGreekChars
,
1061 LOWER_GREEK_CHARS_SIZE
);
1064 case NS_STYLE_LIST_STYLE_CJK_IDEOGRAPHIC
:
1065 case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_INFORMAL
:
1066 success
= CJKIdeographicToText(aOrdinal
, result
, gCJKIdeographicDigit1
,
1067 gCJKIdeographicUnit1
,
1068 gCJKIdeographic10KUnit1
);
1071 case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_FORMAL
:
1072 success
= CJKIdeographicToText(aOrdinal
, result
, gCJKIdeographicDigit2
,
1073 gCJKIdeographicUnit2
,
1074 gCJKIdeographic10KUnit1
);
1077 case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_INFORMAL
:
1078 success
= CJKIdeographicToText(aOrdinal
, result
, gCJKIdeographicDigit1
,
1079 gCJKIdeographicUnit1
,
1080 gCJKIdeographic10KUnit2
);
1083 case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_FORMAL
:
1084 success
= CJKIdeographicToText(aOrdinal
, result
, gCJKIdeographicDigit3
,
1085 gCJKIdeographicUnit2
,
1086 gCJKIdeographic10KUnit2
);
1089 case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_INFORMAL
:
1090 success
= CJKIdeographicToText(aOrdinal
, result
, gCJKIdeographicDigit1
,
1091 gCJKIdeographicUnit1
,
1092 gCJKIdeographic10KUnit3
);
1095 case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_FORMAL
:
1096 success
= CJKIdeographicToText(aOrdinal
, result
, gCJKIdeographicDigit2
,
1097 gCJKIdeographicUnit2
,
1098 gCJKIdeographic10KUnit3
);
1101 case NS_STYLE_LIST_STYLE_HEBREW
:
1102 success
= HebrewToText(aOrdinal
, result
);
1105 case NS_STYLE_LIST_STYLE_ARMENIAN
:
1106 success
= ArmenianToText(aOrdinal
, result
);
1109 case NS_STYLE_LIST_STYLE_GEORGIAN
:
1110 success
= GeorgianToText(aOrdinal
, result
);
1113 case NS_STYLE_LIST_STYLE_MOZ_ARABIC_INDIC
:
1114 success
= OtherDecimalToText(aOrdinal
, 0x0660, result
);
1117 case NS_STYLE_LIST_STYLE_MOZ_PERSIAN
:
1118 case NS_STYLE_LIST_STYLE_MOZ_URDU
:
1119 success
= OtherDecimalToText(aOrdinal
, 0x06f0, result
);
1122 case NS_STYLE_LIST_STYLE_MOZ_DEVANAGARI
:
1123 success
= OtherDecimalToText(aOrdinal
, 0x0966, result
);
1126 case NS_STYLE_LIST_STYLE_MOZ_GURMUKHI
:
1127 success
= OtherDecimalToText(aOrdinal
, 0x0a66, result
);
1130 case NS_STYLE_LIST_STYLE_MOZ_GUJARATI
:
1131 success
= OtherDecimalToText(aOrdinal
, 0x0AE6, result
);
1134 case NS_STYLE_LIST_STYLE_MOZ_ORIYA
:
1135 success
= OtherDecimalToText(aOrdinal
, 0x0B66, result
);
1138 case NS_STYLE_LIST_STYLE_MOZ_KANNADA
:
1139 success
= OtherDecimalToText(aOrdinal
, 0x0CE6, result
);
1142 case NS_STYLE_LIST_STYLE_MOZ_MALAYALAM
:
1143 success
= OtherDecimalToText(aOrdinal
, 0x0D66, result
);
1146 case NS_STYLE_LIST_STYLE_MOZ_THAI
:
1147 success
= OtherDecimalToText(aOrdinal
, 0x0E50, result
);
1150 case NS_STYLE_LIST_STYLE_MOZ_LAO
:
1151 success
= OtherDecimalToText(aOrdinal
, 0x0ED0, result
);
1154 case NS_STYLE_LIST_STYLE_MOZ_MYANMAR
:
1155 success
= OtherDecimalToText(aOrdinal
, 0x1040, result
);
1158 case NS_STYLE_LIST_STYLE_MOZ_KHMER
:
1159 success
= OtherDecimalToText(aOrdinal
, 0x17E0, result
);
1162 case NS_STYLE_LIST_STYLE_MOZ_BENGALI
:
1163 success
= OtherDecimalToText(aOrdinal
, 0x09E6, result
);
1166 case NS_STYLE_LIST_STYLE_MOZ_TELUGU
:
1167 success
= OtherDecimalToText(aOrdinal
, 0x0C66, result
);
1170 case NS_STYLE_LIST_STYLE_MOZ_TAMIL
:
1171 success
= TamilToText(aOrdinal
, result
);
1174 case NS_STYLE_LIST_STYLE_MOZ_CJK_HEAVENLY_STEM
:
1175 success
= CharListToText(aOrdinal
, result
, gCJKHeavenlyStemChars
,
1176 CJK_HEAVENLY_STEM_CHARS_SIZE
);
1179 case NS_STYLE_LIST_STYLE_MOZ_CJK_EARTHLY_BRANCH
:
1180 success
= CharListToText(aOrdinal
, result
, gCJKEarthlyBranchChars
,
1181 CJK_EARTHLY_BRANCH_CHARS_SIZE
);
1184 case NS_STYLE_LIST_STYLE_MOZ_HANGUL
:
1185 success
= CharListToText(aOrdinal
, result
, gHangulChars
, HANGUL_CHARS_SIZE
);
1188 case NS_STYLE_LIST_STYLE_MOZ_HANGUL_CONSONANT
:
1189 success
= CharListToText(aOrdinal
, result
, gHangulConsonantChars
,
1190 HANGUL_CONSONANT_CHARS_SIZE
);
1193 case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME
:
1194 success
= CharListToText(aOrdinal
, result
, gEthiopicHalehameChars
,
1195 ETHIOPIC_HALEHAME_CHARS_SIZE
);
1198 case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_NUMERIC
:
1199 success
= EthiopicToText(aOrdinal
, result
);
1202 case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_AM
:
1203 success
= CharListToText(aOrdinal
, result
, gEthiopicHalehameAmChars
,
1204 ETHIOPIC_HALEHAME_AM_CHARS_SIZE
);
1207 case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ER
:
1208 success
= CharListToText(aOrdinal
, result
, gEthiopicHalehameTiErChars
,
1209 ETHIOPIC_HALEHAME_TI_ER_CHARS_SIZE
);
1212 case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ET
:
1213 success
= CharListToText(aOrdinal
, result
, gEthiopicHalehameTiEtChars
,
1214 ETHIOPIC_HALEHAME_TI_ET_CHARS_SIZE
);
1221 nsBulletFrame::GetListItemText(const nsStyleList
& aListStyle
,
1224 const nsStyleVisibility
* vis
= GetStyleVisibility();
1226 NS_ASSERTION(aListStyle
.mListStyleType
!= NS_STYLE_LIST_STYLE_NONE
&&
1227 aListStyle
.mListStyleType
!= NS_STYLE_LIST_STYLE_DISC
&&
1228 aListStyle
.mListStyleType
!= NS_STYLE_LIST_STYLE_CIRCLE
&&
1229 aListStyle
.mListStyleType
!= NS_STYLE_LIST_STYLE_SQUARE
,
1230 "we should be using specialized code for these types");
1232 AppendCounterText(aListStyle
.mListStyleType
, mOrdinal
, result
);
1233 if (success
&& aListStyle
.mListStyleType
== NS_STYLE_LIST_STYLE_HEBREW
)
1234 mTextIsRTL
= PR_TRUE
;
1236 // XXX For some of these systems, "." is wrong! This should really be
1237 // pushed down into the individual cases!
1238 nsString suffix
= NS_LITERAL_STRING(".");
1240 // We're not going to do proper Bidi reordering on the list item marker, but
1241 // just display the whole thing as RTL or LTR, so we fake reordering by
1242 // appending the suffix to the end of the list item marker if the
1243 // directionality of the characters is the same as the style direction or
1244 // prepending it to the beginning if they are different.
1245 result
= (mTextIsRTL
== (vis
->mDirection
== NS_STYLE_DIRECTION_RTL
)) ?
1246 result
+ suffix
: suffix
+ result
;
1250 #define MIN_BULLET_SIZE 1
1254 nsBulletFrame::GetDesiredSize(nsPresContext
* aCX
,
1255 nsIRenderingContext
*aRenderingContext
,
1256 nsHTMLReflowMetrics
& aMetrics
)
1258 // Reset our padding. If we need it, we'll set it below.
1259 mPadding
.SizeTo(0, 0, 0, 0);
1261 const nsStyleList
* myList
= GetStyleList();
1264 if (myList
->mListStyleImage
&& mImageRequest
) {
1266 mImageRequest
->GetImageStatus(&status
);
1267 if (status
& imgIRequest::STATUS_SIZE_AVAILABLE
&&
1268 !(status
& imgIRequest::STATUS_ERROR
)) {
1269 // auto size the image
1270 mComputedSize
.width
= mIntrinsicSize
.width
;
1271 mComputedSize
.height
= mIntrinsicSize
.height
;
1273 aMetrics
.width
= mComputedSize
.width
;
1274 aMetrics
.ascent
= aMetrics
.height
= mComputedSize
.height
;
1280 // If we're getting our desired size and don't have an image, reset
1281 // mIntrinsicSize to (0,0). Otherwise, if we used to have an image, it
1282 // changed, and the new one is coming in, but we're reflowing before it's
1283 // fully there, we'll end up with mIntrinsicSize not matching our size, but
1284 // won't trigger a reflow in OnStartContainer (because mIntrinsicSize will
1285 // match the image size).
1286 mIntrinsicSize
.SizeTo(0, 0);
1288 nsCOMPtr
<nsIFontMetrics
> fm
;
1289 nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm
));
1293 switch (myList
->mListStyleType
) {
1294 case NS_STYLE_LIST_STYLE_NONE
:
1296 aMetrics
.ascent
= aMetrics
.height
= 0;
1299 case NS_STYLE_LIST_STYLE_DISC
:
1300 case NS_STYLE_LIST_STYLE_CIRCLE
:
1301 case NS_STYLE_LIST_STYLE_SQUARE
:
1302 fm
->GetMaxAscent(ascent
);
1303 bulletSize
= PR_MAX(nsPresContext::CSSPixelsToAppUnits(MIN_BULLET_SIZE
),
1304 NSToCoordRound(0.8f
* (float(ascent
) / 2.0f
)));
1305 mPadding
.bottom
= NSToCoordRound(float(ascent
) / 8.0f
);
1306 aMetrics
.width
= mPadding
.right
+ bulletSize
;
1307 aMetrics
.ascent
= aMetrics
.height
= mPadding
.bottom
+ bulletSize
;
1311 case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO
:
1312 case NS_STYLE_LIST_STYLE_DECIMAL
:
1313 case NS_STYLE_LIST_STYLE_OLD_DECIMAL
:
1314 case NS_STYLE_LIST_STYLE_LOWER_ROMAN
:
1315 case NS_STYLE_LIST_STYLE_UPPER_ROMAN
:
1316 case NS_STYLE_LIST_STYLE_LOWER_ALPHA
:
1317 case NS_STYLE_LIST_STYLE_UPPER_ALPHA
:
1318 case NS_STYLE_LIST_STYLE_OLD_LOWER_ROMAN
:
1319 case NS_STYLE_LIST_STYLE_OLD_UPPER_ROMAN
:
1320 case NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA
:
1321 case NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA
:
1322 case NS_STYLE_LIST_STYLE_KATAKANA
:
1323 case NS_STYLE_LIST_STYLE_HIRAGANA
:
1324 case NS_STYLE_LIST_STYLE_KATAKANA_IROHA
:
1325 case NS_STYLE_LIST_STYLE_HIRAGANA_IROHA
:
1326 case NS_STYLE_LIST_STYLE_LOWER_GREEK
:
1327 case NS_STYLE_LIST_STYLE_HEBREW
:
1328 case NS_STYLE_LIST_STYLE_ARMENIAN
:
1329 case NS_STYLE_LIST_STYLE_GEORGIAN
:
1330 case NS_STYLE_LIST_STYLE_CJK_IDEOGRAPHIC
:
1331 case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_INFORMAL
:
1332 case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_FORMAL
:
1333 case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_INFORMAL
:
1334 case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_FORMAL
:
1335 case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_INFORMAL
:
1336 case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_FORMAL
:
1337 case NS_STYLE_LIST_STYLE_MOZ_CJK_HEAVENLY_STEM
:
1338 case NS_STYLE_LIST_STYLE_MOZ_CJK_EARTHLY_BRANCH
:
1339 case NS_STYLE_LIST_STYLE_MOZ_ARABIC_INDIC
:
1340 case NS_STYLE_LIST_STYLE_MOZ_PERSIAN
:
1341 case NS_STYLE_LIST_STYLE_MOZ_URDU
:
1342 case NS_STYLE_LIST_STYLE_MOZ_DEVANAGARI
:
1343 case NS_STYLE_LIST_STYLE_MOZ_GURMUKHI
:
1344 case NS_STYLE_LIST_STYLE_MOZ_GUJARATI
:
1345 case NS_STYLE_LIST_STYLE_MOZ_ORIYA
:
1346 case NS_STYLE_LIST_STYLE_MOZ_KANNADA
:
1347 case NS_STYLE_LIST_STYLE_MOZ_MALAYALAM
:
1348 case NS_STYLE_LIST_STYLE_MOZ_BENGALI
:
1349 case NS_STYLE_LIST_STYLE_MOZ_TAMIL
:
1350 case NS_STYLE_LIST_STYLE_MOZ_TELUGU
:
1351 case NS_STYLE_LIST_STYLE_MOZ_THAI
:
1352 case NS_STYLE_LIST_STYLE_MOZ_LAO
:
1353 case NS_STYLE_LIST_STYLE_MOZ_MYANMAR
:
1354 case NS_STYLE_LIST_STYLE_MOZ_KHMER
:
1355 case NS_STYLE_LIST_STYLE_MOZ_HANGUL
:
1356 case NS_STYLE_LIST_STYLE_MOZ_HANGUL_CONSONANT
:
1357 case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME
:
1358 case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_NUMERIC
:
1359 case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_AM
:
1360 case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ER
:
1361 case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ET
:
1362 GetListItemText(*myList
, text
);
1363 fm
->GetHeight(aMetrics
.height
);
1364 aRenderingContext
->SetFont(fm
);
1365 aMetrics
.width
= nsLayoutUtils::GetStringWidth(this, aRenderingContext
, text
.get(), text
.Length());
1366 aMetrics
.width
+= mPadding
.right
;
1367 fm
->GetMaxAscent(aMetrics
.ascent
);
1373 nsBulletFrame::Reflow(nsPresContext
* aPresContext
,
1374 nsHTMLReflowMetrics
& aMetrics
,
1375 const nsHTMLReflowState
& aReflowState
,
1376 nsReflowStatus
& aStatus
)
1378 DO_GLOBAL_REFLOW_COUNT("nsBulletFrame");
1379 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aMetrics
, aStatus
);
1381 // Get the base size
1382 GetDesiredSize(aPresContext
, aReflowState
.rendContext
, aMetrics
);
1384 // Add in the border and padding; split the top/bottom between the
1385 // ascent and descent to make things look nice
1386 const nsMargin
& borderPadding
= aReflowState
.mComputedBorderPadding
;
1387 aMetrics
.width
+= borderPadding
.left
+ borderPadding
.right
;
1388 aMetrics
.height
+= borderPadding
.top
+ borderPadding
.bottom
;
1389 aMetrics
.ascent
+= borderPadding
.top
;
1391 // XXX this is a bit of a hack, we're assuming that no glyphs used for bullets
1392 // overflow their font-boxes. It'll do for now; to fix it for real, we really
1393 // should rewrite all the text-handling code here to use gfxTextRun (bug
1395 aMetrics
.mOverflowArea
.SetRect(0, 0, aMetrics
.width
, aMetrics
.height
);
1397 aStatus
= NS_FRAME_COMPLETE
;
1398 NS_FRAME_SET_TRUNCATION(aStatus
, aReflowState
, aMetrics
);
1402 /* virtual */ nscoord
1403 nsBulletFrame::GetMinWidth(nsIRenderingContext
*aRenderingContext
)
1405 nsHTMLReflowMetrics metrics
;
1406 DISPLAY_MIN_WIDTH(this, metrics
.width
);
1407 GetDesiredSize(PresContext(), aRenderingContext
, metrics
);
1408 return metrics
.width
;
1411 /* virtual */ nscoord
1412 nsBulletFrame::GetPrefWidth(nsIRenderingContext
*aRenderingContext
)
1414 nsHTMLReflowMetrics metrics
;
1415 DISPLAY_PREF_WIDTH(this, metrics
.width
);
1416 GetDesiredSize(PresContext(), aRenderingContext
, metrics
);
1417 return metrics
.width
;
1421 NS_IMETHODIMP
nsBulletFrame::OnStartContainer(imgIRequest
*aRequest
,
1422 imgIContainer
*aImage
)
1424 if (!aImage
) return NS_ERROR_INVALID_ARG
;
1425 if (!aRequest
) return NS_ERROR_INVALID_ARG
;
1428 aRequest
->GetImageStatus(&status
);
1429 if (status
& imgIRequest::STATUS_ERROR
) {
1434 aImage
->GetWidth(&w
);
1435 aImage
->GetHeight(&h
);
1437 nsPresContext
* presContext
= PresContext();
1439 nsSize
newsize(nsPresContext::CSSPixelsToAppUnits(w
),
1440 nsPresContext::CSSPixelsToAppUnits(h
));
1442 if (mIntrinsicSize
!= newsize
) {
1443 mIntrinsicSize
= newsize
;
1445 // Now that the size is available (or an error occurred), trigger
1446 // a reflow of the bullet frame.
1447 nsIPresShell
*shell
= presContext
->GetPresShell();
1449 shell
->FrameNeedsReflow(this, nsIPresShell::eStyleChange
,
1454 // Handle animations
1455 aImage
->SetAnimationMode(presContext
->ImageAnimationMode());
1456 // Ensure the animation (if any) is started.
1457 aImage
->StartAnimation();
1463 NS_IMETHODIMP
nsBulletFrame::OnDataAvailable(imgIRequest
*aRequest
,
1464 gfxIImageFrame
*aFrame
,
1465 const nsRect
*aRect
)
1467 // The image has changed.
1468 // Invalidate the entire content area. Maybe it's not optimal but it's simple and
1469 // always correct, and I'll be a stunned mullet if it ever matters for performance
1470 Invalidate(nsRect(0, 0, mRect
.width
, mRect
.height
), PR_FALSE
);
1475 NS_IMETHODIMP
nsBulletFrame::OnStopDecode(imgIRequest
*aRequest
,
1477 const PRUnichar
*aStatusArg
)
1479 // XXX should the bulletframe do anything if the image failed to load?
1480 // it didn't in the old code...
1483 if (NS_FAILED(aStatus
)) {
1484 // We failed to load the image. Notify the pres shell
1485 if (NS_FAILED(aStatus
) && (mImageRequest
== aRequest
|| !mImageRequest
)) {
1486 imageFailed
= PR_TRUE
;
1494 NS_IMETHODIMP
nsBulletFrame::FrameChanged(imgIContainer
*aContainer
,
1495 gfxIImageFrame
*aNewFrame
,
1498 // Invalidate the entire content area. Maybe it's not optimal but it's simple and
1500 Invalidate(nsRect(0, 0, mRect
.width
, mRect
.height
), PR_FALSE
);
1506 nsBulletFrame::GetLoadGroup(nsPresContext
*aPresContext
, nsILoadGroup
**aLoadGroup
)
1511 NS_PRECONDITION(nsnull
!= aLoadGroup
, "null OUT parameter pointer");
1513 nsIPresShell
*shell
= aPresContext
->GetPresShell();
1518 nsIDocument
*doc
= shell
->GetDocument();
1522 *aLoadGroup
= doc
->GetDocumentLoadGroup().get(); // already_AddRefed
1532 NS_IMPL_ISUPPORTS2(nsBulletListener
, imgIDecoderObserver
, imgIContainerObserver
)
1534 nsBulletListener::nsBulletListener() :
1539 nsBulletListener::~nsBulletListener()
1543 NS_IMETHODIMP
nsBulletListener::OnStartContainer(imgIRequest
*aRequest
,
1544 imgIContainer
*aImage
)
1547 return NS_ERROR_FAILURE
;
1549 return mFrame
->OnStartContainer(aRequest
, aImage
);
1552 NS_IMETHODIMP
nsBulletListener::OnDataAvailable(imgIRequest
*aRequest
,
1553 gfxIImageFrame
*aFrame
,
1554 const nsRect
*aRect
)
1557 return NS_ERROR_FAILURE
;
1559 return mFrame
->OnDataAvailable(aRequest
, aFrame
, aRect
);
1562 NS_IMETHODIMP
nsBulletListener::OnStopDecode(imgIRequest
*aRequest
,
1564 const PRUnichar
*statusArg
)
1567 return NS_ERROR_FAILURE
;
1569 return mFrame
->OnStopDecode(aRequest
, status
, statusArg
);
1572 NS_IMETHODIMP
nsBulletListener::FrameChanged(imgIContainer
*aContainer
,
1573 gfxIImageFrame
*newframe
,
1577 return NS_ERROR_FAILURE
;
1579 return mFrame
->FrameChanged(aContainer
, newframe
, dirtyRect
);