mirror of
https://github.com/servo/servo.git
synced 2025-06-24 09:04:33 +01:00
Move RenderContext::draw_text() to Font::draw_text_into_context(). Fixes #156.
This commit is contained in:
parent
416ffeaca6
commit
a06b573e74
3 changed files with 153 additions and 147 deletions
|
@ -2,6 +2,7 @@ use azure::azure_hl::DrawTarget;
|
||||||
use au = gfx::geometry;
|
use au = gfx::geometry;
|
||||||
use au::Au;
|
use au::Au;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
|
use geom::point::Point2D;
|
||||||
use image::base::Image;
|
use image::base::Image;
|
||||||
use render_context::RenderContext;
|
use render_context::RenderContext;
|
||||||
use servo_text::text_run;
|
use servo_text::text_run;
|
||||||
|
@ -49,7 +50,10 @@ impl DisplayItem {
|
||||||
SolidColor(_, r,g,b) => ctx.draw_solid_color(&self.d().bounds, r, g, b),
|
SolidColor(_, r,g,b) => ctx.draw_solid_color(&self.d().bounds, r, g, b),
|
||||||
Text(_, run, range) => {
|
Text(_, run, range) => {
|
||||||
let new_run = @run.deserialize(ctx.font_cache);
|
let new_run = @run.deserialize(ctx.font_cache);
|
||||||
ctx.draw_text(self.d().bounds, new_run, range)
|
let font = new_run.font;
|
||||||
|
let origin = self.d().bounds.origin;
|
||||||
|
let baseline_origin = Point2D(origin.x, origin.y + font.metrics.ascent);
|
||||||
|
font.draw_text_into_context(ctx, new_run, range, baseline_origin);
|
||||||
},
|
},
|
||||||
Image(_, ref img) => ctx.draw_image(self.d().bounds, clone_arc(img)),
|
Image(_, ref img) => ctx.draw_image(self.d().bounds, clone_arc(img)),
|
||||||
Border(_, width, r, g, b) => ctx.draw_border(&self.d().bounds, width, r, g, b),
|
Border(_, width, r, g, b) => ctx.draw_border(&self.d().bounds, width, r, g, b),
|
||||||
|
|
|
@ -15,10 +15,8 @@ use std::arc::ARC;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use azure::bindgen::AzDrawTargetFillGlyphs;
|
|
||||||
use azure::cairo::{cairo_font_face_t, cairo_scaled_font_t};
|
|
||||||
use azure::cairo_hl::ImageSurface;
|
use azure::cairo_hl::ImageSurface;
|
||||||
use azure::{AzDrawOptions, AzFloat, AzGlyph, AzGlyphBuffer};
|
use azure::{AzDrawOptions, AzFloat};
|
||||||
use azure::azure_hl::{AsAzureRect, B8G8R8A8, Color, ColorPattern, DrawOptions, DrawSurfaceOptions, StrokeOptions};
|
use azure::azure_hl::{AsAzureRect, B8G8R8A8, Color, ColorPattern, DrawOptions, DrawSurfaceOptions, StrokeOptions};
|
||||||
use azure::azure_hl::{DrawTarget, Linear};
|
use azure::azure_hl::{DrawTarget, Linear};
|
||||||
|
|
||||||
|
@ -28,6 +26,10 @@ struct RenderContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderContext {
|
impl RenderContext {
|
||||||
|
pub fn get_draw_target(&self) -> &self/DrawTarget {
|
||||||
|
&self.canvas.draw_target
|
||||||
|
}
|
||||||
|
|
||||||
pub fn draw_solid_color(&self, bounds: &Rect<Au>, r: u8, g: u8, b: u8) {
|
pub fn draw_solid_color(&self, bounds: &Rect<Au>, r: u8, g: u8, b: u8) {
|
||||||
let color = Color(r.to_float() as AzFloat,
|
let color = Color(r.to_float() as AzFloat,
|
||||||
g.to_float() as AzFloat,
|
g.to_float() as AzFloat,
|
||||||
|
@ -74,85 +76,6 @@ impl RenderContext {
|
||||||
draw_surface_options, draw_options);
|
draw_surface_options, draw_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: azure takes the origin as the left or right baseline. We
|
|
||||||
// should be passing in a bunch of glyphs and the baseline
|
|
||||||
// point. The baseline point should be computed somewhere else,
|
|
||||||
// like Font::draw_to_context() or TextRun::draw_to_context().
|
|
||||||
pub fn draw_text(&self, bounds: Rect<Au>, run: &TextRun, range: Range) {
|
|
||||||
use ptr::{null};
|
|
||||||
use vec::raw::to_ptr;
|
|
||||||
use libc::types::common::c99::{uint16_t, uint32_t};
|
|
||||||
use geom::point::Point2D;
|
|
||||||
use text::font_cache::FontCache;
|
|
||||||
use text::font::Font;
|
|
||||||
use azure::{AzNativeFont, AzFloat, AZ_NATIVE_FONT_CAIRO_FONT_FACE};
|
|
||||||
use azure::bindgen::{AzCreateScaledFontWithCairo,
|
|
||||||
AzReleaseScaledFont,
|
|
||||||
AzCreateColorPattern,
|
|
||||||
AzReleaseColorPattern};
|
|
||||||
use azure::cairo::bindgen::cairo_scaled_font_destroy;
|
|
||||||
|
|
||||||
let font = run.font;
|
|
||||||
// See the TODO above.
|
|
||||||
let y_adjust = font.metrics.descent;
|
|
||||||
let nfont: AzNativeFont = {
|
|
||||||
mType: AZ_NATIVE_FONT_CAIRO_FONT_FACE,
|
|
||||||
mFont: null()
|
|
||||||
};
|
|
||||||
|
|
||||||
let cfont = get_cairo_font(font);
|
|
||||||
let azfont = AzCreateScaledFontWithCairo(to_unsafe_ptr(&nfont), 1f as AzFloat, cfont);
|
|
||||||
assert azfont.is_not_null();
|
|
||||||
cairo_scaled_font_destroy(cfont);
|
|
||||||
|
|
||||||
let color = {
|
|
||||||
r: 0f as AzFloat,
|
|
||||||
g: 0f as AzFloat,
|
|
||||||
b: 0f as AzFloat,
|
|
||||||
a: 1f as AzFloat
|
|
||||||
};
|
|
||||||
let pattern = AzCreateColorPattern(to_unsafe_ptr(&color));
|
|
||||||
assert pattern.is_not_null();
|
|
||||||
|
|
||||||
let options: AzDrawOptions = {
|
|
||||||
mAlpha: 1f as AzFloat,
|
|
||||||
fields: 0 as uint16_t
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut origin = Point2D(bounds.origin.x, bounds.origin.y.add(&bounds.size.height) - y_adjust);
|
|
||||||
let azglyphs = DVec();
|
|
||||||
azglyphs.reserve(range.length());
|
|
||||||
|
|
||||||
do run.glyphs.iter_glyphs_for_range(range) |_i, glyph| {
|
|
||||||
let glyph_advance = glyph.advance();
|
|
||||||
let glyph_offset = glyph.offset().get_default(au::zero_point());
|
|
||||||
|
|
||||||
let azglyph: AzGlyph = {
|
|
||||||
mIndex: glyph.index() as uint32_t,
|
|
||||||
mPosition: {
|
|
||||||
x: au::to_px(origin.x + glyph_offset.x) as AzFloat,
|
|
||||||
y: au::to_px(origin.y + glyph_offset.y) as AzFloat
|
|
||||||
}
|
|
||||||
};
|
|
||||||
origin = Point2D(origin.x + glyph_advance, origin.y);
|
|
||||||
azglyphs.push(move azglyph)
|
|
||||||
};
|
|
||||||
|
|
||||||
let azglyph_buf_len = azglyphs.len();
|
|
||||||
let azglyph_buf = dvec::unwrap(move azglyphs);
|
|
||||||
let glyphbuf: AzGlyphBuffer = unsafe {{
|
|
||||||
mGlyphs: to_ptr(azglyph_buf),
|
|
||||||
mNumGlyphs: azglyph_buf_len as uint32_t
|
|
||||||
}};
|
|
||||||
|
|
||||||
// TODO: this call needs to move into azure_hl.rs
|
|
||||||
AzDrawTargetFillGlyphs(self.canvas.draw_target.azure_draw_target, azfont,
|
|
||||||
to_unsafe_ptr(&glyphbuf), pattern, to_unsafe_ptr(&options), null());
|
|
||||||
|
|
||||||
AzReleaseColorPattern(pattern);
|
|
||||||
AzReleaseScaledFont(azfont);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear(&self) {
|
fn clear(&self) {
|
||||||
let pattern = ColorPattern(Color(1f as AzFloat, 1f as AzFloat, 1f as AzFloat, 1f as AzFloat));
|
let pattern = ColorPattern(Color(1f as AzFloat, 1f as AzFloat, 1f as AzFloat, 1f as AzFloat));
|
||||||
let rect = Rect(Point2D(0 as AzFloat, 0 as AzFloat),
|
let rect = Rect(Point2D(0 as AzFloat, 0 as AzFloat),
|
||||||
|
@ -187,63 +110,3 @@ impl Rect<Au> : ToAzureRect {
|
||||||
Size2D(au::to_px(self.size.width) as AzFloat, au::to_px(self.size.height) as AzFloat))
|
Size2D(au::to_px(self.size.width) as AzFloat, au::to_px(self.size.height) as AzFloat))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
fn get_cairo_face(font: &Font) -> *cairo_font_face_t {
|
|
||||||
|
|
||||||
use libc::c_int;
|
|
||||||
use azure::cairo_ft::bindgen::{cairo_ft_font_face_create_for_ft_face};
|
|
||||||
|
|
||||||
let ftface = font.native_font.face;
|
|
||||||
let cface = cairo_ft_font_face_create_for_ft_face(ftface, 0 as c_int);
|
|
||||||
// FIXME: error handling
|
|
||||||
return cface;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
fn get_cairo_face(font: &Font) -> *cairo_font_face_t {
|
|
||||||
use azure::cairo_quartz::bindgen::cairo_quartz_font_face_create_for_cgfont;
|
|
||||||
|
|
||||||
let cgfont = font.native_font.cgfont;
|
|
||||||
let face = cairo_quartz_font_face_create_for_cgfont(cgfont);
|
|
||||||
// FIXME: error handling
|
|
||||||
return face;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_cairo_font(font: &Font) -> *cairo_scaled_font_t {
|
|
||||||
|
|
||||||
use libc::c_double;
|
|
||||||
use azure::cairo;
|
|
||||||
use cairo::cairo_matrix_t;
|
|
||||||
use cairo::bindgen::{cairo_matrix_init_identity,
|
|
||||||
cairo_matrix_scale,
|
|
||||||
cairo_font_options_create,
|
|
||||||
cairo_scaled_font_create,
|
|
||||||
cairo_font_options_destroy,
|
|
||||||
cairo_font_face_destroy};
|
|
||||||
|
|
||||||
// FIXME: error handling
|
|
||||||
|
|
||||||
let face = get_cairo_face(font);
|
|
||||||
|
|
||||||
let idmatrix: cairo_matrix_t = {
|
|
||||||
xx: 0 as c_double,
|
|
||||||
yx: 0 as c_double,
|
|
||||||
xy: 0 as c_double,
|
|
||||||
yy: 0 as c_double,
|
|
||||||
x0: 0 as c_double,
|
|
||||||
y0: 0 as c_double
|
|
||||||
};
|
|
||||||
cairo_matrix_init_identity(to_unsafe_ptr(&idmatrix));
|
|
||||||
|
|
||||||
let fontmatrix = idmatrix;
|
|
||||||
cairo_matrix_scale(to_unsafe_ptr(&fontmatrix), 21f as c_double, 21f as c_double);
|
|
||||||
let options = cairo_font_options_create();
|
|
||||||
let cfont = cairo_scaled_font_create(face, to_unsafe_ptr(&fontmatrix),
|
|
||||||
to_unsafe_ptr(&idmatrix), options);
|
|
||||||
cairo_font_options_destroy(options);
|
|
||||||
cairo_font_face_destroy(face);
|
|
||||||
|
|
||||||
return cfont;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -2,16 +2,15 @@ pub use font_cache::FontCache;
|
||||||
|
|
||||||
use au = gfx::geometry;
|
use au = gfx::geometry;
|
||||||
use au::Au;
|
use au::Au;
|
||||||
|
use core::dvec::DVec;
|
||||||
|
use gfx::render_context::RenderContext;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use glyph::GlyphIndex;
|
use glyph::GlyphIndex;
|
||||||
use libc::{ c_int, c_double, c_ulong };
|
|
||||||
use native_font::NativeFont;
|
use native_font::NativeFont;
|
||||||
use ptr::{null, addr_of};
|
|
||||||
use text::text_run::TextRun;
|
|
||||||
use vec_to_ptr = vec::raw::to_ptr;
|
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
|
use text::text_run::TextRun;
|
||||||
|
|
||||||
// Used to abstract over the shaper's choice of fixed int representation.
|
// Used to abstract over the shaper's choice of fixed int representation.
|
||||||
type FractionalPixel = float;
|
type FractionalPixel = float;
|
||||||
|
@ -42,6 +41,7 @@ struct RunMetrics {
|
||||||
|
|
||||||
// Public API
|
// Public API
|
||||||
pub trait FontMethods {
|
pub trait FontMethods {
|
||||||
|
fn draw_text_into_context(rctx: &RenderContext, run: &TextRun, range: Range, baseline_origin: Point2D<Au>);
|
||||||
fn measure_text(&TextRun, Range) -> RunMetrics;
|
fn measure_text(&TextRun, Range) -> RunMetrics;
|
||||||
|
|
||||||
fn buf(&self) -> @~[u8];
|
fn buf(&self) -> @~[u8];
|
||||||
|
@ -52,6 +52,145 @@ pub trait FontMethods {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl Font : FontMethods {
|
pub impl Font : FontMethods {
|
||||||
|
fn draw_text_into_context(rctx: &RenderContext, run: &TextRun, range: Range, baseline_origin: Point2D<Au>) {
|
||||||
|
use libc::types::common::c99::{uint16_t, uint32_t};
|
||||||
|
use azure::{AzDrawOptions,
|
||||||
|
AzFloat,
|
||||||
|
AzGlyph,
|
||||||
|
AzGlyphBuffer,
|
||||||
|
AzNativeFont,
|
||||||
|
AZ_NATIVE_FONT_CAIRO_FONT_FACE};
|
||||||
|
use azure::bindgen::{AzCreateColorPattern,
|
||||||
|
AzCreateScaledFontWithCairo,
|
||||||
|
AzDrawTargetFillGlyphs,
|
||||||
|
AzReleaseScaledFont,
|
||||||
|
AzReleaseColorPattern};
|
||||||
|
use azure::cairo::{cairo_font_face_t, cairo_scaled_font_t};
|
||||||
|
use azure::cairo::bindgen::cairo_scaled_font_destroy;
|
||||||
|
|
||||||
|
let target = rctx.get_draw_target();
|
||||||
|
// TODO(Issue #83): these should be cached on this Font, not created anew
|
||||||
|
let nfont: AzNativeFont = {
|
||||||
|
mType: AZ_NATIVE_FONT_CAIRO_FONT_FACE,
|
||||||
|
mFont: ptr::null()
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO(Issue #64): we should be able to remove cairo stepping
|
||||||
|
// stones and manual memory management, and put them inside of
|
||||||
|
// azure_hl.rs and elsewhere instead.
|
||||||
|
let cfont = get_cairo_font(&self);
|
||||||
|
let azfont = AzCreateScaledFontWithCairo(ptr::to_unsafe_ptr(&nfont), 1f as AzFloat, cfont);
|
||||||
|
assert azfont.is_not_null();
|
||||||
|
cairo_scaled_font_destroy(cfont);
|
||||||
|
|
||||||
|
let color = {
|
||||||
|
r: 0f as AzFloat,
|
||||||
|
g: 0f as AzFloat,
|
||||||
|
b: 0f as AzFloat,
|
||||||
|
a: 1f as AzFloat
|
||||||
|
};
|
||||||
|
let pattern = AzCreateColorPattern(ptr::to_unsafe_ptr(&color));
|
||||||
|
assert pattern.is_not_null();
|
||||||
|
|
||||||
|
let options: AzDrawOptions = {
|
||||||
|
mAlpha: 1f as AzFloat,
|
||||||
|
fields: 0 as uint16_t
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut origin = copy baseline_origin;
|
||||||
|
let azglyphs = DVec();
|
||||||
|
azglyphs.reserve(range.length());
|
||||||
|
|
||||||
|
do run.glyphs.iter_glyphs_for_range(range) |_i, glyph| {
|
||||||
|
let glyph_advance = glyph.advance();
|
||||||
|
let glyph_offset = glyph.offset().get_default(au::zero_point());
|
||||||
|
|
||||||
|
let azglyph: AzGlyph = {
|
||||||
|
mIndex: glyph.index() as uint32_t,
|
||||||
|
mPosition: {
|
||||||
|
x: au::to_px(origin.x + glyph_offset.x) as AzFloat,
|
||||||
|
y: au::to_px(origin.y + glyph_offset.y) as AzFloat
|
||||||
|
}
|
||||||
|
};
|
||||||
|
origin = Point2D(origin.x + glyph_advance, origin.y);
|
||||||
|
azglyphs.push(move azglyph)
|
||||||
|
};
|
||||||
|
|
||||||
|
let azglyph_buf_len = azglyphs.len();
|
||||||
|
let azglyph_buf = dvec::unwrap(move azglyphs);
|
||||||
|
let glyphbuf: AzGlyphBuffer = unsafe {{
|
||||||
|
mGlyphs: vec::raw::to_ptr(azglyph_buf),
|
||||||
|
mNumGlyphs: azglyph_buf_len as uint32_t
|
||||||
|
}};
|
||||||
|
|
||||||
|
// TODO: this call needs to move into azure_hl.rs
|
||||||
|
AzDrawTargetFillGlyphs(target.azure_draw_target, azfont,
|
||||||
|
ptr::to_unsafe_ptr(&glyphbuf), pattern, ptr::to_unsafe_ptr(&options), ptr::null());
|
||||||
|
|
||||||
|
AzReleaseColorPattern(pattern);
|
||||||
|
AzReleaseScaledFont(azfont);
|
||||||
|
|
||||||
|
// TODO: these should be private instance methods
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
fn get_cairo_face(font: &Font) -> *cairo_font_face_t {
|
||||||
|
|
||||||
|
use libc::c_int;
|
||||||
|
use azure::cairo_ft::bindgen::{cairo_ft_font_face_create_for_ft_face};
|
||||||
|
|
||||||
|
let ftface = font.native_font.face;
|
||||||
|
let cface = cairo_ft_font_face_create_for_ft_face(ftface, 0 as c_int);
|
||||||
|
// FIXME: error handling
|
||||||
|
return cface;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
fn get_cairo_face(font: &Font) -> *cairo_font_face_t {
|
||||||
|
use azure::cairo_quartz::bindgen::cairo_quartz_font_face_create_for_cgfont;
|
||||||
|
|
||||||
|
let cgfont = font.native_font.cgfont;
|
||||||
|
let face = cairo_quartz_font_face_create_for_cgfont(cgfont);
|
||||||
|
// FIXME: error handling
|
||||||
|
return face;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_cairo_font(font: &Font) -> *cairo_scaled_font_t {
|
||||||
|
|
||||||
|
use libc::c_double;
|
||||||
|
use azure::cairo;
|
||||||
|
use cairo::cairo_matrix_t;
|
||||||
|
use cairo::bindgen::{cairo_matrix_init_identity,
|
||||||
|
cairo_matrix_scale,
|
||||||
|
cairo_font_options_create,
|
||||||
|
cairo_scaled_font_create,
|
||||||
|
cairo_font_options_destroy,
|
||||||
|
cairo_font_face_destroy};
|
||||||
|
|
||||||
|
// FIXME: error handling
|
||||||
|
|
||||||
|
let face = get_cairo_face(font);
|
||||||
|
|
||||||
|
let idmatrix: cairo_matrix_t = {
|
||||||
|
xx: 0 as c_double,
|
||||||
|
yx: 0 as c_double,
|
||||||
|
xy: 0 as c_double,
|
||||||
|
yy: 0 as c_double,
|
||||||
|
x0: 0 as c_double,
|
||||||
|
y0: 0 as c_double
|
||||||
|
};
|
||||||
|
cairo_matrix_init_identity(ptr::to_unsafe_ptr(&idmatrix));
|
||||||
|
|
||||||
|
let fontmatrix = idmatrix;
|
||||||
|
cairo_matrix_scale(ptr::to_unsafe_ptr(&fontmatrix), 21f as c_double, 21f as c_double);
|
||||||
|
let options = cairo_font_options_create();
|
||||||
|
let cfont = cairo_scaled_font_create(face, ptr::to_unsafe_ptr(&fontmatrix),
|
||||||
|
ptr::to_unsafe_ptr(&idmatrix), options);
|
||||||
|
cairo_font_options_destroy(options);
|
||||||
|
cairo_font_face_destroy(face);
|
||||||
|
|
||||||
|
return cfont;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn measure_text(run: &TextRun, range: Range) -> RunMetrics {
|
fn measure_text(run: &TextRun, range: Range) -> RunMetrics {
|
||||||
assert range.is_valid_for_string(run.text);
|
assert range.is_valid_for_string(run.text);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue