📄 renderlistmarker.cpp
字号:
/* * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */#include "config.h"#include "RenderListMarker.h"#include "CachedImage.h"#include "CharacterNames.h"#include "Document.h"#include "GraphicsContext.h"#include "ListMarkerBox.h"#include "RenderLayer.h"#include "RenderListItem.h"#include "RenderView.h"using namespace std;using namespace WTF;using namespace Unicode;namespace WebCore {const int cMarkerPadding = 7;static String toRoman(int number, bool upper){ // FIXME: CSS3 describes how to make this work for much larger numbers, // using overbars and special characters. It also specifies the characters // in the range U+2160 to U+217F instead of standard ASCII ones. if (number < 1 || number > 3999) return String::number(number); const int lettersSize = 12; // big enough for three each of I, X, C, and M UChar letters[lettersSize]; int length = 0; const UChar ldigits[] = { 'i', 'v', 'x', 'l', 'c', 'd', 'm' }; const UChar udigits[] = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' }; const UChar* digits = upper ? udigits : ldigits; int d = 0; do { int num = number % 10; if (num % 5 < 4) for (int i = num % 5; i > 0; i--) letters[lettersSize - ++length] = digits[d]; if (num >= 4 && num <= 8) letters[lettersSize - ++length] = digits[d + 1]; if (num == 9) letters[lettersSize - ++length] = digits[d + 2]; if (num % 5 == 4) letters[lettersSize - ++length] = digits[d]; number /= 10; d += 2; } while (number); ASSERT(length <= lettersSize); return String(&letters[lettersSize - length], length);}static String toAlphabetic(int number, const UChar* alphabet, int alphabetSize){ ASSERT(alphabetSize >= 10); if (number < 1) return String::number(number); const int lettersSize = 10; // big enough for a 32-bit int, with a 10-letter alphabet UChar letters[lettersSize]; --number; letters[lettersSize - 1] = alphabet[number % alphabetSize]; int length = 1; while ((number /= alphabetSize) > 0) letters[lettersSize - ++length] = alphabet[number % alphabetSize - 1]; ASSERT(length <= lettersSize); return String(&letters[lettersSize - length], length);}static int toHebrewUnder1000(int number, UChar letters[5]){ // FIXME: CSS3 mentions various refinements not implemented here. // FIXME: Should take a look at Mozilla's HebrewToText function (in nsBulletFrame). ASSERT(number >= 0 && number < 1000); int length = 0; int fourHundreds = number / 400; for (int i = 0; i < fourHundreds; i++) letters[length++] = 1511 + 3; number %= 400; if (number / 100) letters[length++] = 1511 + (number / 100) - 1; number %= 100; if (number == 15 || number == 16) { letters[length++] = 1487 + 9; letters[length++] = 1487 + number - 9; } else { if (int tens = number / 10) { static const UChar hebrewTens[9] = { 1497, 1499, 1500, 1502, 1504, 1505, 1506, 1508, 1510 }; letters[length++] = hebrewTens[tens - 1]; } if (int ones = number % 10) letters[length++] = 1487 + ones; } ASSERT(length <= 5); return length;}static String toHebrew(int number){ // FIXME: CSS3 mentions ways to make this work for much larger numbers. if (number < 0 || number > 999999) return String::number(number); if (number == 0) { static const UChar hebrewZero[3] = { 0x05D0, 0x05E4, 0x05E1 }; return String(hebrewZero, 3); } const int lettersSize = 11; // big enough for two 5-digit sequences plus a quote mark between UChar letters[lettersSize]; int length; if (number < 1000) length = 0; else { length = toHebrewUnder1000(number / 1000, letters); letters[length++] = '\''; number = number % 1000; } length += toHebrewUnder1000(number, letters + length); ASSERT(length <= lettersSize); return String(letters, length);}static int toArmenianUnder10000(int number, bool upper, bool addCircumflex, UChar letters[9]){ ASSERT(number >= 0 && number < 10000); int length = 0; int lowerOffset = upper ? 0 : 0x0030; if (int thousands = number / 1000) if (thousands == 7) { letters[length++] = 0x0548 + lowerOffset; letters[length++] = 0x0552 + lowerOffset; if (addCircumflex) letters[length++] = 0x0302; } else { letters[length++] = (0x054C - 1 + lowerOffset) + thousands; if (addCircumflex) letters[length++] = 0x0302; } if (int hundreds = (number / 100) % 10) { letters[length++] = (0x0543 - 1 + lowerOffset) + hundreds; if (addCircumflex) letters[length++] = 0x0302; } if (int tens = (number / 10) % 10) { letters[length++] = (0x053A - 1 + lowerOffset) + tens; if (addCircumflex) letters[length++] = 0x0302; } if (int ones = number % 10) { letters[length++] = (0x531 - 1 + lowerOffset) + ones; if (addCircumflex) letters[length++] = 0x0302; } return length;}static String toArmenian(int number, bool upper){ if (number < 1 || number > 99999999) return String::number(number); const int lettersSize = 18; // twice what toArmenianUnder10000 needs UChar letters[lettersSize]; int length = toArmenianUnder10000(number / 10000, upper, true, letters); length += toArmenianUnder10000(number % 10000, upper, false, letters + length); ASSERT(length <= lettersSize); return String(letters, length);}static String toGeorgian(int number){ if (number < 1 || number > 19999) return String::number(number); const int lettersSize = 5; UChar letters[lettersSize]; int length = 0; if (number > 9999) letters[length++] = 0x10F5; if (int thousands = (number / 1000) % 10) { static const UChar georgianThousands[9] = { 0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10F4, 0x10EF, 0x10F0 }; letters[length++] = georgianThousands[thousands - 1]; } if (int hundreds = (number / 100) % 10) { static const UChar georgianHundreds[9] = { 0x10E0, 0x10E1, 0x10E2, 0x10F3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, 0x10E8 }; letters[length++] = georgianHundreds[hundreds - 1]; } if (int tens = (number / 10) % 10) { static const UChar georgianTens[9] = { 0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10F2, 0x10DD, 0x10DE, 0x10DF }; letters[length++] = georgianTens[tens - 1]; } if (int ones = number % 10) { static const UChar georgianOnes[9] = { 0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10F1, 0x10D7 }; letters[length++] = georgianOnes[ones - 1]; } ASSERT(length <= lettersSize); return String(letters, length);}// The table uses the order from the CSS3 specification:// first 3 group markers, then 3 digit markers, then ten digits.static String toCJKIdeographic(int number, const UChar table[16]){ if (number < 0) return String::number(number); enum AbstractCJKChar { noChar, secondGroupMarker, thirdGroupMarker, fourthGroupMarker, secondDigitMarker, thirdDigitMarker, fourthDigitMarker, digit0, digit1, digit2, digit3, digit4, digit5, digit6, digit7, digit8, digit9 }; if (number == 0) return String(&table[digit0 - 1], 1); const int groupLength = 8; // 4 digits, 3 digit markers, and a group marker const int bufferLength = 4 * groupLength; AbstractCJKChar buffer[bufferLength] = { noChar }; for (int i = 0; i < 4; ++i) { int groupValue = number % 10000; number /= 10000; // Process least-significant group first, but put it in the buffer last. AbstractCJKChar* group = &buffer[(3 - i) * groupLength]; if (groupValue && i) group[7] = static_cast<AbstractCJKChar>(secondGroupMarker - 1 + i); // Put in the four digits and digit markers for any non-zero digits. group[6] = static_cast<AbstractCJKChar>(digit0 + (groupValue % 10)); if (number != 0 || groupValue > 9) { int digitValue = ((groupValue / 10) % 10); group[4] = static_cast<AbstractCJKChar>(digit0 + digitValue); if (digitValue) group[5] = secondDigitMarker; } if (number != 0 || groupValue > 99) { int digitValue = ((groupValue / 100) % 10); group[2] = static_cast<AbstractCJKChar>(digit0 + digitValue); if (digitValue) group[3] = thirdDigitMarker; } if (number != 0 || groupValue > 999) { int digitValue = groupValue / 1000;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -