mirror of
https://github.com/servo/servo.git
synced 2025-06-24 00:54:32 +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::Au;
|
||||
use geom::rect::Rect;
|
||||
use geom::point::Point2D;
|
||||
use image::base::Image;
|
||||
use render_context::RenderContext;
|
||||
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),
|
||||
Text(_, run, range) => {
|
||||
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)),
|
||||
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::point::Point2D;
|
||||
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::{AzDrawOptions, AzFloat, AzGlyph, AzGlyphBuffer};
|
||||
use azure::{AzDrawOptions, AzFloat};
|
||||
use azure::azure_hl::{AsAzureRect, B8G8R8A8, Color, ColorPattern, DrawOptions, DrawSurfaceOptions, StrokeOptions};
|
||||
use azure::azure_hl::{DrawTarget, Linear};
|
||||
|
||||
|
@ -28,6 +26,10 @@ struct 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) {
|
||||
let color = Color(r.to_float() as AzFloat,
|
||||
g.to_float() as AzFloat,
|
||||
|
@ -74,85 +76,6 @@ impl RenderContext {
|
|||
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) {
|
||||
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),
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
#[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::Au;
|
||||
use core::dvec::DVec;
|
||||
use gfx::render_context::RenderContext;
|
||||
use geom::point::Point2D;
|
||||
use geom::rect::Rect;
|
||||
use geom::size::Size2D;
|
||||
use glyph::GlyphIndex;
|
||||
use libc::{ c_int, c_double, c_ulong };
|
||||
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 text::text_run::TextRun;
|
||||
|
||||
// Used to abstract over the shaper's choice of fixed int representation.
|
||||
type FractionalPixel = float;
|
||||
|
@ -42,6 +41,7 @@ struct RunMetrics {
|
|||
|
||||
// Public API
|
||||
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 buf(&self) -> @~[u8];
|
||||
|
@ -52,6 +52,145 @@ pub trait 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 {
|
||||
assert range.is_valid_for_string(run.text);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue