aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout')
-rw-r--r--components/layout/display_list_builder.rs4
-rw-r--r--components/layout/fragment.rs112
-rw-r--r--components/layout/text.rs81
-rw-r--r--components/layout/webrender_helpers.rs2
-rw-r--r--components/layout/wrapper.rs37
5 files changed, 88 insertions, 148 deletions
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs
index de76e2b20cc..495c22e7589 100644
--- a/components/layout/display_list_builder.rs
+++ b/components/layout/display_list_builder.rs
@@ -31,7 +31,7 @@ use gfx::display_list::{LineDisplayItem, OpaqueNode, SolidColorDisplayItem};
use gfx::display_list::{StackingContext, StackingContextId, StackingContextType};
use gfx::display_list::{TextDisplayItem, TextOrientation, WebRenderImageInfo};
use gfx::paint_thread::THREAD_TINT_COLORS;
-use gfx::text::glyph::CharIndex;
+use gfx::text::glyph::ByteIndex;
use gfx_traits::{color, ScrollPolicy};
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
use ipc_channel::ipc::{self};
@@ -965,7 +965,7 @@ impl FragmentDisplayListBuilding for Fragment {
Some(insertion_point_index) => insertion_point_index,
None => return,
};
- let range = Range::new(CharIndex(0), insertion_point_index);
+ let range = Range::new(ByteIndex(0), insertion_point_index);
let advance = scanned_text_fragment_info.run.advance_for_range(&range);
let insertion_point_bounds;
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index 5612a322b95..ce9e55496c7 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -15,7 +15,7 @@ use flow::{self, Flow};
use flow_ref::{self, FlowRef};
use gfx;
use gfx::display_list::{BLUR_INFLATION_FACTOR, FragmentType, OpaqueNode, StackingContextId};
-use gfx::text::glyph::CharIndex;
+use gfx::text::glyph::ByteIndex;
use gfx::text::text_run::{TextRun, TextRunSlice};
use gfx_traits::{LayerId, LayerType};
use incremental::{RECONSTRUCT_FLOW, RestyleDamage};
@@ -48,7 +48,6 @@ use text;
use text::TextRunScanner;
use url::Url;
use util;
-use util::str::slice_chars;
use wrapper::{PseudoElementType, ThreadSafeLayoutElement, ThreadSafeLayoutNode};
/// Fragments (`struct Fragment`) are the leaves of the layout tree. They cannot position
@@ -227,13 +226,8 @@ impl SpecificFragmentInfo {
impl fmt::Debug for SpecificFragmentInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
- SpecificFragmentInfo::ScannedText(ref info) => {
- write!(f, "{:?}", slice_chars(&*info.run.text, info.range.begin().get() as usize,
- info.range.end().get() as usize))
- }
- SpecificFragmentInfo::UnscannedText(ref info) => {
- write!(f, "{:?}", info.text)
- }
+ SpecificFragmentInfo::ScannedText(ref info) => write!(f, "{:?}", info.text()),
+ SpecificFragmentInfo::UnscannedText(ref info) => write!(f, "{:?}", info.text),
_ => Ok(())
}
}
@@ -657,16 +651,16 @@ pub struct ScannedTextFragmentInfo {
/// The intrinsic size of the text fragment.
pub content_size: LogicalSize<Au>,
- /// The position of the insertion point in characters, if any.
- pub insertion_point: Option<CharIndex>,
+ /// The byte offset of the insertion point, if any.
+ pub insertion_point: Option<ByteIndex>,
/// The range within the above text run that this represents.
- pub range: Range<CharIndex>,
+ pub range: Range<ByteIndex>,
/// The endpoint of the above range, including whitespace that was stripped out. This exists
/// so that we can restore the range to its original value (before line breaking occurred) when
/// performing incremental reflow.
- pub range_end_including_stripped_whitespace: CharIndex,
+ pub range_end_including_stripped_whitespace: ByteIndex,
pub flags: ScannedTextFlags,
}
@@ -685,9 +679,9 @@ bitflags! {
impl ScannedTextFragmentInfo {
/// Creates the information specific to a scanned text fragment from a range and a text run.
pub fn new(run: Arc<TextRun>,
- range: Range<CharIndex>,
+ range: Range<ByteIndex>,
content_size: LogicalSize<Au>,
- insertion_point: Option<CharIndex>,
+ insertion_point: Option<ByteIndex>,
flags: ScannedTextFlags)
-> ScannedTextFragmentInfo {
ScannedTextFragmentInfo {
@@ -700,6 +694,10 @@ impl ScannedTextFragmentInfo {
}
}
+ pub fn text(&self) -> &str {
+ &self.run.text[self.range.begin().to_usize() .. self.range.end().to_usize()]
+ }
+
pub fn requires_line_break_afterward_if_wrapping_on_newlines(&self) -> bool {
self.flags.contains(REQUIRES_LINE_BREAK_AFTERWARD_IF_WRAPPING_ON_NEWLINES)
}
@@ -715,12 +713,12 @@ impl ScannedTextFragmentInfo {
pub struct SplitInfo {
// TODO(bjz): this should only need to be a single character index, but both values are
// currently needed for splitting in the `inline::try_append_*` functions.
- pub range: Range<CharIndex>,
+ pub range: Range<ByteIndex>,
pub inline_size: Au,
}
impl SplitInfo {
- fn new(range: Range<CharIndex>, info: &ScannedTextFragmentInfo) -> SplitInfo {
+ fn new(range: Range<ByteIndex>, info: &ScannedTextFragmentInfo) -> SplitInfo {
let inline_size = info.run.advance_for_range(&range);
SplitInfo {
range: range,
@@ -755,13 +753,13 @@ pub struct UnscannedTextFragmentInfo {
pub text: Box<str>,
/// The selected text range. An empty range represents the insertion point.
- pub selection: Option<Range<CharIndex>>,
+ pub selection: Option<Range<ByteIndex>>,
}
impl UnscannedTextFragmentInfo {
/// Creates a new instance of `UnscannedTextFragmentInfo` from the given text.
#[inline]
- pub fn new(text: String, selection: Option<Range<CharIndex>>) -> UnscannedTextFragmentInfo {
+ pub fn new(text: String, selection: Option<Range<ByteIndex>>) -> UnscannedTextFragmentInfo {
UnscannedTextFragmentInfo {
text: text.into_boxed_str(),
selection: selection,
@@ -1611,7 +1609,7 @@ impl Fragment {
};
let mut remaining_inline_size = max_inline_size;
- let mut inline_start_range = Range::new(text_fragment_info.range.begin(), CharIndex(0));
+ let mut inline_start_range = Range::new(text_fragment_info.range.begin(), ByteIndex(0));
let mut inline_end_range = None;
let mut overflowing = false;
@@ -1651,7 +1649,7 @@ impl Fragment {
// We're going to overflow the line.
overflowing = true;
inline_start_range = slice.text_run_range();
- remaining_range = Range::new(slice.text_run_range().end(), CharIndex(0));
+ remaining_range = Range::new(slice.text_run_range().end(), ByteIndex(0));
remaining_range.extend_to(text_fragment_info.range.end());
}
@@ -2322,32 +2320,20 @@ impl Fragment {
match self.specific {
SpecificFragmentInfo::ScannedText(ref mut scanned_text_fragment_info) => {
- let mut leading_whitespace_character_count = 0;
- {
- let text = slice_chars(
- &*scanned_text_fragment_info.run.text,
- scanned_text_fragment_info.range.begin().to_usize(),
- scanned_text_fragment_info.range.end().to_usize());
- for character in text.chars() {
- if util::str::char_is_whitespace(character) {
- leading_whitespace_character_count += 1
- } else {
- break
- }
- }
- }
+ let leading_whitespace_byte_count = scanned_text_fragment_info.text()
+ .find(|c| !util::str::char_is_whitespace(c))
+ .unwrap_or(scanned_text_fragment_info.text().len());
+ let whitespace_len = ByteIndex(leading_whitespace_byte_count as isize);
let whitespace_range = Range::new(scanned_text_fragment_info.range.begin(),
- CharIndex(leading_whitespace_character_count));
+ whitespace_len);
let text_bounds =
scanned_text_fragment_info.run.metrics_for_range(&whitespace_range).bounding_box;
self.border_box.size.inline = self.border_box.size.inline - text_bounds.size.width;
scanned_text_fragment_info.content_size.inline =
scanned_text_fragment_info.content_size.inline - text_bounds.size.width;
- scanned_text_fragment_info.range.adjust_by(
- CharIndex(leading_whitespace_character_count),
- -CharIndex(leading_whitespace_character_count));
+ scanned_text_fragment_info.range.adjust_by(whitespace_len, -whitespace_len);
WhitespaceStrippingResult::RetainFragment
}
@@ -2388,43 +2374,29 @@ impl Fragment {
match self.specific {
SpecificFragmentInfo::ScannedText(ref mut scanned_text_fragment_info) => {
- // FIXME(pcwalton): Is there a more clever (i.e. faster) way to do this?
- debug!("stripping trailing whitespace: range={:?}, len={}",
- scanned_text_fragment_info.range,
- scanned_text_fragment_info.run.text.chars().count());
- let mut trailing_whitespace_character_count = 0;
- let text_bounds;
- {
- let text = slice_chars(&*scanned_text_fragment_info.run.text,
- scanned_text_fragment_info.range.begin().to_usize(),
- scanned_text_fragment_info.range.end().to_usize());
- for ch in text.chars().rev() {
- if util::str::char_is_whitespace(ch) {
- trailing_whitespace_character_count += 1
- } else {
- break
- }
+ let mut trailing_whitespace_start_byte = 0;
+ for (i, c) in scanned_text_fragment_info.text().char_indices().rev() {
+ if !util::str::char_is_whitespace(c) {
+ trailing_whitespace_start_byte = i + c.len_utf8();
+ break;
}
-
- let whitespace_range =
- Range::new(scanned_text_fragment_info.range.end() -
- CharIndex(trailing_whitespace_character_count),
- CharIndex(trailing_whitespace_character_count));
- text_bounds = scanned_text_fragment_info.run
- .metrics_for_range(&whitespace_range)
- .bounding_box;
- self.border_box.size.inline = self.border_box.size.inline -
- text_bounds.size.width;
}
+ let whitespace_start = ByteIndex(trailing_whitespace_start_byte as isize);
+ let whitespace_len = scanned_text_fragment_info.range.length() - whitespace_start;
+ let whitespace_range = Range::new(whitespace_start, whitespace_len);
+
+ // FIXME: This may be unnecessary because these metrics will be recomputed in
+ // LineBreaker::strip_trailing_whitespace_from_pending_line_if_necessary
+ let text_bounds = scanned_text_fragment_info.run
+ .metrics_for_range(&whitespace_range)
+ .bounding_box;
+ self.border_box.size.inline = self.border_box.size.inline -
+ text_bounds.size.width;
scanned_text_fragment_info.content_size.inline =
scanned_text_fragment_info.content_size.inline - text_bounds.size.width;
- if trailing_whitespace_character_count != 0 {
- scanned_text_fragment_info.range.extend_by(
- CharIndex(-trailing_whitespace_character_count));
- }
-
+ scanned_text_fragment_info.range.extend_by(-whitespace_len);
WhitespaceStrippingResult::RetainFragment
}
SpecificFragmentInfo::UnscannedText(ref mut unscanned_text_fragment_info) => {
diff --git a/components/layout/text.rs b/components/layout/text.rs
index 22fbeb9ad1a..b7729608ce7 100644
--- a/components/layout/text.rs
+++ b/components/layout/text.rs
@@ -12,7 +12,7 @@ use fragment::{ScannedTextFragmentInfo, SELECTED, SpecificFragmentInfo, Unscanne
use gfx::font::{DISABLE_KERNING_SHAPING_FLAG, FontMetrics, IGNORE_LIGATURES_SHAPING_FLAG};
use gfx::font::{RTL_FLAG, RunMetrics, ShapingFlags, ShapingOptions};
use gfx::font_context::FontContext;
-use gfx::text::glyph::CharIndex;
+use gfx::text::glyph::ByteIndex;
use gfx::text::text_run::TextRun;
use gfx::text::util::{self, CompressionMode};
use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFragments, LAST_FRAGMENT_OF_ELEMENT};
@@ -174,7 +174,7 @@ impl TextRunScanner {
for (fragment_index, in_fragment) in self.clump.iter().enumerate() {
debug!(" flushing {:?}", in_fragment);
- let mut mapping = RunMapping::new(&run_info_list[..], &run_info, fragment_index);
+ let mut mapping = RunMapping::new(&run_info_list[..], fragment_index);
let text;
let selection;
match in_fragment.specific {
@@ -188,13 +188,13 @@ impl TextRunScanner {
Some(range) if range.is_empty() => {
// `range` is the range within the current fragment. To get the range
// within the text run, offset it by the length of the preceding fragments.
- Some(range.begin() + CharIndex(run_info.character_length as isize))
+ Some(range.begin() + ByteIndex(run_info.text.len() as isize))
}
_ => None
};
let (mut start_position, mut end_position) = (0, 0);
- for (char_index, character) in text.chars().enumerate() {
+ for (byte_index, character) in text.char_indices() {
// Search for the first font in this font group that contains a glyph for this
// character.
let mut font_index = 0;
@@ -226,7 +226,7 @@ impl TextRunScanner {
}
let selected = match selection {
- Some(range) => range.contains(CharIndex(char_index as isize)),
+ Some(range) => range.contains(ByteIndex(byte_index as isize)),
None => false
};
@@ -251,7 +251,6 @@ impl TextRunScanner {
run_info = RunInfo::new();
}
mapping = RunMapping::new(&run_info_list[..],
- &run_info,
fragment_index);
}
run_info.font_index = font_index;
@@ -343,11 +342,14 @@ impl TextRunScanner {
let mut mapping = mappings.next().unwrap();
let scanned_run = runs[mapping.text_run_index].clone();
+ let mut byte_range = Range::new(ByteIndex(mapping.byte_range.begin() as isize),
+ ByteIndex(mapping.byte_range.length() as isize));
+
let requires_line_break_afterward_if_wrapping_on_newlines =
!mapping.byte_range.is_empty() &&
scanned_run.run.text.char_at_reverse(mapping.byte_range.end()) == '\n';
if requires_line_break_afterward_if_wrapping_on_newlines {
- mapping.char_range.extend_by(CharIndex(-1));
+ byte_range.extend_by(ByteIndex(-1)); // Trim the '\n'
}
let text_size = old_fragment.border_box.size;
@@ -368,12 +370,12 @@ impl TextRunScanner {
let mut new_text_fragment_info = box ScannedTextFragmentInfo::new(
scanned_run.run,
- mapping.char_range,
+ byte_range,
text_size,
insertion_point,
flags);
- let new_metrics = new_text_fragment_info.run.metrics_for_range(&mapping.char_range);
+ let new_metrics = new_text_fragment_info.run.metrics_for_range(&byte_range);
let writing_mode = old_fragment.style.writing_mode;
let bounding_box_size = bounding_box_for_run_metrics(&new_metrics, writing_mode);
new_text_fragment_info.content_size = bounding_box_size;
@@ -490,7 +492,7 @@ fn split_first_fragment_at_newline_if_necessary(fragments: &mut LinkedList<Fragm
unscanned_text_fragment_info.text[..(position + 1)].to_owned();
unscanned_text_fragment_info.text =
unscanned_text_fragment_info.text[(position + 1)..].to_owned().into_boxed_str();
- let offset = CharIndex(string_before.char_indices().count() as isize);
+ let offset = ByteIndex(string_before.len() as isize);
match unscanned_text_fragment_info.selection {
Some(ref mut selection) if selection.begin() >= offset => {
// Selection is entirely in the second fragment.
@@ -500,7 +502,7 @@ fn split_first_fragment_at_newline_if_necessary(fragments: &mut LinkedList<Fragm
Some(ref mut selection) if selection.end() > offset => {
// Selection is split across two fragments.
selection_before = Some(Range::new(selection.begin(), offset));
- *selection = Range::new(CharIndex(0), selection.end() - offset);
+ *selection = Range::new(ByteIndex(0), selection.end() - offset);
}
_ => {
// Selection is entirely in the first fragment.
@@ -523,11 +525,9 @@ struct RunInfo {
/// The text that will go in this text run.
text: String,
/// The insertion point in this text run, if applicable.
- insertion_point: Option<CharIndex>,
+ insertion_point: Option<ByteIndex>,
/// The index of the applicable font in the font group.
font_index: usize,
- /// A cached copy of the number of Unicode characters in the text run.
- character_length: usize,
/// The bidirection embedding level of this text run.
bidi_level: u8,
/// The Unicode script property of this text run.
@@ -540,7 +540,6 @@ impl RunInfo {
text: String::new(),
insertion_point: None,
font_index: 0,
- character_length: 0,
bidi_level: 0,
script: Script::Common,
}
@@ -552,9 +551,9 @@ impl RunInfo {
/// of this text run.
fn flush(mut self,
list: &mut Vec<RunInfo>,
- insertion_point: &mut Option<CharIndex>) {
+ insertion_point: &mut Option<ByteIndex>) {
if let Some(idx) = *insertion_point {
- let char_len = CharIndex(self.character_length as isize);
+ let char_len = ByteIndex(self.text.len() as isize);
if idx <= char_len {
// The insertion point is in this text run.
self.insertion_point = insertion_point.take()
@@ -571,8 +570,6 @@ impl RunInfo {
/// for it.
#[derive(Copy, Clone, Debug)]
struct RunMapping {
- /// The range of characters within the text fragment.
- char_range: Range<CharIndex>,
/// The range of byte indices within the text fragment.
byte_range: Range<usize>,
/// The index of the unscanned text fragment that this mapping corresponds to.
@@ -585,13 +582,10 @@ struct RunMapping {
impl RunMapping {
/// Given the current set of text runs, creates a run mapping for the next fragment.
- /// `run_info_list` describes the set of runs we've seen already, and `current_run_info`
- /// describes the run we just finished processing.
- fn new(run_info_list: &[RunInfo], current_run_info: &RunInfo, fragment_index: usize)
+ /// `run_info_list` describes the set of runs we've seen already.
+ fn new(run_info_list: &[RunInfo], fragment_index: usize)
-> RunMapping {
RunMapping {
- char_range: Range::new(CharIndex(current_run_info.character_length as isize),
- CharIndex(0)),
byte_range: Range::new(0, 0),
old_fragment_index: fragment_index,
text_run_index: run_info_list.len(),
@@ -620,26 +614,21 @@ impl RunMapping {
// Account for `text-transform`. (Confusingly, this is not handled in "text
// transformation" above, but we follow Gecko in the naming.)
let is_first_run = *start_position == 0;
- let character_count = apply_style_transform_if_necessary(&mut run_info.text,
- old_byte_length,
- text_transform,
- *last_whitespace,
- is_first_run);
-
- run_info.character_length = run_info.character_length + character_count;
+ apply_style_transform_if_necessary(&mut run_info.text, old_byte_length, text_transform,
+ *last_whitespace, is_first_run);
*start_position = end_position;
+ let new_byte_length = run_info.text.len();
+ let is_empty = new_byte_length == old_byte_length;
+
// Don't save mappings that contain only discarded characters.
// (But keep ones that contained no characters to begin with, since they might have been
// generated by an empty flow to draw its borders/padding/insertion point.)
- let is_empty = character_count == 0;
if is_empty && !was_empty {
return;
}
- let new_byte_length = run_info.text.len();
self.byte_range = Range::new(old_byte_length, new_byte_length - old_byte_length);
- self.char_range.extend_by(CharIndex(character_count as isize));
mappings.push(self)
}
@@ -648,10 +637,10 @@ impl RunMapping {
/// NOTE: We treat the range as inclusive at both ends, since the insertion point can lie
/// before the first character *or* after the last character, and should be drawn even if the
/// text is empty.
- fn contains_insertion_point(&self, insertion_point: Option<CharIndex>) -> bool {
- match insertion_point {
+ fn contains_insertion_point(&self, insertion_point: Option<ByteIndex>) -> bool {
+ match insertion_point.map(ByteIndex::to_usize) {
None => false,
- Some(idx) => self.char_range.begin() <= idx && idx <= self.char_range.end()
+ Some(idx) => self.byte_range.begin() <= idx && idx <= self.byte_range.end()
}
}
}
@@ -666,39 +655,29 @@ fn apply_style_transform_if_necessary(string: &mut String,
first_character_position: usize,
text_transform: text_transform::T,
last_whitespace: bool,
- is_first_run: bool)
- -> usize {
+ is_first_run: bool) {
match text_transform {
- text_transform::T::none => string[first_character_position..].chars().count(),
+ text_transform::T::none => {}
text_transform::T::uppercase => {
let original = string[first_character_position..].to_owned();
string.truncate(first_character_position);
- let mut count = 0;
for ch in original.chars().flat_map(|ch| ch.to_uppercase()) {
string.push(ch);
- count += 1;
}
- count
}
text_transform::T::lowercase => {
let original = string[first_character_position..].to_owned();
string.truncate(first_character_position);
- let mut count = 0;
for ch in original.chars().flat_map(|ch| ch.to_lowercase()) {
string.push(ch);
- count += 1;
}
- count
}
text_transform::T::capitalize => {
let original = string[first_character_position..].to_owned();
string.truncate(first_character_position);
let mut capitalize_next_letter = is_first_run || last_whitespace;
- let mut count = 0;
for character in original.chars() {
- count += 1;
-
// FIXME(#4311, pcwalton): Should be the CSS/Unicode notion of a *typographic
// letter unit*, not an *alphabetic* character:
//
@@ -716,8 +695,6 @@ fn apply_style_transform_if_necessary(string: &mut String,
capitalize_next_letter = true
}
}
-
- count
}
}
}
@@ -725,7 +702,7 @@ fn apply_style_transform_if_necessary(string: &mut String,
#[derive(Clone)]
struct ScannedTextRun {
run: Arc<TextRun>,
- insertion_point: Option<CharIndex>,
+ insertion_point: Option<ByteIndex>,
}
/// Can a character with script `b` continue a text run with script `a`?
diff --git a/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs
index c3b28f8ecc1..053ecf87f50 100644
--- a/components/layout/webrender_helpers.rs
+++ b/components/layout/webrender_helpers.rs
@@ -392,7 +392,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
let mut glyphs = vec!();
for slice in item.text_run.natural_word_slices_in_visual_order(&item.range) {
- for glyph in slice.glyphs.iter_glyphs_for_char_range(&slice.range) {
+ for glyph in slice.glyphs.iter_glyphs_for_byte_range(&slice.range) {
let glyph_advance = glyph.advance();
let glyph_offset = glyph.offset().unwrap_or(Point2D::zero());
let glyph = webrender_traits::GlyphInstance {
diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs
index 00c77631707..86c370c0a83 100644
--- a/components/layout/wrapper.rs
+++ b/components/layout/wrapper.rs
@@ -33,7 +33,7 @@
use core::nonzero::NonZero;
use data::{LayoutDataFlags, PrivateLayoutData};
use gfx::display_list::OpaqueNode;
-use gfx::text::glyph::CharIndex;
+use gfx::text::glyph::ByteIndex;
use gfx_traits::{LayerId, LayerType};
use incremental::RestyleDamage;
use msg::constellation_msg::PipelineId;
@@ -74,7 +74,7 @@ use style::restyle_hints::ElementSnapshot;
use style::selector_impl::{NonTSPseudoClass, PseudoElement, ServoSelectorImpl};
use style::servo::PrivateStyleData;
use url::Url;
-use util::str::{is_whitespace, search_index};
+use util::str::is_whitespace;
pub type NonOpaqueStyleAndLayoutData = *mut RefCell<PrivateLayoutData>;
@@ -838,7 +838,7 @@ pub trait ThreadSafeLayoutNode : Clone + Copy + Sized + PartialEq {
fn text_content(&self) -> TextContent;
/// If the insertion point is within this node, returns it. Otherwise, returns `None`.
- fn selection(&self) -> Option<Range<CharIndex>>;
+ fn selection(&self) -> Option<Range<ByteIndex>>;
/// If this is an image element, returns its URL. If this is not an image element, fails.
///
@@ -1077,27 +1077,18 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {
panic!("not text!")
}
- fn selection(&self) -> Option<Range<CharIndex>> {
- let this = unsafe {
- self.get_jsmanaged()
- };
+ fn selection(&self) -> Option<Range<ByteIndex>> {
+ let this = unsafe { self.get_jsmanaged() };
- if let Some(area) = this.downcast::<HTMLTextAreaElement>() {
- if let Some(selection) = unsafe { area.get_absolute_selection_for_layout() } {
- let text = unsafe { area.get_value_for_layout() };
- let begin_byte = selection.begin();
- let begin = search_index(begin_byte, text.char_indices());
- let length = search_index(selection.length(), text[begin_byte..].char_indices());
- return Some(Range::new(CharIndex(begin), CharIndex(length)));
- }
- }
- if let Some(input) = this.downcast::<HTMLInputElement>() {
- if let Some(selection) = unsafe { input.selection_for_layout() } {
- return Some(Range::new(CharIndex(selection.begin()),
- CharIndex(selection.length())));
- }
- }
- None
+ let selection = if let Some(area) = this.downcast::<HTMLTextAreaElement>() {
+ unsafe { area.selection_for_layout() }
+ } else if let Some(input) = this.downcast::<HTMLInputElement>() {
+ unsafe { input.selection_for_layout() }
+ } else {
+ return None;
+ };
+ selection.map(|range| Range::new(ByteIndex(range.start as isize),
+ ByteIndex(range.len() as isize)))
}
fn image_url(&self) -> Option<Url> {