mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
gfx: Paint the insertion point as a one-pixel wide line.
This commit is contained in:
parent
357419dc8d
commit
efdf435ba3
1 changed files with 64 additions and 1 deletions
|
@ -34,6 +34,7 @@ use gfx::display_list::{GradientStop, ImageDisplayItem, LineDisplayItem};
|
|||
use gfx::display_list::{OpaqueNode, SolidColorDisplayItem};
|
||||
use gfx::display_list::{StackingContext, TextDisplayItem, TextOrientation};
|
||||
use gfx::paint_task::THREAD_TINT_COLORS;
|
||||
use gfx::text::glyph::CharIndex;
|
||||
use gfx_traits::color;
|
||||
use ipc_channel::ipc::{self, IpcSharedMemory};
|
||||
use msg::compositor_msg::{ScrollPolicy, LayerId};
|
||||
|
@ -60,15 +61,19 @@ use style::values::computed::{LengthOrNone, LengthOrPercentage, LengthOrPercenta
|
|||
use style::values::specified::{AngleOrCorner, HorizontalDirection, VerticalDirection};
|
||||
use url::Url;
|
||||
use util::cursor::Cursor;
|
||||
use util::geometry::{Au, ZERO_POINT};
|
||||
use util::geometry::{AU_PER_PX, Au, ZERO_POINT};
|
||||
use util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode};
|
||||
use util::opts;
|
||||
use util::range::Range;
|
||||
|
||||
/// The fake fragment ID we use to indicate the inner display list for `overflow: scroll`.
|
||||
///
|
||||
/// FIXME(pcwalton): This is pretty ugly. Consider modifying `LayerId` somehow.
|
||||
const FAKE_FRAGMENT_ID_FOR_OVERFLOW_SCROLL: u32 = 1000000;
|
||||
|
||||
/// The logical width of an insertion point: at the moment, a one-pixel-wide line.
|
||||
const INSERTION_POINT_LOGICAL_WIDTH: Au = Au(1 * AU_PER_PX);
|
||||
|
||||
/// Whether a stacking context needs a layer or not.
|
||||
pub enum StackingContextLayerNecessity {
|
||||
Always(LayerId, ScrollPolicy),
|
||||
|
@ -229,6 +234,14 @@ pub trait FragmentDisplayListBuilding {
|
|||
stacking_relative_border_box: &Rect<Au>)
|
||||
-> ClippingRegion;
|
||||
|
||||
/// Builds the display items necessary to paint the selection and/or caret for this fragment,
|
||||
/// if any.
|
||||
fn build_display_items_for_selection_if_necessary(&self,
|
||||
display_list: &mut DisplayList,
|
||||
stacking_relative_border_box: &Rect<Au>,
|
||||
level: StackingLevel,
|
||||
clip: &ClippingRegion);
|
||||
|
||||
/// Creates the text display item for one text fragment. This can be called multiple times for
|
||||
/// one fragment if there are text shadows.
|
||||
///
|
||||
|
@ -882,6 +895,50 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
(*parent_clip).clone().intersect_rect(&Rect::new(clip_origin, clip_size))
|
||||
}
|
||||
|
||||
fn build_display_items_for_selection_if_necessary(&self,
|
||||
display_list: &mut DisplayList,
|
||||
stacking_relative_border_box: &Rect<Au>,
|
||||
level: StackingLevel,
|
||||
clip: &ClippingRegion) {
|
||||
let scanned_text_fragment_info = match self.specific {
|
||||
SpecificFragmentInfo::ScannedText(ref scanned_text_fragment_info) => {
|
||||
scanned_text_fragment_info
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
let insertion_point_index = match scanned_text_fragment_info.insertion_point {
|
||||
Some(insertion_point_index) => insertion_point_index,
|
||||
None => return,
|
||||
};
|
||||
let range = Range::new(CharIndex(0), insertion_point_index);
|
||||
let advance = scanned_text_fragment_info.run.advance_for_range(&range);
|
||||
|
||||
let insertion_point_bounds;
|
||||
let cursor;
|
||||
if !self.style.writing_mode.is_vertical() {
|
||||
insertion_point_bounds =
|
||||
Rect::new(Point2D::new(stacking_relative_border_box.origin.x + advance,
|
||||
stacking_relative_border_box.origin.y),
|
||||
Size2D::new(INSERTION_POINT_LOGICAL_WIDTH,
|
||||
stacking_relative_border_box.size.height));
|
||||
cursor = Cursor::TextCursor;
|
||||
} else {
|
||||
insertion_point_bounds =
|
||||
Rect::new(Point2D::new(stacking_relative_border_box.origin.x,
|
||||
stacking_relative_border_box.origin.y + advance),
|
||||
Size2D::new(stacking_relative_border_box.size.width,
|
||||
INSERTION_POINT_LOGICAL_WIDTH));
|
||||
cursor = Cursor::VerticalTextCursor;
|
||||
};
|
||||
|
||||
display_list.push(DisplayItem::SolidColorClass(box SolidColorDisplayItem {
|
||||
base: BaseDisplayItem::new(insertion_point_bounds,
|
||||
DisplayItemMetadata::new(self.node, &*self.style, cursor),
|
||||
clip.clone()),
|
||||
color: self.style().get_color().color.to_gfx_color(),
|
||||
}), level);
|
||||
}
|
||||
|
||||
fn build_display_list(&mut self,
|
||||
display_list: &mut DisplayList,
|
||||
layout_context: &LayoutContext,
|
||||
|
@ -991,6 +1048,12 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
&stacking_relative_border_box,
|
||||
&clip);
|
||||
}
|
||||
|
||||
// Paint the selection point if necessary.
|
||||
self.build_display_items_for_selection_if_necessary(display_list,
|
||||
&stacking_relative_border_box,
|
||||
level,
|
||||
&clip);
|
||||
}
|
||||
|
||||
// Create special per-fragment-type display items.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue