mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
auto merge of #2365 : bjz/servo/generic-range, r=pcwalton
Signed integers allow for generic +ve/-ve offsets. r? @pcwalton
This commit is contained in:
commit
8e0febb109
11 changed files with 256 additions and 244 deletions
|
@ -395,7 +395,7 @@ pub struct TextDisplayItem {
|
||||||
pub text_run: Arc<~TextRun>,
|
pub text_run: Arc<~TextRun>,
|
||||||
|
|
||||||
/// The range of text within the text run.
|
/// The range of text within the text run.
|
||||||
pub range: Range,
|
pub range: Range<int>,
|
||||||
|
|
||||||
/// The color of the text.
|
/// The color of the text.
|
||||||
pub text_color: Color,
|
pub text_color: Color,
|
||||||
|
|
|
@ -330,7 +330,7 @@ impl Font {
|
||||||
pub fn draw_text_into_context(&mut self,
|
pub fn draw_text_into_context(&mut self,
|
||||||
rctx: &RenderContext,
|
rctx: &RenderContext,
|
||||||
run: &~TextRun,
|
run: &~TextRun,
|
||||||
range: &Range,
|
range: &Range<int>,
|
||||||
baseline_origin: Point2D<Au>,
|
baseline_origin: Point2D<Au>,
|
||||||
color: Color) {
|
color: Color) {
|
||||||
use libc::types::common::c99::{uint16_t, uint32_t};
|
use libc::types::common::c99::{uint16_t, uint32_t};
|
||||||
|
@ -353,7 +353,7 @@ impl Font {
|
||||||
|
|
||||||
let mut origin = baseline_origin.clone();
|
let mut origin = baseline_origin.clone();
|
||||||
let mut azglyphs = vec!();
|
let mut azglyphs = vec!();
|
||||||
azglyphs.reserve(range.length());
|
azglyphs.reserve(range.length() as uint);
|
||||||
|
|
||||||
for (glyphs, _offset, slice_range) in run.iter_slices_for_range(range) {
|
for (glyphs, _offset, slice_range) in run.iter_slices_for_range(range) {
|
||||||
for (_i, glyph) in glyphs.iter_glyphs_for_char_range(&slice_range) {
|
for (_i, glyph) in glyphs.iter_glyphs_for_char_range(&slice_range) {
|
||||||
|
@ -391,7 +391,7 @@ impl Font {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn measure_text(&self, run: &TextRun, range: &Range) -> RunMetrics {
|
pub fn measure_text(&self, run: &TextRun, range: &Range<int>) -> RunMetrics {
|
||||||
// TODO(Issue #199): alter advance direction for RTL
|
// TODO(Issue #199): alter advance direction for RTL
|
||||||
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
|
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
|
||||||
let mut advance = Au(0);
|
let mut advance = Au(0);
|
||||||
|
@ -405,7 +405,7 @@ impl Font {
|
||||||
|
|
||||||
pub fn measure_text_for_slice(&self,
|
pub fn measure_text_for_slice(&self,
|
||||||
glyphs: &GlyphStore,
|
glyphs: &GlyphStore,
|
||||||
slice_range: &Range)
|
slice_range: &Range<int>)
|
||||||
-> RunMetrics {
|
-> RunMetrics {
|
||||||
let mut advance = Au(0);
|
let mut advance = Au(0);
|
||||||
for (_i, glyph) in glyphs.iter_glyphs_for_char_range(slice_range) {
|
for (_i, glyph) in glyphs.iter_glyphs_for_char_range(slice_range) {
|
||||||
|
@ -420,7 +420,7 @@ impl Font {
|
||||||
self.make_shaper();
|
self.make_shaper();
|
||||||
let shaper = &self.shaper;
|
let shaper = &self.shaper;
|
||||||
self.shape_cache.find_or_create(&text, |txt| {
|
self.shape_cache.find_or_create(&text, |txt| {
|
||||||
let mut glyphs = GlyphStore::new(text.char_len(), is_whitespace);
|
let mut glyphs = GlyphStore::new(text.char_len() as int, is_whitespace);
|
||||||
shaper.get_ref().shape_text(*txt, &mut glyphs);
|
shaper.get_ref().shape_text(*txt, &mut glyphs);
|
||||||
Arc::new(glyphs)
|
Arc::new(glyphs)
|
||||||
})
|
})
|
||||||
|
|
|
@ -52,8 +52,8 @@ impl GlyphEntry {
|
||||||
|
|
||||||
// Create a GlyphEntry for uncommon case; should be accompanied by
|
// Create a GlyphEntry for uncommon case; should be accompanied by
|
||||||
// initialization of the actual DetailedGlyph data in DetailedGlyphStore
|
// initialization of the actual DetailedGlyph data in DetailedGlyphStore
|
||||||
fn complex(starts_cluster: bool, starts_ligature: bool, glyph_count: uint) -> GlyphEntry {
|
fn complex(starts_cluster: bool, starts_ligature: bool, glyph_count: int) -> GlyphEntry {
|
||||||
assert!(glyph_count <= u16::MAX as uint);
|
assert!(glyph_count <= u16::MAX as int);
|
||||||
|
|
||||||
debug!("creating complex glyph entry: starts_cluster={}, starts_ligature={}, \
|
debug!("creating complex glyph entry: starts_cluster={}, starts_ligature={}, \
|
||||||
glyph_count={}",
|
glyph_count={}",
|
||||||
|
@ -76,8 +76,8 @@ impl GlyphEntry {
|
||||||
|
|
||||||
/// Create a GlyphEntry for the case where glyphs couldn't be found for the specified
|
/// Create a GlyphEntry for the case where glyphs couldn't be found for the specified
|
||||||
/// character.
|
/// character.
|
||||||
fn missing(glyph_count: uint) -> GlyphEntry {
|
fn missing(glyph_count: int) -> GlyphEntry {
|
||||||
assert!(glyph_count <= u16::MAX as uint);
|
assert!(glyph_count <= u16::MAX as int);
|
||||||
|
|
||||||
GlyphEntry::new((glyph_count as u32) << GLYPH_COUNT_SHIFT)
|
GlyphEntry::new((glyph_count as u32) << GLYPH_COUNT_SHIFT)
|
||||||
}
|
}
|
||||||
|
@ -273,9 +273,9 @@ impl DetailedGlyph {
|
||||||
#[deriving(Eq, Clone)]
|
#[deriving(Eq, Clone)]
|
||||||
struct DetailedGlyphRecord {
|
struct DetailedGlyphRecord {
|
||||||
// source string offset/GlyphEntry offset in the TextRun
|
// source string offset/GlyphEntry offset in the TextRun
|
||||||
entry_offset: uint,
|
entry_offset: int,
|
||||||
// offset into the detailed glyphs buffer
|
// offset into the detailed glyphs buffer
|
||||||
detail_offset: uint
|
detail_offset: int
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for DetailedGlyphRecord {
|
impl Ord for DetailedGlyphRecord {
|
||||||
|
@ -316,13 +316,13 @@ impl<'a> DetailedGlyphStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_detailed_glyphs_for_entry(&mut self, entry_offset: uint, glyphs: &[DetailedGlyph]) {
|
fn add_detailed_glyphs_for_entry(&mut self, entry_offset: int, glyphs: &[DetailedGlyph]) {
|
||||||
let entry = DetailedGlyphRecord {
|
let entry = DetailedGlyphRecord {
|
||||||
entry_offset: entry_offset,
|
entry_offset: entry_offset,
|
||||||
detail_offset: self.detail_buffer.len()
|
detail_offset: self.detail_buffer.len() as int
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("Adding entry[off={:u}] for detailed glyphs: {:?}", entry_offset, glyphs);
|
debug!("Adding entry[off={}] for detailed glyphs: {:?}", entry_offset, glyphs);
|
||||||
|
|
||||||
/* TODO: don't actually assert this until asserts are compiled
|
/* TODO: don't actually assert this until asserts are compiled
|
||||||
in/out based on severity, debug/release, etc. This assertion
|
in/out based on severity, debug/release, etc. This assertion
|
||||||
|
@ -340,9 +340,9 @@ impl<'a> DetailedGlyphStore {
|
||||||
self.lookup_is_sorted = false;
|
self.lookup_is_sorted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_detailed_glyphs_for_entry(&'a self, entry_offset: uint, count: u16)
|
fn get_detailed_glyphs_for_entry(&'a self, entry_offset: int, count: u16)
|
||||||
-> &'a [DetailedGlyph] {
|
-> &'a [DetailedGlyph] {
|
||||||
debug!("Requesting detailed glyphs[n={:u}] for entry[off={:u}]", count as uint, entry_offset);
|
debug!("Requesting detailed glyphs[n={}] for entry[off={}]", count, entry_offset);
|
||||||
|
|
||||||
// FIXME: Is this right? --pcwalton
|
// FIXME: Is this right? --pcwalton
|
||||||
// TODO: should fix this somewhere else
|
// TODO: should fix this somewhere else
|
||||||
|
@ -371,7 +371,7 @@ impl<'a> DetailedGlyphStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_detailed_glyph_with_index(&'a self,
|
fn get_detailed_glyph_with_index(&'a self,
|
||||||
entry_offset: uint,
|
entry_offset: int,
|
||||||
detail_offset: u16)
|
detail_offset: u16)
|
||||||
-> &'a DetailedGlyph {
|
-> &'a DetailedGlyph {
|
||||||
assert!((detail_offset as uint) <= self.detail_buffer.len());
|
assert!((detail_offset as uint) <= self.detail_buffer.len());
|
||||||
|
@ -460,14 +460,14 @@ impl GlyphData {
|
||||||
// Rather than eagerly assembling and copying glyph data, it only retrieves
|
// Rather than eagerly assembling and copying glyph data, it only retrieves
|
||||||
// values as they are needed from the GlyphStore, using provided offsets.
|
// values as they are needed from the GlyphStore, using provided offsets.
|
||||||
pub enum GlyphInfo<'a> {
|
pub enum GlyphInfo<'a> {
|
||||||
SimpleGlyphInfo(&'a GlyphStore, uint),
|
SimpleGlyphInfo(&'a GlyphStore, int),
|
||||||
DetailGlyphInfo(&'a GlyphStore, uint, u16)
|
DetailGlyphInfo(&'a GlyphStore, int, u16)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> GlyphInfo<'a> {
|
impl<'a> GlyphInfo<'a> {
|
||||||
pub fn index(self) -> GlyphIndex {
|
pub fn index(self) -> GlyphIndex {
|
||||||
match self {
|
match self {
|
||||||
SimpleGlyphInfo(store, entry_i) => store.entry_buffer.get(entry_i).index(),
|
SimpleGlyphInfo(store, entry_i) => store.entry_buffer.get(entry_i as uint).index(),
|
||||||
DetailGlyphInfo(store, entry_i, detail_j) => {
|
DetailGlyphInfo(store, entry_i, detail_j) => {
|
||||||
store.detail_store.get_detailed_glyph_with_index(entry_i, detail_j).index
|
store.detail_store.get_detailed_glyph_with_index(entry_i, detail_j).index
|
||||||
}
|
}
|
||||||
|
@ -478,7 +478,7 @@ impl<'a> GlyphInfo<'a> {
|
||||||
// FIXME: Resolution conflicts with IteratorUtil trait so adding trailing _
|
// FIXME: Resolution conflicts with IteratorUtil trait so adding trailing _
|
||||||
pub fn advance(self) -> Au {
|
pub fn advance(self) -> Au {
|
||||||
match self {
|
match self {
|
||||||
SimpleGlyphInfo(store, entry_i) => store.entry_buffer.get(entry_i).advance(),
|
SimpleGlyphInfo(store, entry_i) => store.entry_buffer.get(entry_i as uint).advance(),
|
||||||
DetailGlyphInfo(store, entry_i, detail_j) => {
|
DetailGlyphInfo(store, entry_i, detail_j) => {
|
||||||
store.detail_store.get_detailed_glyph_with_index(entry_i, detail_j).advance
|
store.detail_store.get_detailed_glyph_with_index(entry_i, detail_j).advance
|
||||||
}
|
}
|
||||||
|
@ -509,18 +509,18 @@ pub struct GlyphStore {
|
||||||
impl<'a> GlyphStore {
|
impl<'a> GlyphStore {
|
||||||
// Initializes the glyph store, but doesn't actually shape anything.
|
// Initializes the glyph store, but doesn't actually shape anything.
|
||||||
// Use the set_glyph, set_glyphs() methods to store glyph data.
|
// Use the set_glyph, set_glyphs() methods to store glyph data.
|
||||||
pub fn new(length: uint, is_whitespace: bool) -> GlyphStore {
|
pub fn new(length: int, is_whitespace: bool) -> GlyphStore {
|
||||||
assert!(length > 0);
|
assert!(length > 0);
|
||||||
|
|
||||||
GlyphStore {
|
GlyphStore {
|
||||||
entry_buffer: Vec::from_elem(length, GlyphEntry::initial()),
|
entry_buffer: Vec::from_elem(length as uint, GlyphEntry::initial()),
|
||||||
detail_store: DetailedGlyphStore::new(),
|
detail_store: DetailedGlyphStore::new(),
|
||||||
is_whitespace: is_whitespace,
|
is_whitespace: is_whitespace,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn char_len(&self) -> uint {
|
pub fn char_len(&self) -> int {
|
||||||
self.entry_buffer.len()
|
self.entry_buffer.len() as int
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_whitespace(&self) -> bool {
|
pub fn is_whitespace(&self) -> bool {
|
||||||
|
@ -531,7 +531,7 @@ impl<'a> GlyphStore {
|
||||||
self.detail_store.ensure_sorted();
|
self.detail_store.ensure_sorted();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_glyph_for_char_index(&mut self, i: uint, data: &GlyphData) {
|
pub fn add_glyph_for_char_index(&mut self, i: int, data: &GlyphData) {
|
||||||
fn glyph_is_compressible(data: &GlyphData) -> bool {
|
fn glyph_is_compressible(data: &GlyphData) -> bool {
|
||||||
is_simple_glyph_id(data.index)
|
is_simple_glyph_id(data.index)
|
||||||
&& is_simple_advance(data.advance)
|
&& is_simple_advance(data.advance)
|
||||||
|
@ -540,7 +540,7 @@ impl<'a> GlyphStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(data.ligature_start); // can't compress ligature continuation glyphs.
|
assert!(data.ligature_start); // can't compress ligature continuation glyphs.
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len() as int);
|
||||||
|
|
||||||
let entry = match (data.is_missing, glyph_is_compressible(data)) {
|
let entry = match (data.is_missing, glyph_is_compressible(data)) {
|
||||||
(true, _) => GlyphEntry::missing(1),
|
(true, _) => GlyphEntry::missing(1),
|
||||||
|
@ -550,22 +550,22 @@ impl<'a> GlyphStore {
|
||||||
self.detail_store.add_detailed_glyphs_for_entry(i, glyph);
|
self.detail_store.add_detailed_glyphs_for_entry(i, glyph);
|
||||||
GlyphEntry::complex(data.cluster_start, data.ligature_start, 1)
|
GlyphEntry::complex(data.cluster_start, data.ligature_start, 1)
|
||||||
}
|
}
|
||||||
}.adapt_character_flags_of_entry(*self.entry_buffer.get(i));
|
}.adapt_character_flags_of_entry(*self.entry_buffer.get(i as uint));
|
||||||
|
|
||||||
*self.entry_buffer.get_mut(i) = entry;
|
*self.entry_buffer.get_mut(i as uint) = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_glyphs_for_char_index(&mut self, i: uint, data_for_glyphs: &[GlyphData]) {
|
pub fn add_glyphs_for_char_index(&mut self, i: int, data_for_glyphs: &[GlyphData]) {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len() as int);
|
||||||
assert!(data_for_glyphs.len() > 0);
|
assert!(data_for_glyphs.len() > 0);
|
||||||
|
|
||||||
let glyph_count = data_for_glyphs.len();
|
let glyph_count = data_for_glyphs.len() as int;
|
||||||
|
|
||||||
let first_glyph_data = data_for_glyphs[0];
|
let first_glyph_data = data_for_glyphs[0];
|
||||||
let entry = match first_glyph_data.is_missing {
|
let entry = match first_glyph_data.is_missing {
|
||||||
true => GlyphEntry::missing(glyph_count),
|
true => GlyphEntry::missing(glyph_count),
|
||||||
false => {
|
false => {
|
||||||
let glyphs_vec = slice::from_fn(glyph_count, |i| {
|
let glyphs_vec = slice::from_fn(glyph_count as uint, |i| {
|
||||||
DetailedGlyph::new(data_for_glyphs[i].index,
|
DetailedGlyph::new(data_for_glyphs[i].index,
|
||||||
data_for_glyphs[i].advance,
|
data_for_glyphs[i].advance,
|
||||||
data_for_glyphs[i].offset)
|
data_for_glyphs[i].offset)
|
||||||
|
@ -576,33 +576,33 @@ impl<'a> GlyphStore {
|
||||||
first_glyph_data.ligature_start,
|
first_glyph_data.ligature_start,
|
||||||
glyph_count)
|
glyph_count)
|
||||||
}
|
}
|
||||||
}.adapt_character_flags_of_entry(*self.entry_buffer.get(i));
|
}.adapt_character_flags_of_entry(*self.entry_buffer.get(i as uint));
|
||||||
|
|
||||||
debug!("Adding multiple glyphs[idx={:u}, count={:u}]: {:?}", i, glyph_count, entry);
|
debug!("Adding multiple glyphs[idx={}, count={}]: {:?}", i, glyph_count, entry);
|
||||||
|
|
||||||
*self.entry_buffer.get_mut(i) = entry;
|
*self.entry_buffer.get_mut(i as uint) = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
// used when a character index has no associated glyph---for example, a ligature continuation.
|
// used when a character index has no associated glyph---for example, a ligature continuation.
|
||||||
pub fn add_nonglyph_for_char_index(&mut self, i: uint, cluster_start: bool, ligature_start: bool) {
|
pub fn add_nonglyph_for_char_index(&mut self, i: int, cluster_start: bool, ligature_start: bool) {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len() as int);
|
||||||
|
|
||||||
let entry = GlyphEntry::complex(cluster_start, ligature_start, 0);
|
let entry = GlyphEntry::complex(cluster_start, ligature_start, 0);
|
||||||
debug!("adding spacer for chracter without associated glyph[idx={:u}]", i);
|
debug!("adding spacer for chracter without associated glyph[idx={}]", i);
|
||||||
|
|
||||||
*self.entry_buffer.get_mut(i) = entry;
|
*self.entry_buffer.get_mut(i as uint) = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_glyphs_for_char_index(&'a self, i: uint) -> GlyphIterator<'a> {
|
pub fn iter_glyphs_for_char_index(&'a self, i: int) -> GlyphIterator<'a> {
|
||||||
self.iter_glyphs_for_char_range(&Range::new(i, 1))
|
self.iter_glyphs_for_char_range(&Range::new(i as int, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn iter_glyphs_for_char_range(&'a self, rang: &Range) -> GlyphIterator<'a> {
|
pub fn iter_glyphs_for_char_range(&'a self, rang: &Range<int>) -> GlyphIterator<'a> {
|
||||||
if rang.begin() >= self.entry_buffer.len() {
|
if rang.begin() >= self.entry_buffer.len() as int {
|
||||||
fail!("iter_glyphs_for_range: range.begin beyond length!");
|
fail!("iter_glyphs_for_range: range.begin beyond length!");
|
||||||
}
|
}
|
||||||
if rang.end() > self.entry_buffer.len() {
|
if rang.end() > self.entry_buffer.len() as int {
|
||||||
fail!("iter_glyphs_for_range: range.end beyond length!");
|
fail!("iter_glyphs_for_range: range.end beyond length!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,73 +615,73 @@ impl<'a> GlyphStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
// getter methods
|
// getter methods
|
||||||
pub fn char_is_space(&self, i: uint) -> bool {
|
pub fn char_is_space(&self, i: int) -> bool {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len() as int);
|
||||||
self.entry_buffer.get(i).char_is_space()
|
self.entry_buffer.get(i as uint).char_is_space()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn char_is_tab(&self, i: uint) -> bool {
|
pub fn char_is_tab(&self, i: int) -> bool {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len() as int);
|
||||||
self.entry_buffer.get(i).char_is_tab()
|
self.entry_buffer.get(i as uint).char_is_tab()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn char_is_newline(&self, i: uint) -> bool {
|
pub fn char_is_newline(&self, i: int) -> bool {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len() as int);
|
||||||
self.entry_buffer.get(i).char_is_newline()
|
self.entry_buffer.get(i as uint).char_is_newline()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_ligature_start(&self, i: uint) -> bool {
|
pub fn is_ligature_start(&self, i: int) -> bool {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len() as int);
|
||||||
self.entry_buffer.get(i).is_ligature_start()
|
self.entry_buffer.get(i as uint).is_ligature_start()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_cluster_start(&self, i: uint) -> bool {
|
pub fn is_cluster_start(&self, i: int) -> bool {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len() as int);
|
||||||
self.entry_buffer.get(i).is_cluster_start()
|
self.entry_buffer.get(i as uint).is_cluster_start()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_break_before(&self, i: uint) -> BreakType {
|
pub fn can_break_before(&self, i: int) -> BreakType {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len() as int);
|
||||||
self.entry_buffer.get(i).can_break_before()
|
self.entry_buffer.get(i as uint).can_break_before()
|
||||||
}
|
}
|
||||||
|
|
||||||
// setter methods
|
// setter methods
|
||||||
pub fn set_char_is_space(&mut self, i: uint) {
|
pub fn set_char_is_space(&mut self, i: int) {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len() as int);
|
||||||
let entry = *self.entry_buffer.get(i);
|
let entry = *self.entry_buffer.get(i as uint);
|
||||||
*self.entry_buffer.get_mut(i) = entry.set_char_is_space();
|
*self.entry_buffer.get_mut(i as uint) = entry.set_char_is_space();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_char_is_tab(&mut self, i: uint) {
|
pub fn set_char_is_tab(&mut self, i: int) {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len() as int);
|
||||||
let entry = *self.entry_buffer.get(i);
|
let entry = *self.entry_buffer.get(i as uint);
|
||||||
*self.entry_buffer.get_mut(i) = entry.set_char_is_tab();
|
*self.entry_buffer.get_mut(i as uint) = entry.set_char_is_tab();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_char_is_newline(&mut self, i: uint) {
|
pub fn set_char_is_newline(&mut self, i: int) {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len() as int);
|
||||||
let entry = *self.entry_buffer.get(i);
|
let entry = *self.entry_buffer.get(i as uint);
|
||||||
*self.entry_buffer.get_mut(i) = entry.set_char_is_newline();
|
*self.entry_buffer.get_mut(i as uint) = entry.set_char_is_newline();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_can_break_before(&mut self, i: uint, t: BreakType) {
|
pub fn set_can_break_before(&mut self, i: int, t: BreakType) {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len() as int);
|
||||||
let entry = *self.entry_buffer.get(i);
|
let entry = *self.entry_buffer.get(i as uint);
|
||||||
*self.entry_buffer.get_mut(i) = entry.set_can_break_before(t);
|
*self.entry_buffer.get_mut(i as uint) = entry.set_can_break_before(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GlyphIterator<'a> {
|
pub struct GlyphIterator<'a> {
|
||||||
store: &'a GlyphStore,
|
store: &'a GlyphStore,
|
||||||
char_index: uint,
|
char_index: int,
|
||||||
char_range: iter::Range<uint>,
|
char_range: iter::Range<int>,
|
||||||
glyph_range: Option<iter::Range<uint>>,
|
glyph_range: Option<iter::Range<int>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> GlyphIterator<'a> {
|
impl<'a> GlyphIterator<'a> {
|
||||||
// Slow path when there is a glyph range.
|
// Slow path when there is a glyph range.
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn next_glyph_range(&mut self) -> Option<(uint, GlyphInfo<'a>)> {
|
fn next_glyph_range(&mut self) -> Option<(int, GlyphInfo<'a>)> {
|
||||||
match self.glyph_range.get_mut_ref().next() {
|
match self.glyph_range.get_mut_ref().next() {
|
||||||
Some(j) => Some((self.char_index,
|
Some(j) => Some((self.char_index,
|
||||||
DetailGlyphInfo(self.store, self.char_index, j as u16))),
|
DetailGlyphInfo(self.store, self.char_index, j as u16))),
|
||||||
|
@ -695,15 +695,15 @@ impl<'a> GlyphIterator<'a> {
|
||||||
|
|
||||||
// Slow path when there is a complex glyph.
|
// Slow path when there is a complex glyph.
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn next_complex_glyph(&mut self, entry: &GlyphEntry, i: uint)
|
fn next_complex_glyph(&mut self, entry: &GlyphEntry, i: int)
|
||||||
-> Option<(uint, GlyphInfo<'a>)> {
|
-> Option<(int, GlyphInfo<'a>)> {
|
||||||
let glyphs = self.store.detail_store.get_detailed_glyphs_for_entry(i, entry.glyph_count());
|
let glyphs = self.store.detail_store.get_detailed_glyphs_for_entry(i, entry.glyph_count());
|
||||||
self.glyph_range = Some(range(0, glyphs.len()));
|
self.glyph_range = Some(range(0, glyphs.len() as int));
|
||||||
self.next()
|
self.next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator<(uint, GlyphInfo<'a>)> for GlyphIterator<'a> {
|
impl<'a> Iterator<(int, GlyphInfo<'a>)> for GlyphIterator<'a> {
|
||||||
// I tried to start with something simpler and apply FlatMap, but the
|
// I tried to start with something simpler and apply FlatMap, but the
|
||||||
// inability to store free variables in the FlatMap struct was problematic.
|
// inability to store free variables in the FlatMap struct was problematic.
|
||||||
//
|
//
|
||||||
|
@ -711,7 +711,7 @@ impl<'a> Iterator<(uint, GlyphInfo<'a>)> for GlyphIterator<'a> {
|
||||||
// slow paths, which should not be inlined, are `next_glyph_range()` and
|
// slow paths, which should not be inlined, are `next_glyph_range()` and
|
||||||
// `next_complex_glyph()`.
|
// `next_complex_glyph()`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn next(&mut self) -> Option<(uint, GlyphInfo<'a>)> {
|
fn next(&mut self) -> Option<(int, GlyphInfo<'a>)> {
|
||||||
// Would use 'match' here but it borrows contents in a way that
|
// Would use 'match' here but it borrows contents in a way that
|
||||||
// interferes with mutation.
|
// interferes with mutation.
|
||||||
if self.glyph_range.is_some() {
|
if self.glyph_range.is_some() {
|
||||||
|
@ -721,8 +721,8 @@ impl<'a> Iterator<(uint, GlyphInfo<'a>)> for GlyphIterator<'a> {
|
||||||
match self.char_range.next() {
|
match self.char_range.next() {
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
self.char_index = i;
|
self.char_index = i;
|
||||||
assert!(i < self.store.entry_buffer.len());
|
assert!(i < self.store.entry_buffer.len() as int);
|
||||||
let entry = self.store.entry_buffer.get(i);
|
let entry = self.store.entry_buffer.get(i as uint);
|
||||||
if entry.is_simple() {
|
if entry.is_simple() {
|
||||||
Some((self.char_index, SimpleGlyphInfo(self.store, i)))
|
Some((self.char_index, SimpleGlyphInfo(self.store, i)))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -48,13 +48,13 @@ static NO_GLYPH: i32 = -1;
|
||||||
static CONTINUATION_BYTE: i32 = -2;
|
static CONTINUATION_BYTE: i32 = -2;
|
||||||
|
|
||||||
pub struct ShapedGlyphData {
|
pub struct ShapedGlyphData {
|
||||||
count: uint,
|
count: int,
|
||||||
glyph_infos: *hb_glyph_info_t,
|
glyph_infos: *hb_glyph_info_t,
|
||||||
pos_infos: *hb_glyph_position_t,
|
pos_infos: *hb_glyph_position_t,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ShapedGlyphEntry {
|
pub struct ShapedGlyphEntry {
|
||||||
cluster: uint,
|
cluster: int,
|
||||||
codepoint: GlyphIndex,
|
codepoint: GlyphIndex,
|
||||||
advance: Au,
|
advance: Au,
|
||||||
offset: Option<Point2D<Au>>,
|
offset: Option<Point2D<Au>>,
|
||||||
|
@ -65,12 +65,13 @@ impl ShapedGlyphData {
|
||||||
unsafe {
|
unsafe {
|
||||||
let glyph_count = 0;
|
let glyph_count = 0;
|
||||||
let glyph_infos = hb_buffer_get_glyph_infos(buffer, &glyph_count);
|
let glyph_infos = hb_buffer_get_glyph_infos(buffer, &glyph_count);
|
||||||
let glyph_count = glyph_count as uint;
|
let glyph_count = glyph_count as int;
|
||||||
assert!(glyph_infos.is_not_null());
|
assert!(glyph_infos.is_not_null());
|
||||||
let pos_count = 0;
|
let pos_count = 0;
|
||||||
let pos_infos = hb_buffer_get_glyph_positions(buffer, &pos_count);
|
let pos_infos = hb_buffer_get_glyph_positions(buffer, &pos_count);
|
||||||
|
let pos_count = pos_count as int;
|
||||||
assert!(pos_infos.is_not_null());
|
assert!(pos_infos.is_not_null());
|
||||||
assert!(glyph_count == pos_count as uint);
|
assert!(glyph_count == pos_count);
|
||||||
|
|
||||||
ShapedGlyphData {
|
ShapedGlyphData {
|
||||||
count: glyph_count,
|
count: glyph_count,
|
||||||
|
@ -81,26 +82,26 @@ impl ShapedGlyphData {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn byte_offset_of_glyph(&self, i: uint) -> uint {
|
fn byte_offset_of_glyph(&self, i: int) -> int {
|
||||||
assert!(i < self.count);
|
assert!(i < self.count);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let glyph_info_i = self.glyph_infos.offset(i as int);
|
let glyph_info_i = self.glyph_infos.offset(i);
|
||||||
(*glyph_info_i).cluster as uint
|
(*glyph_info_i).cluster as int
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> uint {
|
pub fn len(&self) -> int {
|
||||||
self.count
|
self.count
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns shaped glyph data for one glyph, and updates the y-position of the pen.
|
/// Returns shaped glyph data for one glyph, and updates the y-position of the pen.
|
||||||
pub fn get_entry_for_glyph(&self, i: uint, y_pos: &mut Au) -> ShapedGlyphEntry {
|
pub fn get_entry_for_glyph(&self, i: int, y_pos: &mut Au) -> ShapedGlyphEntry {
|
||||||
assert!(i < self.count);
|
assert!(i < self.count);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let glyph_info_i = self.glyph_infos.offset(i as int);
|
let glyph_info_i = self.glyph_infos.offset(i);
|
||||||
let pos_info_i = self.pos_infos.offset(i as int);
|
let pos_info_i = self.pos_infos.offset(i);
|
||||||
let x_offset = Shaper::fixed_to_float((*pos_info_i).x_offset);
|
let x_offset = Shaper::fixed_to_float((*pos_info_i).x_offset);
|
||||||
let y_offset = Shaper::fixed_to_float((*pos_info_i).y_offset);
|
let y_offset = Shaper::fixed_to_float((*pos_info_i).y_offset);
|
||||||
let x_advance = Shaper::fixed_to_float((*pos_info_i).x_advance);
|
let x_advance = Shaper::fixed_to_float((*pos_info_i).x_advance);
|
||||||
|
@ -123,7 +124,7 @@ impl ShapedGlyphData {
|
||||||
};
|
};
|
||||||
|
|
||||||
ShapedGlyphEntry {
|
ShapedGlyphEntry {
|
||||||
cluster: (*glyph_info_i).cluster as uint,
|
cluster: (*glyph_info_i).cluster as int,
|
||||||
codepoint: (*glyph_info_i).codepoint as GlyphIndex,
|
codepoint: (*glyph_info_i).codepoint as GlyphIndex,
|
||||||
advance: x_advance,
|
advance: x_advance,
|
||||||
offset: offset,
|
offset: offset,
|
||||||
|
@ -223,8 +224,8 @@ impl Shaper {
|
||||||
fn save_glyph_results(&self, text: &str, glyphs: &mut GlyphStore, buffer: *hb_buffer_t) {
|
fn save_glyph_results(&self, text: &str, glyphs: &mut GlyphStore, buffer: *hb_buffer_t) {
|
||||||
let glyph_data = ShapedGlyphData::new(buffer);
|
let glyph_data = ShapedGlyphData::new(buffer);
|
||||||
let glyph_count = glyph_data.len();
|
let glyph_count = glyph_data.len();
|
||||||
let byte_max = text.len();
|
let byte_max = text.len() as int;
|
||||||
let char_max = text.char_len();
|
let char_max = text.char_len() as int;
|
||||||
|
|
||||||
// GlyphStore records are indexed by character, not byte offset.
|
// GlyphStore records are indexed by character, not byte offset.
|
||||||
// so, we must be careful to increment this when saving glyph entries.
|
// so, we must be careful to increment this when saving glyph entries.
|
||||||
|
@ -232,7 +233,7 @@ impl Shaper {
|
||||||
|
|
||||||
assert!(glyph_count <= char_max);
|
assert!(glyph_count <= char_max);
|
||||||
|
|
||||||
debug!("Shaped text[char count={:u}], got back {:u} glyph info records.",
|
debug!("Shaped text[char count={}], got back {} glyph info records.",
|
||||||
char_max,
|
char_max,
|
||||||
glyph_count);
|
glyph_count);
|
||||||
|
|
||||||
|
@ -246,9 +247,9 @@ impl Shaper {
|
||||||
|
|
||||||
// fast path: all chars are single-byte.
|
// fast path: all chars are single-byte.
|
||||||
if byte_max == char_max {
|
if byte_max == char_max {
|
||||||
byteToGlyph = slice::from_elem(byte_max, NO_GLYPH);
|
byteToGlyph = slice::from_elem(byte_max as uint, NO_GLYPH);
|
||||||
} else {
|
} else {
|
||||||
byteToGlyph = slice::from_elem(byte_max, CONTINUATION_BYTE);
|
byteToGlyph = slice::from_elem(byte_max as uint, CONTINUATION_BYTE);
|
||||||
for (i, _) in text.char_indices() {
|
for (i, _) in text.char_indices() {
|
||||||
byteToGlyph[i] = NO_GLYPH;
|
byteToGlyph[i] = NO_GLYPH;
|
||||||
}
|
}
|
||||||
|
@ -259,27 +260,27 @@ impl Shaper {
|
||||||
// loc refers to a *byte* offset within the utf8 string.
|
// loc refers to a *byte* offset within the utf8 string.
|
||||||
let loc = glyph_data.byte_offset_of_glyph(i);
|
let loc = glyph_data.byte_offset_of_glyph(i);
|
||||||
if loc < byte_max {
|
if loc < byte_max {
|
||||||
assert!(byteToGlyph[loc] != CONTINUATION_BYTE);
|
assert!(byteToGlyph[loc as uint] != CONTINUATION_BYTE);
|
||||||
byteToGlyph[loc] = i as i32;
|
byteToGlyph[loc as uint] = i as i32;
|
||||||
} else {
|
} else {
|
||||||
debug!("ERROR: tried to set out of range byteToGlyph: idx={:u}, glyph idx={:u}",
|
debug!("ERROR: tried to set out of range byteToGlyph: idx={}, glyph idx={}",
|
||||||
loc,
|
loc,
|
||||||
i);
|
i);
|
||||||
}
|
}
|
||||||
debug!("{:u} -> {:u}", i, loc);
|
debug!("{} -> {}", i, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("text: {:s}", text);
|
debug!("text: {:s}", text);
|
||||||
debug!("(char idx): char->(glyph index):");
|
debug!("(char idx): char->(glyph index):");
|
||||||
for (i, ch) in text.char_indices() {
|
for (i, ch) in text.char_indices() {
|
||||||
debug!("{:u}: {} --> {:d}", i, ch, byteToGlyph[i] as int);
|
debug!("{}: {} --> {:d}", i, ch, byteToGlyph[i] as int);
|
||||||
}
|
}
|
||||||
|
|
||||||
// some helpers
|
// some helpers
|
||||||
let mut glyph_span: Range = Range::empty();
|
let mut glyph_span: Range<int> = Range::empty();
|
||||||
// this span contains first byte of first char, to last byte of last char in range.
|
// this span contains first byte of first char, to last byte of last char in range.
|
||||||
// so, end() points to first byte of last+1 char, if it's less than byte_max.
|
// so, end() points to first byte of last+1 char, if it's less than byte_max.
|
||||||
let mut char_byte_span: Range = Range::empty();
|
let mut char_byte_span: Range<int> = Range::empty();
|
||||||
let mut y_pos = Au(0);
|
let mut y_pos = Au(0);
|
||||||
|
|
||||||
// main loop over each glyph. each iteration usually processes 1 glyph and 1+ chars.
|
// main loop over each glyph. each iteration usually processes 1 glyph and 1+ chars.
|
||||||
|
@ -288,7 +289,7 @@ impl Shaper {
|
||||||
while glyph_span.begin() < glyph_count {
|
while glyph_span.begin() < glyph_count {
|
||||||
// start by looking at just one glyph.
|
// start by looking at just one glyph.
|
||||||
glyph_span.extend_by(1);
|
glyph_span.extend_by(1);
|
||||||
debug!("Processing glyph at idx={:u}", glyph_span.begin());
|
debug!("Processing glyph at idx={}", glyph_span.begin());
|
||||||
|
|
||||||
let char_byte_start = glyph_data.byte_offset_of_glyph(glyph_span.begin());
|
let char_byte_start = glyph_data.byte_offset_of_glyph(glyph_span.begin());
|
||||||
char_byte_span.reset(char_byte_start, 0);
|
char_byte_span.reset(char_byte_start, 0);
|
||||||
|
@ -296,34 +297,34 @@ impl Shaper {
|
||||||
// find a range of chars corresponding to this glyph, plus
|
// find a range of chars corresponding to this glyph, plus
|
||||||
// any trailing chars that do not have associated glyphs.
|
// any trailing chars that do not have associated glyphs.
|
||||||
while char_byte_span.end() < byte_max {
|
while char_byte_span.end() < byte_max {
|
||||||
let range = text.char_range_at(char_byte_span.end());
|
let range = text.char_range_at(char_byte_span.end() as uint);
|
||||||
drop(range.ch);
|
drop(range.ch);
|
||||||
char_byte_span.extend_to(range.next);
|
char_byte_span.extend_to(range.next as int);
|
||||||
|
|
||||||
debug!("Processing char byte span: off={:u}, len={:u} for glyph idx={:u}",
|
debug!("Processing char byte span: off={}, len={} for glyph idx={}",
|
||||||
char_byte_span.begin(), char_byte_span.length(), glyph_span.begin());
|
char_byte_span.begin(), char_byte_span.length(), glyph_span.begin());
|
||||||
|
|
||||||
while char_byte_span.end() != byte_max &&
|
while char_byte_span.end() != byte_max &&
|
||||||
byteToGlyph[char_byte_span.end()] == NO_GLYPH {
|
byteToGlyph[char_byte_span.end() as uint] == NO_GLYPH {
|
||||||
debug!("Extending char byte span to include byte offset={:u} with no associated \
|
debug!("Extending char byte span to include byte offset={} with no associated \
|
||||||
glyph", char_byte_span.end());
|
glyph", char_byte_span.end());
|
||||||
let range = text.char_range_at(char_byte_span.end());
|
let range = text.char_range_at(char_byte_span.end() as uint);
|
||||||
drop(range.ch);
|
drop(range.ch);
|
||||||
char_byte_span.extend_to(range.next);
|
char_byte_span.extend_to(range.next as int);
|
||||||
}
|
}
|
||||||
|
|
||||||
// extend glyph range to max glyph index covered by char_span,
|
// extend glyph range to max glyph index covered by char_span,
|
||||||
// in cases where one char made several glyphs and left some unassociated chars.
|
// in cases where one char made several glyphs and left some unassociated chars.
|
||||||
let mut max_glyph_idx = glyph_span.end();
|
let mut max_glyph_idx = glyph_span.end();
|
||||||
for i in char_byte_span.eachi() {
|
for i in char_byte_span.eachi() {
|
||||||
if byteToGlyph[i] > NO_GLYPH {
|
if byteToGlyph[i as uint] > NO_GLYPH {
|
||||||
max_glyph_idx = cmp::max(byteToGlyph[i] as uint + 1, max_glyph_idx);
|
max_glyph_idx = cmp::max(byteToGlyph[i as uint] as int + 1, max_glyph_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if max_glyph_idx > glyph_span.end() {
|
if max_glyph_idx > glyph_span.end() {
|
||||||
glyph_span.extend_to(max_glyph_idx);
|
glyph_span.extend_to(max_glyph_idx);
|
||||||
debug!("Extended glyph span (off={:u}, len={:u}) to cover char byte span's max \
|
debug!("Extended glyph span (off={}, len={}) to cover char byte span's max \
|
||||||
glyph index",
|
glyph index",
|
||||||
glyph_span.begin(), glyph_span.length());
|
glyph_span.begin(), glyph_span.length());
|
||||||
}
|
}
|
||||||
|
@ -376,10 +377,10 @@ impl Shaper {
|
||||||
let mut covered_byte_span = char_byte_span.clone();
|
let mut covered_byte_span = char_byte_span.clone();
|
||||||
// extend, clipping at end of text range.
|
// extend, clipping at end of text range.
|
||||||
while covered_byte_span.end() < byte_max
|
while covered_byte_span.end() < byte_max
|
||||||
&& byteToGlyph[covered_byte_span.end()] == NO_GLYPH {
|
&& byteToGlyph[covered_byte_span.end() as uint] == NO_GLYPH {
|
||||||
let range = text.char_range_at(covered_byte_span.end());
|
let range = text.char_range_at(covered_byte_span.end() as uint);
|
||||||
drop(range.ch);
|
drop(range.ch);
|
||||||
covered_byte_span.extend_to(range.next);
|
covered_byte_span.extend_to(range.next as int);
|
||||||
}
|
}
|
||||||
|
|
||||||
if covered_byte_span.begin() >= byte_max {
|
if covered_byte_span.begin() >= byte_max {
|
||||||
|
@ -430,9 +431,9 @@ impl Shaper {
|
||||||
// set the other chars, who have no glyphs
|
// set the other chars, who have no glyphs
|
||||||
let mut i = covered_byte_span.begin();
|
let mut i = covered_byte_span.begin();
|
||||||
loop {
|
loop {
|
||||||
let range = text.char_range_at(i);
|
let range = text.char_range_at(i as uint);
|
||||||
drop(range.ch);
|
drop(range.ch);
|
||||||
i = range.next;
|
i = range.next as int;
|
||||||
if i >= covered_byte_span.end() { break; }
|
if i >= covered_byte_span.end() { break; }
|
||||||
char_idx += 1;
|
char_idx += 1;
|
||||||
glyphs.add_nonglyph_for_char_index(char_idx, false, false);
|
glyphs.add_nonglyph_for_char_index(char_idx, false, false);
|
||||||
|
|
|
@ -23,14 +23,14 @@ pub struct TextRun {
|
||||||
|
|
||||||
pub struct SliceIterator<'a> {
|
pub struct SliceIterator<'a> {
|
||||||
glyph_iter: Items<'a, Arc<GlyphStore>>,
|
glyph_iter: Items<'a, Arc<GlyphStore>>,
|
||||||
range: Range,
|
range: Range<int>,
|
||||||
offset: uint,
|
offset: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator<(&'a GlyphStore, uint, Range)> for SliceIterator<'a> {
|
impl<'a> Iterator<(&'a GlyphStore, int, Range<int>)> for SliceIterator<'a> {
|
||||||
// inline(always) due to the inefficient rt failures messing up inline heuristics, I think.
|
// inline(always) due to the inefficient rt failures messing up inline heuristics, I think.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn next(&mut self) -> Option<(&'a GlyphStore, uint, Range)> {
|
fn next(&mut self) -> Option<(&'a GlyphStore, int, Range<int>)> {
|
||||||
loop {
|
loop {
|
||||||
let slice_glyphs = self.glyph_iter.next();
|
let slice_glyphs = self.glyph_iter.next();
|
||||||
if slice_glyphs.is_none() {
|
if slice_glyphs.is_none() {
|
||||||
|
@ -52,13 +52,13 @@ impl<'a> Iterator<(&'a GlyphStore, uint, Range)> for SliceIterator<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LineIterator<'a> {
|
pub struct LineIterator<'a> {
|
||||||
range: Range,
|
range: Range<int>,
|
||||||
clump: Option<Range>,
|
clump: Option<Range<int>>,
|
||||||
slices: SliceIterator<'a>,
|
slices: SliceIterator<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator<Range> for LineIterator<'a> {
|
impl<'a> Iterator<Range<int>> for LineIterator<'a> {
|
||||||
fn next(&mut self) -> Option<Range> {
|
fn next(&mut self) -> Option<Range<int>> {
|
||||||
// Loop until we hit whitespace and are in a clump.
|
// Loop until we hit whitespace and are in a clump.
|
||||||
loop {
|
loop {
|
||||||
match self.slices.next() {
|
match self.slices.next() {
|
||||||
|
@ -165,8 +165,8 @@ impl<'a> TextRun {
|
||||||
glyphs
|
glyphs
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn char_len(&self) -> uint {
|
pub fn char_len(&self) -> int {
|
||||||
self.glyphs.iter().fold(0u, |len, slice_glyphs| {
|
self.glyphs.iter().fold(0, |len, slice_glyphs| {
|
||||||
len + slice_glyphs.char_len()
|
len + slice_glyphs.char_len()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -175,14 +175,14 @@ impl<'a> TextRun {
|
||||||
&*self.glyphs
|
&*self.glyphs
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn range_is_trimmable_whitespace(&self, range: &Range) -> bool {
|
pub fn range_is_trimmable_whitespace(&self, range: &Range<int>) -> bool {
|
||||||
for (slice_glyphs, _, _) in self.iter_slices_for_range(range) {
|
for (slice_glyphs, _, _) in self.iter_slices_for_range(range) {
|
||||||
if !slice_glyphs.is_whitespace() { return false; }
|
if !slice_glyphs.is_whitespace() { return false; }
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn metrics_for_range(&self, range: &Range) -> RunMetrics {
|
pub fn metrics_for_range(&self, range: &Range<int>) -> RunMetrics {
|
||||||
// TODO(Issue #199): alter advance direction for RTL
|
// TODO(Issue #199): alter advance direction for RTL
|
||||||
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
|
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
|
||||||
let mut advance = Au(0);
|
let mut advance = Au(0);
|
||||||
|
@ -194,14 +194,14 @@ impl<'a> TextRun {
|
||||||
RunMetrics::new(advance, self.font_metrics.ascent, self.font_metrics.descent)
|
RunMetrics::new(advance, self.font_metrics.ascent, self.font_metrics.descent)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn metrics_for_slice(&self, glyphs: &GlyphStore, slice_range: &Range) -> RunMetrics {
|
pub fn metrics_for_slice(&self, glyphs: &GlyphStore, slice_range: &Range<int>) -> RunMetrics {
|
||||||
let mut advance = Au(0);
|
let mut advance = Au(0);
|
||||||
for (_i, glyph) in glyphs.iter_glyphs_for_char_range(slice_range) {
|
for (_i, glyph) in glyphs.iter_glyphs_for_char_range(slice_range) {
|
||||||
advance = advance + glyph.advance();
|
advance = advance + glyph.advance();
|
||||||
}
|
}
|
||||||
RunMetrics::new(advance, self.font_metrics.ascent, self.font_metrics.descent)
|
RunMetrics::new(advance, self.font_metrics.ascent, self.font_metrics.descent)
|
||||||
}
|
}
|
||||||
pub fn min_width_for_range(&self, range: &Range) -> Au {
|
pub fn min_width_for_range(&self, range: &Range<int>) -> Au {
|
||||||
let mut max_piece_width = Au(0);
|
let mut max_piece_width = Au(0);
|
||||||
debug!("iterating outer range {:?}", range);
|
debug!("iterating outer range {:?}", range);
|
||||||
for (_, offset, slice_range) in self.iter_slices_for_range(range) {
|
for (_, offset, slice_range) in self.iter_slices_for_range(range) {
|
||||||
|
@ -212,7 +212,7 @@ impl<'a> TextRun {
|
||||||
max_piece_width
|
max_piece_width
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_slices_for_range(&'a self, range: &Range) -> SliceIterator<'a> {
|
pub fn iter_slices_for_range(&'a self, range: &Range<int>) -> SliceIterator<'a> {
|
||||||
SliceIterator {
|
SliceIterator {
|
||||||
glyph_iter: self.glyphs.iter(),
|
glyph_iter: self.glyphs.iter(),
|
||||||
range: *range,
|
range: *range,
|
||||||
|
@ -220,7 +220,7 @@ impl<'a> TextRun {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_natural_lines_for_range(&'a self, range: &Range) -> LineIterator<'a> {
|
pub fn iter_natural_lines_for_range(&'a self, range: &Range<int>) -> LineIterator<'a> {
|
||||||
LineIterator {
|
LineIterator {
|
||||||
range: *range,
|
range: *range,
|
||||||
clump: None,
|
clump: None,
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub enum CompressionMode {
|
||||||
// * Issue #114: record skipped and kept chars for mapping original to new text
|
// * Issue #114: record skipped and kept chars for mapping original to new text
|
||||||
//
|
//
|
||||||
// * Untracked: various edge cases for bidi, CJK, etc.
|
// * Untracked: various edge cases for bidi, CJK, etc.
|
||||||
pub fn transform_text(text: &str, mode: CompressionMode, incoming_whitespace: bool, new_line_pos: &mut Vec<uint>) -> (~str, bool) {
|
pub fn transform_text(text: &str, mode: CompressionMode, incoming_whitespace: bool, new_line_pos: &mut Vec<int>) -> (~str, bool) {
|
||||||
let mut out_str: ~str = "".to_owned();
|
let mut out_str: ~str = "".to_owned();
|
||||||
let out_whitespace = match mode {
|
let out_whitespace = match mode {
|
||||||
CompressNone | DiscardNewline => {
|
CompressNone | DiscardNewline => {
|
||||||
|
|
|
@ -95,7 +95,7 @@ pub struct Box {
|
||||||
/// New-line chracter(\n)'s positions(relative, not absolute)
|
/// New-line chracter(\n)'s positions(relative, not absolute)
|
||||||
///
|
///
|
||||||
/// FIXME(#2260, pcwalton): This is very inefficient; remove.
|
/// FIXME(#2260, pcwalton): This is very inefficient; remove.
|
||||||
pub new_line_pos: Vec<uint>,
|
pub new_line_pos: Vec<int>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Info specific to the kind of box. Keep this enum small.
|
/// Info specific to the kind of box. Keep this enum small.
|
||||||
|
@ -226,12 +226,12 @@ pub struct ScannedTextBoxInfo {
|
||||||
pub run: Arc<~TextRun>,
|
pub run: Arc<~TextRun>,
|
||||||
|
|
||||||
/// The range within the above text run that this represents.
|
/// The range within the above text run that this represents.
|
||||||
pub range: Range,
|
pub range: Range<int>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScannedTextBoxInfo {
|
impl ScannedTextBoxInfo {
|
||||||
/// Creates the information specific to a scanned text box from a range and a text run.
|
/// Creates the information specific to a scanned text box from a range and a text run.
|
||||||
pub fn new(run: Arc<~TextRun>, range: Range) -> ScannedTextBoxInfo {
|
pub fn new(run: Arc<~TextRun>, range: Range<int>) -> ScannedTextBoxInfo {
|
||||||
ScannedTextBoxInfo {
|
ScannedTextBoxInfo {
|
||||||
run: run,
|
run: run,
|
||||||
range: range,
|
range: range,
|
||||||
|
@ -1146,7 +1146,7 @@ impl Box {
|
||||||
let mut pieces_processed_count: uint = 0;
|
let mut pieces_processed_count: uint = 0;
|
||||||
let mut remaining_width: Au = max_width;
|
let mut remaining_width: Au = max_width;
|
||||||
let mut left_range = Range::new(text_box_info.range.begin(), 0);
|
let mut left_range = Range::new(text_box_info.range.begin(), 0);
|
||||||
let mut right_range: Option<Range> = None;
|
let mut right_range: Option<Range<int>> = None;
|
||||||
|
|
||||||
debug!("split_to_width: splitting text box (strlen={:u}, range={}, \
|
debug!("split_to_width: splitting text box (strlen={:u}, range={}, \
|
||||||
avail_width={})",
|
avail_width={})",
|
||||||
|
@ -1222,7 +1222,7 @@ impl Box {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let right_box = right_range.map_or(None, |range: Range| {
|
let right_box = right_range.map_or(None, |range: Range<int>| {
|
||||||
let new_text_box_info = ScannedTextBoxInfo::new(text_box_info.run.clone(),
|
let new_text_box_info = ScannedTextBoxInfo::new(text_box_info.run.clone(),
|
||||||
range);
|
range);
|
||||||
let mut new_metrics = new_text_box_info.run.metrics_for_range(&range);
|
let mut new_metrics = new_text_box_info.run.metrics_for_range(&range);
|
||||||
|
|
|
@ -203,7 +203,7 @@ impl InlineBoxAccumulator {
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
if has_enclosing_range {
|
if has_enclosing_range {
|
||||||
let len = boxes.len();
|
let len = boxes.len() as int;
|
||||||
boxes.map.get_mut(0).range.extend_to(len);
|
boxes.map.get_mut(0).range.extend_to(len);
|
||||||
}
|
}
|
||||||
boxes
|
boxes
|
||||||
|
|
|
@ -56,7 +56,7 @@ use sync::Arc;
|
||||||
/// left corner of the green zone is the same as that of the line, but
|
/// left corner of the green zone is the same as that of the line, but
|
||||||
/// the green zone can be taller and wider than the line itself.
|
/// the green zone can be taller and wider than the line itself.
|
||||||
pub struct LineBox {
|
pub struct LineBox {
|
||||||
pub range: Range,
|
pub range: Range<int>,
|
||||||
pub bounds: Rect<Au>,
|
pub bounds: Rect<Au>,
|
||||||
pub green_zone: Size2D<Au>
|
pub green_zone: Size2D<Au>
|
||||||
}
|
}
|
||||||
|
@ -446,7 +446,7 @@ impl LineboxScanner {
|
||||||
|
|
||||||
if self.pending_line.range.length() == 0 {
|
if self.pending_line.range.length() == 0 {
|
||||||
assert!(self.new_boxes.len() <= (u16::MAX as uint));
|
assert!(self.new_boxes.len() <= (u16::MAX as uint));
|
||||||
self.pending_line.range.reset(self.new_boxes.len(), 0);
|
self.pending_line.range.reset(self.new_boxes.len() as int, 0);
|
||||||
}
|
}
|
||||||
self.pending_line.range.extend_by(1);
|
self.pending_line.range.extend_by(1);
|
||||||
self.pending_line.bounds.size.width = self.pending_line.bounds.size.width +
|
self.pending_line.bounds.size.width = self.pending_line.bounds.size.width +
|
||||||
|
@ -468,7 +468,7 @@ impl<'a> Iterator<(&'a Box, InlineFragmentContext<'a>)> for BoxIterator<'a> {
|
||||||
fn next(&mut self) -> Option<(&'a Box, InlineFragmentContext<'a>)> {
|
fn next(&mut self) -> Option<(&'a Box, InlineFragmentContext<'a>)> {
|
||||||
match self.iter.next() {
|
match self.iter.next() {
|
||||||
None => None,
|
None => None,
|
||||||
Some((i, fragment)) => Some((fragment, InlineFragmentContext::new(self.map, i))),
|
Some((i, fragment)) => Some((fragment, InlineFragmentContext::new(self.map, i as int))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -484,7 +484,7 @@ impl<'a> Iterator<(&'a mut Box, InlineFragmentContext<'a>)> for MutBoxIterator<'
|
||||||
fn next(&mut self) -> Option<(&'a mut Box, InlineFragmentContext<'a>)> {
|
fn next(&mut self) -> Option<(&'a mut Box, InlineFragmentContext<'a>)> {
|
||||||
match self.iter.next() {
|
match self.iter.next() {
|
||||||
None => None,
|
None => None,
|
||||||
Some((i, fragment)) => Some((fragment, InlineFragmentContext::new(self.map, i))),
|
Some((i, fragment)) => Some((fragment, InlineFragmentContext::new(self.map, i as int))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -518,7 +518,7 @@ impl InlineBoxes {
|
||||||
|
|
||||||
/// Pushes a new inline box.
|
/// Pushes a new inline box.
|
||||||
pub fn push(&mut self, fragment: Box, style: Arc<ComputedValues>) {
|
pub fn push(&mut self, fragment: Box, style: Arc<ComputedValues>) {
|
||||||
self.map.push(style, Range::new(self.boxes.len(), 1));
|
self.map.push(style, Range::new(self.boxes.len() as int, 1));
|
||||||
self.boxes.push(fragment)
|
self.boxes.push(fragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -714,7 +714,7 @@ impl InlineFlow {
|
||||||
};
|
};
|
||||||
|
|
||||||
for i in line.range.eachi() {
|
for i in line.range.eachi() {
|
||||||
let box_ = boxes.get_mut(i);
|
let box_ = boxes.get_mut(i as uint);
|
||||||
let size = box_.border_box.size;
|
let size = box_.border_box.size;
|
||||||
box_.border_box = Rect(Point2D(offset_x, box_.border_box.origin.y), size);
|
box_.border_box = Rect(Point2D(offset_x, box_.border_box.origin.y), size);
|
||||||
offset_x = offset_x + size.width;
|
offset_x = offset_x + size.width;
|
||||||
|
@ -845,7 +845,7 @@ impl Flow for InlineFlow {
|
||||||
(Au(0), Au(0));
|
(Au(0), Au(0));
|
||||||
|
|
||||||
for box_i in line.range.eachi() {
|
for box_i in line.range.eachi() {
|
||||||
let fragment = self.boxes.boxes.get_mut(box_i);
|
let fragment = self.boxes.boxes.get_mut(box_i as uint);
|
||||||
|
|
||||||
let InlineMetrics {
|
let InlineMetrics {
|
||||||
height_above_baseline: mut height_above_baseline,
|
height_above_baseline: mut height_above_baseline,
|
||||||
|
@ -921,7 +921,7 @@ impl Flow for InlineFlow {
|
||||||
// Compute the final positions in the block direction of each fragment. Recall that
|
// Compute the final positions in the block direction of each fragment. Recall that
|
||||||
// `fragment.border_box.origin.y` was set to the distance from the baseline above.
|
// `fragment.border_box.origin.y` was set to the distance from the baseline above.
|
||||||
for box_i in line.range.eachi() {
|
for box_i in line.range.eachi() {
|
||||||
let fragment = self.boxes.get_mut(box_i);
|
let fragment = self.boxes.get_mut(box_i as uint);
|
||||||
match fragment.vertical_align() {
|
match fragment.vertical_align() {
|
||||||
vertical_align::top => {
|
vertical_align::top => {
|
||||||
fragment.border_box.origin.y = fragment.border_box.origin.y +
|
fragment.border_box.origin.y = fragment.border_box.origin.y +
|
||||||
|
@ -977,12 +977,12 @@ pub struct FragmentRange {
|
||||||
/// The style of the DOM node that this range refers to.
|
/// The style of the DOM node that this range refers to.
|
||||||
pub style: Arc<ComputedValues>,
|
pub style: Arc<ComputedValues>,
|
||||||
/// The range, in indices into the fragment list.
|
/// The range, in indices into the fragment list.
|
||||||
pub range: Range,
|
pub range: Range<int>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FragmentRange {
|
impl FragmentRange {
|
||||||
/// Creates a new fragment range from the given values.
|
/// Creates a new fragment range from the given values.
|
||||||
fn new(style: Arc<ComputedValues>, range: Range) -> FragmentRange {
|
fn new(style: Arc<ComputedValues>, range: Range<int>) -> FragmentRange {
|
||||||
FragmentRange {
|
FragmentRange {
|
||||||
style: style,
|
style: style,
|
||||||
range: range,
|
range: range,
|
||||||
|
@ -1003,14 +1003,14 @@ impl FragmentRange {
|
||||||
|
|
||||||
struct FragmentFixupWorkItem {
|
struct FragmentFixupWorkItem {
|
||||||
style: Arc<ComputedValues>,
|
style: Arc<ComputedValues>,
|
||||||
new_start_index: uint,
|
new_start_index: int,
|
||||||
old_end_index: uint,
|
old_end_index: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The type of an iterator over fragment ranges in the fragment map.
|
/// The type of an iterator over fragment ranges in the fragment map.
|
||||||
pub struct RangeIterator<'a> {
|
pub struct RangeIterator<'a> {
|
||||||
iter: Items<'a,FragmentRange>,
|
iter: Items<'a,FragmentRange>,
|
||||||
index: uint,
|
index: int,
|
||||||
seen_first: bool,
|
seen_first: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1053,7 +1053,7 @@ impl FragmentMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds the given node to the fragment map.
|
/// Adds the given node to the fragment map.
|
||||||
pub fn push(&mut self, style: Arc<ComputedValues>, range: Range) {
|
pub fn push(&mut self, style: Arc<ComputedValues>, range: Range<int>) {
|
||||||
self.list.push(FragmentRange::new(style, range))
|
self.list.push(FragmentRange::new(style, range))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1076,13 +1076,13 @@ impl FragmentMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the range with the given index.
|
/// Returns the range with the given index.
|
||||||
pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut FragmentRange {
|
pub fn get_mut<'a>(&'a mut self, index: int) -> &'a mut FragmentRange {
|
||||||
&mut self.list.as_mut_slice()[index]
|
&mut self.list.as_mut_slice()[index as uint]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterates over all ranges that contain the box with the given index, outermost first.
|
/// Iterates over all ranges that contain the box with the given index, outermost first.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn ranges_for_index<'a>(&'a self, index: uint) -> RangeIterator<'a> {
|
fn ranges_for_index<'a>(&'a self, index: int) -> RangeIterator<'a> {
|
||||||
RangeIterator {
|
RangeIterator {
|
||||||
iter: self.list.as_slice().iter(),
|
iter: self.list.as_slice().iter(),
|
||||||
index: index,
|
index: index,
|
||||||
|
@ -1113,7 +1113,7 @@ impl FragmentMap {
|
||||||
let new_fragment_start = match new_fragments_iter.peek() {
|
let new_fragment_start = match new_fragments_iter.peek() {
|
||||||
Some(&(index, new_fragment)) if new_fragment.node == old_fragment.node => {
|
Some(&(index, new_fragment)) if new_fragment.node == old_fragment.node => {
|
||||||
// We found the start of the corresponding new fragment.
|
// We found the start of the corresponding new fragment.
|
||||||
index
|
index as int
|
||||||
}
|
}
|
||||||
Some(_) | None => {
|
Some(_) | None => {
|
||||||
// The old fragment got deleted entirely.
|
// The old fragment got deleted entirely.
|
||||||
|
@ -1136,7 +1136,7 @@ impl FragmentMap {
|
||||||
match old_list_iter.peek() {
|
match old_list_iter.peek() {
|
||||||
None => break,
|
None => break,
|
||||||
Some(fragment_range) => {
|
Some(fragment_range) => {
|
||||||
if fragment_range.range.begin() > old_fragment_index {
|
if fragment_range.range.begin() > old_fragment_index as int {
|
||||||
// We haven't gotten to the appropriate old fragment yet, so stop.
|
// We haven't gotten to the appropriate old fragment yet, so stop.
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -1163,7 +1163,7 @@ impl FragmentMap {
|
||||||
match worklist.as_slice().last() {
|
match worklist.as_slice().last() {
|
||||||
None => break,
|
None => break,
|
||||||
Some(last_work_item) => {
|
Some(last_work_item) => {
|
||||||
if last_work_item.old_end_index > old_fragment_index + 1 {
|
if last_work_item.old_end_index > old_fragment_index as int + 1 {
|
||||||
// Haven't gotten to it yet.
|
// Haven't gotten to it yet.
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -1176,7 +1176,7 @@ impl FragmentMap {
|
||||||
new_fragments.len()
|
new_fragments.len()
|
||||||
}
|
}
|
||||||
Some(&(index, _)) => index,
|
Some(&(index, _)) => index,
|
||||||
};
|
} as int;
|
||||||
|
|
||||||
let FragmentFixupWorkItem {
|
let FragmentFixupWorkItem {
|
||||||
style,
|
style,
|
||||||
|
@ -1194,11 +1194,11 @@ impl FragmentMap {
|
||||||
/// conveniently to various fragment functions.
|
/// conveniently to various fragment functions.
|
||||||
pub struct InlineFragmentContext<'a> {
|
pub struct InlineFragmentContext<'a> {
|
||||||
map: &'a FragmentMap,
|
map: &'a FragmentMap,
|
||||||
index: uint,
|
index: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> InlineFragmentContext<'a> {
|
impl<'a> InlineFragmentContext<'a> {
|
||||||
pub fn new<'a>(map: &'a FragmentMap, index: uint) -> InlineFragmentContext<'a> {
|
pub fn new<'a>(map: &'a FragmentMap, index: int) -> InlineFragmentContext<'a> {
|
||||||
InlineFragmentContext {
|
InlineFragmentContext {
|
||||||
map: map,
|
map: map,
|
||||||
index: index,
|
index: index,
|
||||||
|
|
|
@ -20,7 +20,7 @@ use style::computed_values::{font_family, line_height, white_space};
|
||||||
use sync::Arc;
|
use sync::Arc;
|
||||||
|
|
||||||
struct NewLinePositions {
|
struct NewLinePositions {
|
||||||
new_line_pos: Vec<uint>,
|
new_line_pos: Vec<int>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// A helper function.
|
// A helper function.
|
||||||
|
@ -31,7 +31,7 @@ fn can_coalesce_text_nodes(boxes: &[Box], left_i: uint, right_i: uint) -> bool {
|
||||||
|
|
||||||
/// A stack-allocated object for scanning an inline flow into `TextRun`-containing `TextBox`es.
|
/// A stack-allocated object for scanning an inline flow into `TextRun`-containing `TextBox`es.
|
||||||
pub struct TextRunScanner {
|
pub struct TextRunScanner {
|
||||||
pub clump: Range,
|
pub clump: Range<int>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextRunScanner {
|
impl TextRunScanner {
|
||||||
|
@ -104,7 +104,7 @@ impl TextRunScanner {
|
||||||
debug!("TextRunScanner: flushing boxes in range={}", self.clump);
|
debug!("TextRunScanner: flushing boxes in range={}", self.clump);
|
||||||
let is_singleton = self.clump.length() == 1;
|
let is_singleton = self.clump.length() == 1;
|
||||||
|
|
||||||
let is_text_clump = match in_boxes[self.clump.begin()].specific {
|
let is_text_clump = match in_boxes[self.clump.begin() as uint].specific {
|
||||||
UnscannedTextBox(_) => true,
|
UnscannedTextBox(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
@ -117,11 +117,11 @@ impl TextRunScanner {
|
||||||
(true, false) => {
|
(true, false) => {
|
||||||
// FIXME(pcwalton): Stop cloning boxes, as above.
|
// FIXME(pcwalton): Stop cloning boxes, as above.
|
||||||
debug!("TextRunScanner: pushing single non-text box in range: {}", self.clump);
|
debug!("TextRunScanner: pushing single non-text box in range: {}", self.clump);
|
||||||
let new_box = in_boxes[self.clump.begin()].clone();
|
let new_box = in_boxes[self.clump.begin() as uint].clone();
|
||||||
out_boxes.push(new_box)
|
out_boxes.push(new_box)
|
||||||
},
|
},
|
||||||
(true, true) => {
|
(true, true) => {
|
||||||
let old_box = &in_boxes[self.clump.begin()];
|
let old_box = &in_boxes[self.clump.begin() as uint];
|
||||||
let text = match old_box.specific {
|
let text = match old_box.specific {
|
||||||
UnscannedTextBox(ref text_box_info) => &text_box_info.text,
|
UnscannedTextBox(ref text_box_info) => &text_box_info.text,
|
||||||
_ => fail!("Expected an unscanned text box!"),
|
_ => fail!("Expected an unscanned text box!"),
|
||||||
|
@ -136,7 +136,7 @@ impl TextRunScanner {
|
||||||
white_space::pre => CompressNone,
|
white_space::pre => CompressNone,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut new_line_pos = vec!();
|
let mut new_line_pos = vec![];
|
||||||
|
|
||||||
let (transformed_text, whitespace) = transform_text(*text,
|
let (transformed_text, whitespace) = transform_text(*text,
|
||||||
compression,
|
compression,
|
||||||
|
@ -169,7 +169,7 @@ impl TextRunScanner {
|
||||||
// TODO(#177): Text run creation must account for the renderability of text by
|
// TODO(#177): Text run creation must account for the renderability of text by
|
||||||
// font group fonts. This is probably achieved by creating the font group above
|
// font group fonts. This is probably achieved by creating the font group above
|
||||||
// and then letting `FontGroup` decide which `Font` to stick into the text run.
|
// and then letting `FontGroup` decide which `Font` to stick into the text run.
|
||||||
let in_box = &in_boxes[self.clump.begin()];
|
let in_box = &in_boxes[self.clump.begin() as uint];
|
||||||
let font_style = in_box.font_style();
|
let font_style = in_box.font_style();
|
||||||
let fontgroup = font_context.get_resolved_font_for_style(&font_style);
|
let fontgroup = font_context.get_resolved_font_for_style(&font_style);
|
||||||
let decoration = in_box.text_decoration();
|
let decoration = in_box.text_decoration();
|
||||||
|
@ -180,21 +180,21 @@ impl TextRunScanner {
|
||||||
white_space::pre => CompressNone,
|
white_space::pre => CompressNone,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut new_line_positions: Vec<NewLinePositions> = vec!();
|
let mut new_line_positions: Vec<NewLinePositions> = vec![];
|
||||||
|
|
||||||
// First, transform/compress text of all the nodes.
|
// First, transform/compress text of all the nodes.
|
||||||
let mut last_whitespace_in_clump = new_whitespace;
|
let mut last_whitespace_in_clump = new_whitespace;
|
||||||
let transformed_strs: Vec<~str> = Vec::from_fn(self.clump.length(), |i| {
|
let transformed_strs: Vec<~str> = Vec::from_fn(self.clump.length() as uint, |i| {
|
||||||
// TODO(#113): We should be passing the compression context between calls to
|
// TODO(#113): We should be passing the compression context between calls to
|
||||||
// `transform_text`, so that boxes starting and/or ending with whitespace can
|
// `transform_text`, so that boxes starting and/or ending with whitespace can
|
||||||
// be compressed correctly with respect to the text run.
|
// be compressed correctly with respect to the text run.
|
||||||
let idx = i + self.clump.begin();
|
let idx = i as int + self.clump.begin();
|
||||||
let in_box = match in_boxes[idx].specific {
|
let in_box = match in_boxes[idx as uint].specific {
|
||||||
UnscannedTextBox(ref text_box_info) => &text_box_info.text,
|
UnscannedTextBox(ref text_box_info) => &text_box_info.text,
|
||||||
_ => fail!("Expected an unscanned text box!"),
|
_ => fail!("Expected an unscanned text box!"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut new_line_pos = vec!();
|
let mut new_line_pos = vec![];
|
||||||
|
|
||||||
let (new_str, new_whitespace) = transform_text(*in_box,
|
let (new_str, new_whitespace) = transform_text(*in_box,
|
||||||
compression,
|
compression,
|
||||||
|
@ -210,12 +210,12 @@ impl TextRunScanner {
|
||||||
// Next, concatenate all of the transformed strings together, saving the new
|
// Next, concatenate all of the transformed strings together, saving the new
|
||||||
// character indices.
|
// character indices.
|
||||||
let mut run_str: ~str = "".to_owned();
|
let mut run_str: ~str = "".to_owned();
|
||||||
let mut new_ranges: Vec<Range> = vec!();
|
let mut new_ranges: Vec<Range<int>> = vec![];
|
||||||
let mut char_total = 0;
|
let mut char_total = 0;
|
||||||
for i in range(0, transformed_strs.len()) {
|
for i in range(0, transformed_strs.len() as int) {
|
||||||
let added_chars = transformed_strs.get(i).char_len();
|
let added_chars = transformed_strs.get(i as uint).char_len() as int;
|
||||||
new_ranges.push(Range::new(char_total, added_chars));
|
new_ranges.push(Range::new(char_total, added_chars));
|
||||||
run_str.push_str(*transformed_strs.get(i));
|
run_str.push_str(*transformed_strs.get(i as uint));
|
||||||
char_total += added_chars;
|
char_total += added_chars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,18 +234,18 @@ impl TextRunScanner {
|
||||||
debug!("TextRunScanner: pushing box(es) in range: {}", self.clump);
|
debug!("TextRunScanner: pushing box(es) in range: {}", self.clump);
|
||||||
for i in clump.eachi() {
|
for i in clump.eachi() {
|
||||||
let logical_offset = i - self.clump.begin();
|
let logical_offset = i - self.clump.begin();
|
||||||
let range = new_ranges.get(logical_offset);
|
let range = new_ranges.get(logical_offset as uint);
|
||||||
if range.length() == 0 {
|
if range.length() == 0 {
|
||||||
debug!("Elided an `UnscannedTextbox` because it was zero-length after \
|
debug!("Elided an `UnscannedTextbox` because it was zero-length after \
|
||||||
compression; {}", in_boxes[i]);
|
compression; {}", in_boxes[i as uint]);
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_text_box_info = ScannedTextBoxInfo::new(run.get_ref().clone(), *range);
|
let new_text_box_info = ScannedTextBoxInfo::new(run.get_ref().clone(), *range);
|
||||||
let new_metrics = new_text_box_info.run.metrics_for_range(range);
|
let new_metrics = new_text_box_info.run.metrics_for_range(range);
|
||||||
let mut new_box = in_boxes[i].transform(new_metrics.bounding_box.size,
|
let mut new_box = in_boxes[i as uint].transform(new_metrics.bounding_box.size,
|
||||||
ScannedTextBox(new_text_box_info));
|
ScannedTextBox(new_text_box_info));
|
||||||
new_box.new_line_pos = new_line_positions.get(logical_offset).new_line_pos.clone();
|
new_box.new_line_pos = new_line_positions.get(logical_offset as uint).new_line_pos.clone();
|
||||||
out_boxes.push(new_box)
|
out_boxes.push(new_box)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,13 @@
|
||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::num;
|
||||||
|
use std::num::Bounded;
|
||||||
|
|
||||||
pub enum RangeRelation {
|
#[deriving(Show)]
|
||||||
OverlapsBegin(/* overlap */ uint),
|
pub enum RangeRelation<T> {
|
||||||
OverlapsEnd(/* overlap */ uint),
|
OverlapsBegin(/* overlap */ T),
|
||||||
|
OverlapsEnd(/* overlap */ T),
|
||||||
ContainedBy,
|
ContainedBy,
|
||||||
Contains,
|
Contains,
|
||||||
Coincides,
|
Coincides,
|
||||||
|
@ -17,20 +20,20 @@ pub enum RangeRelation {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct Range {
|
pub struct Range<T> {
|
||||||
off: uint,
|
off: T,
|
||||||
len: uint
|
len: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Show for Range {
|
impl<T: Int + TotalOrd + Signed> fmt::Show for Range<T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f.buf, "[{} .. {})", self.begin(), self.end())
|
write!(f.buf, "[{} .. {})", self.begin(), self.end())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Range {
|
impl<T: Int + TotalOrd + Signed> Range<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(off: uint, len: uint) -> Range {
|
pub fn new(off: T, len: T) -> Range<T> {
|
||||||
Range {
|
Range {
|
||||||
off: off,
|
off: off,
|
||||||
len: len,
|
len: len,
|
||||||
|
@ -38,68 +41,76 @@ impl Range {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn empty() -> Range {
|
pub fn empty() -> Range<T> {
|
||||||
Range::new(0, 0)
|
Range::new(num::zero(), num::zero())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Range {
|
|
||||||
#[inline]
|
|
||||||
pub fn begin(&self) -> uint { self.off }
|
|
||||||
#[inline]
|
|
||||||
pub fn length(&self) -> uint { self.len }
|
|
||||||
#[inline]
|
|
||||||
pub fn end(&self) -> uint { self.off + self.len }
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn eachi(&self) -> iter::Range<uint> {
|
pub fn begin(&self) -> T { self.off }
|
||||||
|
#[inline]
|
||||||
|
pub fn length(&self) -> T { self.len }
|
||||||
|
#[inline]
|
||||||
|
pub fn end(&self) -> T { self.off + self.len }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn eachi(&self) -> iter::Range<T> {
|
||||||
range(self.off, self.off + self.len)
|
range(self.off, self.off + self.len)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn contains(&self, i: uint) -> bool {
|
pub fn contains(&self, i: T) -> bool {
|
||||||
i >= self.begin() && i < self.end()
|
i >= self.begin() && i < self.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_valid_for_string(&self, s: &str) -> bool {
|
pub fn is_valid_for_string(&self, s: &str) -> bool {
|
||||||
self.begin() < s.len() && self.end() <= s.len() && self.length() <= s.len()
|
let s_len = s.len();
|
||||||
|
match num::cast(s_len) {
|
||||||
|
Some(len) => {
|
||||||
|
self.begin() < len && self.end() <= len && self.length() <= len
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
debug!("Range<T>::is_valid_for_string: string length (len={}) is longer than the max \
|
||||||
|
value for T (max={})", s_len, { let val: T = Bounded::max_value(); val });
|
||||||
|
false
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.len == 0
|
self.len.is_zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn shift_by(&mut self, i: int) {
|
pub fn shift_by(&mut self, i: T) {
|
||||||
self.off = ((self.off as int) + i) as uint;
|
self.off = self.off + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn extend_by(&mut self, i: int) {
|
pub fn extend_by(&mut self, i: T) {
|
||||||
self.len = ((self.len as int) + i) as uint;
|
self.len = self.len + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn extend_to(&mut self, i: uint) {
|
pub fn extend_to(&mut self, i: T) {
|
||||||
self.len = i - self.off;
|
self.len = i - self.off;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn adjust_by(&mut self, off_i: int, len_i: int) {
|
pub fn adjust_by(&mut self, off_i: T, len_i: T) {
|
||||||
self.off = ((self.off as int) + off_i) as uint;
|
self.off = self.off + off_i;
|
||||||
self.len = ((self.len as int) + len_i) as uint;
|
self.len = self.len + len_i;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn reset(&mut self, off_i: uint, len_i: uint) {
|
pub fn reset(&mut self, off_i: T, len_i: T) {
|
||||||
self.off = off_i;
|
self.off = off_i;
|
||||||
self.len = len_i;
|
self.len = len_i;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn intersect(&self, other: &Range) -> Range {
|
pub fn intersect(&self, other: &Range<T>) -> Range<T> {
|
||||||
let begin = max(self.begin(), other.begin());
|
let begin = max(self.begin(), other.begin());
|
||||||
let end = min(self.end(), other.end());
|
let end = min(self.end(), other.end());
|
||||||
|
|
||||||
|
@ -114,7 +125,7 @@ impl Range {
|
||||||
/// from the point of view of `self`. So, 'EntirelyBefore' means
|
/// from the point of view of `self`. So, 'EntirelyBefore' means
|
||||||
/// that the `self` range is entirely before `other` range.
|
/// that the `self` range is entirely before `other` range.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn relation_to_range(&self, other: &Range) -> RangeRelation {
|
pub fn relation_to_range(&self, other: &Range<T>) -> RangeRelation<T> {
|
||||||
if other.begin() > self.end() {
|
if other.begin() > self.end() {
|
||||||
return EntirelyBefore;
|
return EntirelyBefore;
|
||||||
}
|
}
|
||||||
|
@ -138,27 +149,27 @@ impl Range {
|
||||||
let overlap = other.end() - self.begin();
|
let overlap = other.end() - self.begin();
|
||||||
return OverlapsEnd(overlap);
|
return OverlapsEnd(overlap);
|
||||||
}
|
}
|
||||||
fail!("relation_to_range(): didn't classify self={:?}, other={:?}",
|
fail!("relation_to_range(): didn't classify self={}, other={}",
|
||||||
self, other);
|
self, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn repair_after_coalesced_range(&mut self, other: &Range) {
|
pub fn repair_after_coalesced_range(&mut self, other: &Range<T>) {
|
||||||
let relation = self.relation_to_range(other);
|
let relation = self.relation_to_range(other);
|
||||||
debug!("repair_after_coalesced_range: possibly repairing range {:?}", self);
|
debug!("repair_after_coalesced_range: possibly repairing range {}", *self);
|
||||||
debug!("repair_after_coalesced_range: relation of original range and coalesced range({:?}): {:?}",
|
debug!("repair_after_coalesced_range: relation of original range and coalesced range {}: {}",
|
||||||
other, relation);
|
*other, relation);
|
||||||
match relation {
|
match relation {
|
||||||
EntirelyBefore => { },
|
EntirelyBefore => {},
|
||||||
EntirelyAfter => { self.shift_by(-(other.length() as int)); },
|
EntirelyAfter => { self.shift_by(-other.length()); },
|
||||||
Coincides | ContainedBy => { self.reset(other.begin(), 1); },
|
Coincides | ContainedBy => { self.reset(other.begin(), num::one()); },
|
||||||
Contains => { self.extend_by(-(other.length() as int)); },
|
Contains => { self.extend_by(-other.length()); },
|
||||||
OverlapsBegin(overlap) => { self.extend_by(1 - (overlap as int)); },
|
OverlapsBegin(overlap) => { self.extend_by(num::one::<T>() - overlap); },
|
||||||
OverlapsEnd(overlap) => {
|
OverlapsEnd(overlap) => {
|
||||||
let len = self.length() - overlap + 1;
|
let len = self.length() - overlap + num::one();
|
||||||
self.reset(other.begin(), len);
|
self.reset(other.begin(), len);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
debug!("repair_after_coalesced_range: new range: ---- {:?}", self);
|
debug!("repair_after_coalesced_range: new range: ---- {}", *self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue