diff options
author | davemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-27 23:24:39 +0000 |
---|---|---|
committer | davemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-27 23:24:39 +0000 |
commit | 8129fa5c5831b56fe73e15ebd6cf42fd3a7c935c (patch) | |
tree | 228ee2811357227d23fb3c62502f5b05269bfa08 /app | |
parent | d87703cb9b1debdbe2704f7f50a2f33d38457b37 (diff) | |
download | chromium_src-8129fa5c5831b56fe73e15ebd6cf42fd3a7c935c.zip chromium_src-8129fa5c5831b56fe73e15ebd6cf42fd3a7c935c.tar.gz chromium_src-8129fa5c5831b56fe73e15ebd6cf42fd3a7c935c.tar.bz2 |
Got the about panel to have its text lined up correctly.
Also added underline capability to linux fonts.
Review URL: http://codereview.chromium.org/338029
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30276 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'app')
-rwxr-xr-x | app/gfx/canvas_linux.cc | 14 | ||||
-rw-r--r-- | app/gfx/font.h | 18 | ||||
-rwxr-xr-x | app/gfx/font_skia.cc | 88 |
3 files changed, 101 insertions, 19 deletions
diff --git a/app/gfx/canvas_linux.cc b/app/gfx/canvas_linux.cc index e658c6a..223c1a9 100755 --- a/app/gfx/canvas_linux.cc +++ b/app/gfx/canvas_linux.cc @@ -185,6 +185,9 @@ void Canvas::DrawStringInt(const std::wstring& text, int width, height; pango_layout_get_pixel_size(layout, &width, &height); + cairo_rectangle(cr, x, y, width, height); + cairo_clip(cr); + if (flags & Canvas::TEXT_VALIGN_TOP) { // Cairo should draw from the top left corner already. } else if (flags & Canvas::TEXT_VALIGN_BOTTOM) { @@ -194,11 +197,16 @@ void Canvas::DrawStringInt(const std::wstring& text, y += ((h - height) / 2); } - cairo_rectangle(cr, x, y, w, h); - cairo_clip(cr); - cairo_move_to(cr, x, y); pango_cairo_show_layout(cr, layout); + if (font.style() & gfx::Font::UNDERLINED) { + double underline_y = + static_cast<double>(y) + height + font.underline_position(); + cairo_set_line_width(cr, font.underline_thickness()); + cairo_move_to(cr, x, underline_y); + cairo_line_to(cr, x + width, underline_y); + cairo_stroke(cr); + } cairo_restore(cr); g_object_unref(layout); diff --git a/app/gfx/font.h b/app/gfx/font.h index bc8ee92..4bea194 100644 --- a/app/gfx/font.h +++ b/app/gfx/font.h @@ -136,6 +136,13 @@ class Font { // Converts |gfx_font| to a new pango font. Free the returned font with // pango_font_description_free(). static PangoFontDescription* PangoFontFromGfxFont(const gfx::Font& gfx_font); + + // Position as an offset from the height of the drawn text, used to draw + // an underline. This is a negative number, so the underline would be + // drawn at y + height + underline_position; + double underline_position() const; + // The thickness to draw the underline. + double underline_thickness() const; #endif private: @@ -207,7 +214,10 @@ class Font { static Font* default_font_; // The average width of a character, initialized and cached if needed. - double avg_width(); + double avg_width() const; + + // Potentially slow call to get pango metrics (avg width, underline info). + void InitPangoMetrics(); // These two both point to the same SkTypeface. We use the SkAutoUnref to // handle the reference counting, but without @typeface_ we would have to @@ -224,7 +234,13 @@ class Font { // Cached metrics, generated at construction int height_; int ascent_; + + // The pango metrics are much more expensive so we wait until we need them + // to compute them. + bool pango_metrics_inited_; double avg_width_; + double underline_position_; + double underline_thickness_; #elif defined(OS_MACOSX) explicit Font(const std::wstring& font_name, int font_size, int style); diff --git a/app/gfx/font_skia.cc b/app/gfx/font_skia.cc index 8f6ccc1..a283306 100755 --- a/app/gfx/font_skia.cc +++ b/app/gfx/font_skia.cc @@ -5,6 +5,7 @@ #include "app/gfx/font.h" #include <gdk/gdk.h> +#include <map> #include <pango/pango.h> #include "app/gfx/canvas.h" @@ -42,6 +43,35 @@ static double GetPangoScaleFactor() { return scale_factor; } +// Retrieves the pango metrics for a pango font description. Caches the metrics +// and never frees them. The metrics objects are relatively small and +// very expensive to look up. +static PangoFontMetrics* GetPangoFontMetrics(PangoFontDescription* desc) { + static std::map<int, PangoFontMetrics*>* desc_to_metrics = NULL; + static PangoContext* context = NULL; + + if (!context) { + context = gdk_pango_context_get_for_screen(gdk_screen_get_default()); + pango_context_set_language(context, pango_language_get_default()); + } + + if (!desc_to_metrics) { + desc_to_metrics = new std::map<int, PangoFontMetrics*>(); + } + + int desc_hash = pango_font_description_hash(desc); + std::map<int, PangoFontMetrics*>::iterator i = + desc_to_metrics->find(desc_hash); + + if (i == desc_to_metrics->end()) { + PangoFontMetrics* metrics = pango_context_get_metrics(context, desc, NULL); + (*desc_to_metrics)[desc_hash] = metrics; + return metrics; + } else { + return i->second; + } +} + } // namespace namespace gfx { @@ -61,7 +91,11 @@ Font::Font(SkTypeface* tf, const std::wstring& font_family, int font_size, typeface_(tf), font_family_(font_family), font_size_(font_size), - style_(style) { + style_(style), + pango_metrics_inited_(false), + avg_width_(0.0), + underline_position_(0.0), + underline_thickness_(0.0) { tf->ref(); calculateMetrics(); } @@ -74,8 +108,6 @@ void Font::calculateMetrics() { ascent_ = SkScalarCeil(-metrics.fAscent); height_ = ascent_ + SkScalarCeil(metrics.fDescent); - // avg_width_ is calculated lazily, as it's expensive and not used often. - avg_width_ = -1.0; } @@ -88,7 +120,10 @@ void Font::CopyFont(const Font& other) { style_ = other.style_; height_ = other.height_; ascent_ = other.ascent_; + pango_metrics_inited_ = other.pango_metrics_inited_; avg_width_ = other.avg_width_; + underline_position_ = other.underline_position_; + underline_thickness_ = other.underline_thickness_; } int Font::height() const { @@ -100,7 +135,7 @@ int Font::baseline() const { } int Font::ave_char_width() const { - return SkScalarRound(const_cast<Font*>(this)->avg_width()); + return SkScalarRound(avg_width()); } Font Font::CreateFont(const std::wstring& font_family, int font_size) { @@ -148,7 +183,7 @@ Font Font::DeriveFont(int size_delta, int style) const { static_cast<SkTypeface::Style>(skstyle)); SkAutoUnref tf_helper(tf); - return Font(tf, font_family_, font_size_ + size_delta, skstyle); + return Font(tf, font_family_, font_size_ + size_delta, style); } void Font::PaintSetup(SkPaint* paint) const { @@ -168,16 +203,26 @@ int Font::GetStringWidth(const std::wstring& text) const { return width; } -double Font::avg_width() { - if (avg_width_ < 0) { - // First get the pango based width +void Font::InitPangoMetrics() { + if (!pango_metrics_inited_) { + pango_metrics_inited_ = true; PangoFontDescription* pango_desc = PangoFontFromGfxFont(*this); - PangoContext* context = - gdk_pango_context_get_for_screen(gdk_screen_get_default()); - PangoFontMetrics* pango_metrics = - pango_context_get_metrics(context, - pango_desc, - pango_language_get_default()); + PangoFontMetrics* pango_metrics = GetPangoFontMetrics(pango_desc); + + underline_position_ = + pango_font_metrics_get_underline_position(pango_metrics); + underline_position_ /= PANGO_SCALE; + + // todo(davemoore) Come up with a better solution. + // This is a hack, but without doing this the underlines + // we get end up fuzzy. So we align to the midpoint of a pixel. + underline_position_ /= 2; + + underline_thickness_ = + pango_font_metrics_get_underline_thickness(pango_metrics); + underline_thickness_ /= PANGO_SCALE; + + // First get the pango based width double pango_width = pango_font_metrics_get_approximate_char_width(pango_metrics); pango_width /= PANGO_SCALE; @@ -188,12 +233,25 @@ double Font::avg_width() { L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); double dialog_units = (text_width / 26 + 1) / 2; avg_width_ = std::min(pango_width, dialog_units); - pango_font_metrics_unref(pango_metrics); pango_font_description_free(pango_desc); } +} + +double Font::avg_width() const { + const_cast<Font*>(this)->InitPangoMetrics(); return avg_width_; } +double Font::underline_position() const { + const_cast<Font*>(this)->InitPangoMetrics(); + return underline_position_; +} + +double Font::underline_thickness() const { + const_cast<Font*>(this)->InitPangoMetrics(); + return underline_thickness_; +} + int Font::GetExpectedTextWidth(int length) const { double char_width = const_cast<Font*>(this)->avg_width(); return round(static_cast<float>(length) * char_width); |