summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authordavemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-27 23:24:39 +0000
committerdavemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-27 23:24:39 +0000
commit8129fa5c5831b56fe73e15ebd6cf42fd3a7c935c (patch)
tree228ee2811357227d23fb3c62502f5b05269bfa08 /app
parentd87703cb9b1debdbe2704f7f50a2f33d38457b37 (diff)
downloadchromium_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-xapp/gfx/canvas_linux.cc14
-rw-r--r--app/gfx/font.h18
-rwxr-xr-xapp/gfx/font_skia.cc88
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);