aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/generated_content.rs
diff options
context:
space:
mode:
authorSimon Sapin <simon.sapin@exyr.org>2015-03-03 21:16:24 +0100
committerSimon Sapin <simon.sapin@exyr.org>2015-03-03 21:16:24 +0100
commit4c1d778ced267eeef790d4166e361d9348b933d3 (patch)
treeccdd9544f8f4b7a2f6299244915584fcbf5cfc18 /components/layout/generated_content.rs
parent7a218b3f08c95b5c1a14ef1bbf09658d61b8d342 (diff)
downloadservo-4c1d778ced267eeef790d4166e361d9348b933d3.tar.gz
servo-4c1d778ced267eeef790d4166e361d9348b933d3.zip
Revert "layout: Implement ordered lists, CSS counters, and `quotes` per CSS 2.1"
This reverts commit 30fd28d1077fbb3f47140f6ab1252c0d24f44d23.
Diffstat (limited to 'components/layout/generated_content.rs')
-rw-r--r--components/layout/generated_content.rs573
1 files changed, 0 insertions, 573 deletions
diff --git a/components/layout/generated_content.rs b/components/layout/generated_content.rs
deleted file mode 100644
index d4ec6e5a534..00000000000
--- a/components/layout/generated_content.rs
+++ /dev/null
@@ -1,573 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-//! The generated content assignment phase.
-//!
-//! This phase handles CSS counters, quotes, and ordered lists per CSS § 12.3-12.5. It cannot be
-//! done in parallel and is therefore a sequential pass that runs on as little of the flow tree
-//! as possible.
-
-use context::LayoutContext;
-use flow::{self, AFFECTS_COUNTERS, Flow, HAS_COUNTER_AFFECTING_CHILDREN, ImmutableFlowUtils};
-use flow::{InorderFlowTraversal};
-use fragment::{Fragment, FragmentMutator, GeneratedContentInfo, SpecificFragmentInfo};
-use fragment::{UnscannedTextFragmentInfo};
-use incremental::{self, RESOLVE_GENERATED_CONTENT};
-use text::TextRunScanner;
-
-use gfx::display_list::OpaqueNode;
-use servo_util::smallvec::{SmallVec, SmallVec8};
-use std::collections::{DList, HashMap};
-use std::sync::Arc;
-use style::computed_values::content::ContentItem;
-use style::computed_values::{display, list_style_type};
-use style::properties::ComputedValues;
-
-// Decimal styles per CSS-COUNTER-STYLES § 6.1:
-static DECIMAL: [char; 10] = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ];
-// TODO(pcwalton): `decimal-leading-zero`
-static ARABIC_INDIC: [char; 10] = [ '٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩' ];
-// TODO(pcwalton): `armenian`, `upper-armenian`, `lower-armenian`
-static BENGALI: [char; 10] = [ '০', '১', '২', '৩', '৪', '৫', '৬', '৭', '৮', '৯' ];
-static CAMBODIAN: [char; 10] = [ '០', '១', '២', '៣', '៤', '៥', '៦', '៧', '៨', '៩' ];
-// TODO(pcwalton): Suffix for CJK decimal.
-static CJK_DECIMAL: [char; 10] = [ '〇', '一', '二', '三', '四', '五', '六', '七', '八', '九' ];
-static DEVANAGARI: [char; 10] = [ '०', '१', '२', '३', '४', '५', '६', '७', '८', '९' ];
-// TODO(pcwalton): `georgian`
-static GUJARATI: [char; 10] = ['૦', '૧', '૨', '૩', '૪', '૫', '૬', '૭', '૮', '૯'];
-static GURMUKHI: [char; 10] = ['੦', '੧', '੨', '੩', '੪', '੫', '੬', '੭', '੮', '੯'];
-// TODO(pcwalton): `hebrew`
-static KANNADA: [char; 10] = ['೦', '೧', '೨', '೩', '೪', '೫', '೬', '೭', '೮', '೯'];
-static LAO: [char; 10] = ['໐', '໑', '໒', '໓', '໔', '໕', '໖', '໗', '໘', '໙'];
-static MALAYALAM: [char; 10] = ['൦', '൧', '൨', '൩', '൪', '൫', '൬', '൭', '൮', '൯'];
-static MONGOLIAN: [char; 10] = ['᠐', '᠑', '᠒', '᠓', '᠔', '᠕', '᠖', '᠗', '᠘', '᠙'];
-static MYANMAR: [char; 10] = ['၀', '၁', '၂', '၃', '၄', '၅', '၆', '၇', '၈', '၉'];
-static ORIYA: [char; 10] = ['୦', '୧', '୨', '୩', '୪', '୫', '୬', '୭', '୮', '୯'];
-static PERSIAN: [char; 10] = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];
-// TODO(pcwalton): `lower-roman`, `upper-roman`
-static TELUGU: [char; 10] = ['౦', '౧', '౨', '౩', '౪', '౫', '౬', '౭', '౮', '౯'];
-static THAI: [char; 10] = ['๐', '๑', '๒', '๓', '๔', '๕', '๖', '๗', '๘', '๙'];
-static TIBETAN: [char; 10] = ['༠', '༡', '༢', '༣', '༤', '༥', '༦', '༧', '༨', '༩'];
-
-// Alphabetic styles per CSS-COUNTER-STYLES § 6.2:
-static LOWER_ALPHA: [char; 26] = [
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
- 't', 'u', 'v', 'w', 'x', 'y', 'z'
-];
-static UPPER_ALPHA: [char; 26] = [
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
- 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
-];
-static CJK_EARTHLY_BRANCH: [char; 12] = [
- '子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥'
-];
-static CJK_HEAVENLY_STEM: [char; 10] = [
- '甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'
-];
-static LOWER_GREEK: [char; 24] = [
- 'α', 'β', 'γ', 'δ', 'ε', 'ζ', 'η', 'θ', 'ι', 'κ', 'λ', 'μ', 'ν', 'ξ', 'ο', 'π', 'ρ', 'σ', 'τ',
- 'υ', 'φ', 'χ', 'ψ', 'ω'
-];
-static HIRAGANA: [char; 48] = [
- 'あ', 'い', 'う', 'え', 'お', 'か', 'き', 'く', 'け', 'こ', 'さ', 'し', 'す', 'せ', 'そ',
- 'た', 'ち', 'つ', 'て', 'と', 'な', 'に', 'ぬ', 'ね', 'の', 'は', 'ひ', 'ふ', 'へ', 'ほ',
- 'ま', 'み', 'む', 'め', 'も', 'や', 'ゆ', 'よ', 'ら', 'り', 'る', 'れ', 'ろ',
- 'わ', 'ゐ', 'ゑ', 'を', 'ん'
-];
-static HIRAGANA_IROHA: [char; 47] = [
- 'い', 'ろ', 'は', 'に', 'ほ', 'へ', 'と', 'ち', 'り', 'ぬ', 'る', 'を', 'わ', 'か', 'よ',
- 'た', 'れ', 'そ', 'つ', 'ね', 'な', 'ら', 'む', 'う', 'ゐ', 'の', 'お', 'く', 'や', 'ま',
- 'け', 'ふ', 'こ', 'え', 'て', 'あ', 'さ', 'き', 'ゆ', 'め', 'み', 'し', 'ゑ',
- 'ひ', 'も', 'せ', 'す'
-];
-static KATAKANA: [char; 48] = [
- 'ア', 'イ', 'ウ', 'エ', 'オ', 'カ', 'キ', 'ク', 'ケ', 'コ', 'サ', 'シ', 'ス', 'セ', 'ソ',
- 'タ', 'チ', 'ツ', 'テ', 'ト', 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ', 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ',
- 'マ', 'ミ', 'ム', 'メ', 'モ', 'ヤ', 'ユ', 'ヨ', 'ラ', 'リ', 'ル', 'レ', 'ロ',
- 'ワ', 'ヰ', 'ヱ', 'ヲ', 'ン'
-];
-static KATAKANA_IROHA: [char; 47] = [
- 'イ', 'ロ', 'ハ', 'ニ', 'ホ', 'ヘ', 'ト', 'チ', 'リ', 'ヌ', 'ル', 'ヲ', 'ワ', 'カ', 'ヨ',
- 'タ', 'レ', 'ソ', 'ツ', 'ネ', 'ナ', 'ラ', 'ム', 'ウ', 'ヰ', 'ノ', 'オ', 'ク', 'ヤ', 'マ',
- 'ケ', 'フ', 'コ', 'エ', 'テ', 'ア', 'サ', 'キ', 'ユ', 'メ', 'ミ', 'シ', 'ヱ',
- 'ヒ', 'モ', 'セ', 'ス'
-];
-
-/// The generated content resolution traversal.
-pub struct ResolveGeneratedContent<'a> {
- /// The layout context.
- layout_context: &'a LayoutContext<'a>,
- /// The counter representing an ordered list item.
- list_item: Counter,
- /// Named CSS counters.
- counters: HashMap<String,Counter>,
- /// The level of quote nesting.
- quote: u32,
-}
-
-impl<'a> ResolveGeneratedContent<'a> {
- /// Creates a new generated content resolution traversal.
- pub fn new(layout_context: &'a LayoutContext<'a>) -> ResolveGeneratedContent<'a> {
- ResolveGeneratedContent {
- layout_context: layout_context,
- list_item: Counter::new(),
- counters: HashMap::new(),
- quote: 0,
- }
- }
-}
-
-impl<'a> InorderFlowTraversal for ResolveGeneratedContent<'a> {
- #[inline]
- fn process(&mut self, flow: &mut Flow, level: u32) {
- let mut mutator = ResolveGeneratedContentFragmentMutator {
- traversal: self,
- level: level,
- is_block: flow.is_block_like(),
- incremented: false,
- };
- flow.mutate_fragments(&mut mutator);
- }
-
- #[inline]
- fn should_process(&mut self, flow: &mut Flow) -> bool {
- flow::base(flow).restyle_damage.intersects(RESOLVE_GENERATED_CONTENT) ||
- flow::base(flow).flags.intersects(AFFECTS_COUNTERS | HAS_COUNTER_AFFECTING_CHILDREN)
- }
-}
-
-/// The object that mutates the generated content fragments.
-struct ResolveGeneratedContentFragmentMutator<'a,'b:'a> {
- /// The traversal.
- traversal: &'a mut ResolveGeneratedContent<'b>,
- /// The level we're at in the flow tree.
- level: u32,
- /// Whether this flow is a block flow.
- is_block: bool,
- /// Whether we've incremented the counter yet.
- incremented: bool,
-}
-
-impl<'a,'b> FragmentMutator for ResolveGeneratedContentFragmentMutator<'a,'b> {
- fn process(&mut self, fragment: &mut Fragment) {
- // We only reset and/or increment counters once per flow. This avoids double-incrementing
- // counters on list items (once for the main fragment and once for the marker).
- if !self.incremented {
- self.reset_and_increment_counters_as_necessary(fragment);
- }
-
- let mut list_style_type = fragment.style().get_list().list_style_type;
- if fragment.style().get_box().display != display::T::list_item {
- list_style_type = list_style_type::T::none
- }
-
- let mut new_info = None;
- {
- let info =
- if let SpecificFragmentInfo::GeneratedContent(ref mut info) = fragment.specific {
- info
- } else {
- return
- };
-
- match **info {
- GeneratedContentInfo::ListItem => {
- new_info = self.traversal.list_item.render(self.traversal.layout_context,
- fragment.node,
- fragment.style.clone(),
- list_style_type,
- RenderingMode::Suffix(".\u{00a0}"))
- }
- GeneratedContentInfo::ContentItem(ContentItem::String(_)) => {
- // Nothing to do here.
- }
- GeneratedContentInfo::ContentItem(ContentItem::Counter(ref counter_name,
- list_style_type)) => {
- let mut temporary_counter = Counter::new();
- let counter = self.traversal
- .counters
- .get(counter_name.as_slice())
- .unwrap_or(&mut temporary_counter);
- new_info = counter.render(self.traversal.layout_context,
- fragment.node,
- fragment.style.clone(),
- list_style_type,
- RenderingMode::Plain)
- }
- GeneratedContentInfo::ContentItem(ContentItem::Counters(ref counter_name,
- ref separator,
- list_style_type)) => {
- let mut temporary_counter = Counter::new();
- let counter = self.traversal
- .counters
- .get(counter_name.as_slice())
- .unwrap_or(&mut temporary_counter);
- new_info = counter.render(self.traversal.layout_context,
- fragment.node,
- fragment.style.clone(),
- list_style_type,
- RenderingMode::All(separator.as_slice()))
- }
- GeneratedContentInfo::ContentItem(ContentItem::OpenQuote) => {
- new_info = Some(render_text(self.traversal.layout_context,
- fragment.node,
- fragment.style.clone(),
- self.quote(&*fragment.style, false)));
- self.traversal.quote += 1
- }
- GeneratedContentInfo::ContentItem(ContentItem::CloseQuote) => {
- if self.traversal.quote >= 1 {
- self.traversal.quote -= 1
- }
-
- new_info = Some(render_text(self.traversal.layout_context,
- fragment.node,
- fragment.style.clone(),
- self.quote(&*fragment.style, true)));
- }
- GeneratedContentInfo::ContentItem(ContentItem::NoOpenQuote) => {
- self.traversal.quote += 1
- }
- GeneratedContentInfo::ContentItem(ContentItem::NoCloseQuote) => {
- if self.traversal.quote >= 1 {
- self.traversal.quote -= 1
- }
- }
- }
- };
-
- if let Some(new_info) = new_info {
- fragment.specific = new_info
- }
- }
-}
-
-impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> {
- fn reset_and_increment_counters_as_necessary(&mut self, fragment: &mut Fragment) {
- let mut list_style_type = fragment.style().get_list().list_style_type;
- if !self.is_block || fragment.style().get_box().display != display::T::list_item {
- list_style_type = list_style_type::T::none
- }
-
- match list_style_type {
- list_style_type::T::disc | list_style_type::T::none | list_style_type::T::circle |
- list_style_type::T::square | list_style_type::T::disclosure_open |
- list_style_type::T::disclosure_closed => {}
- _ => self.traversal.list_item.increment(self.level, 1),
- }
-
- // Truncate down counters.
- for (_, counter) in self.traversal.counters.iter_mut() {
- counter.truncate_to_level(self.level);
- }
- self.traversal.list_item.truncate_to_level(self.level);
-
- for &(ref counter_name, value) in fragment.style().get_counters().counter_reset.0.iter() {
- if let Some(ref mut counter) = self.traversal.counters.get_mut(counter_name) {
- counter.reset(self.level, value);
- continue
- }
-
- let mut counter = Counter::new();
- counter.reset(self.level, value);
- self.traversal.counters.insert((*counter_name).clone(), counter);
- }
-
- for &(ref counter_name, value) in fragment.style()
- .get_counters()
- .counter_increment
- .0
- .iter() {
- if let Some(ref mut counter) = self.traversal.counters.get_mut(counter_name) {
- counter.increment(self.level, value);
- continue
- }
-
- let mut counter = Counter::new();
- counter.increment(self.level, value);
- self.traversal.counters.insert((*counter_name).clone(), counter);
- }
-
- self.incremented = true
- }
-
- fn quote(&self, style: &ComputedValues, close: bool) -> String {
- let quotes = &style.get_list().quotes;
- debug_assert!(!quotes.0.is_empty());
- let &(ref open_quote, ref close_quote) =
- if self.traversal.quote as uint >= quotes.0.len() {
- quotes.0.last().unwrap()
- } else {
- &quotes.0[self.traversal.quote as uint]
- };
- if close {
- close_quote.to_string()
- } else {
- open_quote.to_string()
- }
- }
-}
-
-/// A counter per CSS 2.1 § 12.4.
-struct Counter {
- /// The values at each level.
- values: Vec<CounterValue>,
-}
-
-impl Counter {
- fn new() -> Counter {
- Counter {
- values: Vec::new(),
- }
- }
-
- fn reset(&mut self, level: u32, value: i32) {
- // Do we have an instance of the counter at this level? If so, just mutate it.
- match self.values.last_mut() {
- Some(ref mut existing_value) if level == existing_value.level => {
- existing_value.value = value;
- return
- }
- _ => {}
- }
-
- // Otherwise, push a new instance of the counter.
- self.values.push(CounterValue {
- level: level,
- value: value,
- })
- }
-
- fn truncate_to_level(&mut self, level: u32) {
- let mut position = None;
- for (i, value) in self.values.iter().enumerate() {
- if value.level > level {
- position = Some(i);
- break
- }
- }
-
- if let Some(position) = position {
- self.values.truncate(position)
- }
- }
-
- fn increment(&mut self, level: u32, amount: i32) {
- if let Some(ref mut value) = self.values.last_mut() {
- value.value += amount;
- return
- }
-
- self.values.push(CounterValue {
- level: level,
- value: amount,
- })
- }
-
- fn render(&self,
- layout_context: &LayoutContext,
- node: OpaqueNode,
- style: Arc<ComputedValues>,
- list_style_type: list_style_type::T,
- mode: RenderingMode)
- -> Option<SpecificFragmentInfo> {
- let mut string = String::new();
- match mode {
- RenderingMode::Plain => {
- let value = match self.values.last() {
- Some(ref value) => value.value,
- None => 0,
- };
- push_representation(value, list_style_type, &mut string)
- }
- RenderingMode::Suffix(suffix) => {
- let value = match self.values.last() {
- Some(ref value) => value.value,
- None => 0,
- };
- push_representation(value, list_style_type, &mut string);
- string.push_str(suffix)
- }
- RenderingMode::All(separator) => {
- let mut first = true;
- for value in self.values.iter() {
- if !first {
- string.push_str(separator)
- }
- first = false;
- push_representation(value.value, list_style_type, &mut string)
- }
- }
- }
-
- if string.is_empty() {
- None
- } else {
- Some(render_text(layout_context, node, style, string))
- }
- }
-}
-
-/// How a counter value is to be rendered.
-enum RenderingMode<'a> {
- /// The innermost counter value is rendered with no extra decoration.
- Plain,
- /// The innermost counter value is rendered with the given string suffix.
- Suffix(&'a str),
- /// All values of the counter are rendered with the given separator string between them.
- All(&'a str),
-}
-
-/// The value of a counter at a given level.
-struct CounterValue {
- /// The level of the flow tree that this corresponds to.
- level: u32,
- /// The value of the counter at this level.
- value: i32,
-}
-
-/// Creates fragment info for a literal string.
-fn render_text(layout_context: &LayoutContext,
- node: OpaqueNode,
- style: Arc<ComputedValues>,
- string: String)
- -> SpecificFragmentInfo {
- let mut fragments = DList::new();
- let info = SpecificFragmentInfo::UnscannedText(UnscannedTextFragmentInfo::from_text(string));
- fragments.push_back(Fragment::from_opaque_node_and_style(node,
- style,
- incremental::all(),
- info));
- let fragments = TextRunScanner::new().scan_for_runs(layout_context.font_context(), fragments);
- debug_assert!(fragments.len() == 1);
- fragments.fragments.into_iter().next().unwrap().specific
-}
-
-/// Appends string that represents the value rendered using the system appropriate for the given
-/// `list-style-type` onto the given string.
-fn push_representation(value: i32, list_style_type: list_style_type::T, accumulator: &mut String) {
- match list_style_type {
- list_style_type::T::none => {}
- list_style_type::T::disc |
- list_style_type::T::circle |
- list_style_type::T::square |
- list_style_type::T::disclosure_open |
- list_style_type::T::disclosure_closed => {
- accumulator.push_str(static_representation(list_style_type).unwrap())
- }
- list_style_type::T::decimal => push_numeric_representation(value, &DECIMAL, accumulator),
- list_style_type::T::arabic_indic => {
- push_numeric_representation(value, &ARABIC_INDIC, accumulator)
- }
- list_style_type::T::bengali => push_numeric_representation(value, &BENGALI, accumulator),
- list_style_type::T::cambodian | list_style_type::T::khmer => {
- push_numeric_representation(value, &CAMBODIAN, accumulator)
- }
- list_style_type::T::cjk_decimal => {
- push_numeric_representation(value, &CJK_DECIMAL, accumulator)
- }
- list_style_type::T::devanagari => {
- push_numeric_representation(value, &DEVANAGARI, accumulator)
- }
- list_style_type::T::gujarati => push_numeric_representation(value, &GUJARATI, accumulator),
- list_style_type::T::gurmukhi => push_numeric_representation(value, &GURMUKHI, accumulator),
- list_style_type::T::kannada => push_numeric_representation(value, &KANNADA, accumulator),
- list_style_type::T::lao => push_numeric_representation(value, &LAO, accumulator),
- list_style_type::T::malayalam => {
- push_numeric_representation(value, &MALAYALAM, accumulator)
- }
- list_style_type::T::mongolian => {
- push_numeric_representation(value, &MONGOLIAN, accumulator)
- }
- list_style_type::T::myanmar => push_numeric_representation(value, &MYANMAR, accumulator),
- list_style_type::T::oriya => push_numeric_representation(value, &ORIYA, accumulator),
- list_style_type::T::persian => push_numeric_representation(value, &PERSIAN, accumulator),
- list_style_type::T::telugu => push_numeric_representation(value, &TELUGU, accumulator),
- list_style_type::T::thai => push_numeric_representation(value, &THAI, accumulator),
- list_style_type::T::tibetan => push_numeric_representation(value, &TIBETAN, accumulator),
- list_style_type::T::lower_alpha => {
- push_alphabetic_representation(value, &LOWER_ALPHA, accumulator)
- }
- list_style_type::T::upper_alpha => {
- push_alphabetic_representation(value, &UPPER_ALPHA, accumulator)
- }
- list_style_type::T::cjk_earthly_branch => {
- push_alphabetic_representation(value, &CJK_EARTHLY_BRANCH, accumulator)
- }
- list_style_type::T::cjk_heavenly_stem => {
- push_alphabetic_representation(value, &CJK_HEAVENLY_STEM, accumulator)
- }
- list_style_type::T::lower_greek => {
- push_alphabetic_representation(value, &LOWER_GREEK, accumulator)
- }
- list_style_type::T::hiragana => {
- push_alphabetic_representation(value, &HIRAGANA, accumulator)
- }
- list_style_type::T::hiragana_iroha => {
- push_alphabetic_representation(value, &HIRAGANA_IROHA, accumulator)
- }
- list_style_type::T::katakana => {
- push_alphabetic_representation(value, &KATAKANA, accumulator)
- }
- list_style_type::T::katakana_iroha => {
- push_alphabetic_representation(value, &KATAKANA_IROHA, accumulator)
- }
- }
-}
-
-/// Returns the static string that represents the value rendered using the given list-style, if
-/// possible.
-pub fn static_representation(list_style_type: list_style_type::T) -> Option<&'static str> {
- match list_style_type {
- list_style_type::T::disc => Some("•\u{00a0}"),
- list_style_type::T::circle => Some("◦\u{00a0}"),
- list_style_type::T::square => Some("▪\u{00a0}"),
- list_style_type::T::disclosure_open => Some("▾\u{00a0}"),
- list_style_type::T::disclosure_closed => Some("‣\u{00a0}"),
- _ => None,
- }
-}
-
-/// Pushes the string that represents the value rendered using the given *alphabetic system* onto
-/// the accumulator per CSS-COUNTER-STYLES § 3.1.4.
-fn push_alphabetic_representation(mut value: i32, system: &[char], accumulator: &mut String) {
- let mut string = SmallVec8::new();
- while value != 0 {
- // Step 1.
- value = value - 1;
- // Step 2.
- string.push(system[(value as uint) % system.len()]);
- // Step 3.
- value = ((value as uint) / system.len()) as i32;
- }
-
- for i in range(0, string.len()).rev() {
- accumulator.push(*string.get(i))
- }
-}
-
-/// Pushes the string that represents the value rendered using the given *numeric system* onto the
-/// accumulator per CSS-COUNTER-STYLES § 3.1.4.
-fn push_numeric_representation(mut value: i32, system: &[char], accumulator: &mut String) {
- // Step 1.
- if value == 0 {
- accumulator.push(system[0]);
- return
- }
-
- // Step 2.
- let mut string = SmallVec8::new();
- while value != 0 {
- // Step 2.1.
- string.push(system[(value as uint) % system.len()]);
- // Step 2.2.
- value = ((value as uint) / system.len()) as i32;
- }
-
- // Step 3.
- for i in range(0, string.len()).rev() {
- accumulator.push(*string.get(i))
- }
-}
-