summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorasvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-09 00:32:09 +0000
committerasvitkine@chromium.org <asvitkine@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-09 00:32:09 +0000
commit8dca6e58542b84d74677db149a980b91fffb5434 (patch)
tree7b8abbe8248a17e0b37f36dda0c84b146621d61a /ui
parent79f5a64fa99b2bf9833eb44b7ba447befa7ba317 (diff)
downloadchromium_src-8dca6e58542b84d74677db149a980b91fffb5434.zip
chromium_src-8dca6e58542b84d74677db149a980b91fffb5434.tar.gz
chromium_src-8dca6e58542b84d74677db149a980b91fffb5434.tar.bz2
Fix strike-through and add underline support to RenderTextWin.
Uses logic lifted from |SkCanvas::DrawTextDecorations()|. Also, fixes some 'gcl lint' warnings in render_text_win.cc. BUG=none TEST=none Review URL: http://codereview.chromium.org/8440038 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@109148 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/gfx/render_text_win.cc102
-rw-r--r--ui/gfx/render_text_win.h3
2 files changed, 69 insertions, 36 deletions
diff --git a/ui/gfx/render_text_win.cc b/ui/gfx/render_text_win.cc
index b3d3954..6b984ba 100644
--- a/ui/gfx/render_text_win.cc
+++ b/ui/gfx/render_text_win.cc
@@ -4,6 +4,9 @@
#include "ui/gfx/render_text_win.h"
+#include <algorithm>
+#include <map>
+
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/string_util.h"
@@ -22,6 +25,42 @@ const int kMaxItems = 10000;
// TODO(msw): Review memory use/failure? Max string length? Alternate approach?
const int kMaxGlyphs = 100000;
+// Draw underline and strike through text decorations.
+// Based on |SkCanvas::DrawTextDecorations()| and constants from:
+// third_party/skia/src/core/SkTextFormatParams.h
+void DrawTextRunDecorations(SkCanvas* canvas_skia,
+ const SkPaint& paint,
+ const gfx::internal::TextRun& run,
+ SkScalar x,
+ SkScalar y) {
+ // Fraction of the text size to lower a strike through below the baseline.
+ const SkScalar kStrikeThroughOffset = (-SK_Scalar1 * 6 / 21);
+ // Fraction of the text size to lower an underline below the baseline.
+ const SkScalar kUnderlineOffset = (SK_Scalar1 / 9);
+ // Fraction of the text size to use for a strike through or under-line.
+ const SkScalar kLineThickness = (SK_Scalar1 / 18);
+
+ SkScalar text_size = paint.getTextSize();
+ SkScalar height = SkScalarMul(text_size, kLineThickness);
+ SkRect r;
+
+ r.fLeft = x;
+ r.fRight = x + run.width;
+
+ if (run.underline) {
+ SkScalar offset = SkScalarMulAdd(text_size, kUnderlineOffset, y);
+ r.fTop = offset;
+ r.fBottom = offset + height;
+ canvas_skia->drawRect(r, paint);
+ }
+ if (run.strike) {
+ SkScalar offset = SkScalarMulAdd(text_size, kStrikeThroughOffset, y);
+ r.fTop = offset;
+ r.fBottom = offset + height;
+ canvas_skia->drawRect(r, paint);
+ }
+}
+
} // namespace
namespace gfx {
@@ -30,6 +69,7 @@ namespace internal {
TextRun::TextRun()
: strike(false),
+ underline(false),
width(0),
preceding_run_widths(0),
glyph_count(0) {
@@ -297,9 +337,9 @@ bool RenderTextWin::IsCursorablePosition(size_t position) {
size_t RenderTextWin::IndexOfAdjacentGrapheme(size_t index, bool next) {
size_t run_index = GetRunContainingPosition(index);
internal::TextRun* run = run_index < runs_.size() ? runs_[run_index] : NULL;
- long start = run ? run->range.start() : 0;
- long length = run ? run->range.length() : text().length();
- long ch = index - start;
+ int start = run ? run->range.start() : 0;
+ int length = run ? run->range.length() : text().length();
+ int ch = index - start;
WORD cluster = run ? run->logical_clusters[ch] : 0;
if (!next) {
@@ -310,7 +350,7 @@ size_t RenderTextWin::IndexOfAdjacentGrapheme(size_t index, bool next) {
while (ch < length && run && run->logical_clusters[ch] == cluster)
ch++;
}
- return std::max(static_cast<long>(std::min(ch, length) + start), 0L);
+ return std::max(std::min(ch, length) + start, 0);
}
void RenderTextWin::ItemizeAndLayoutText() {
@@ -359,10 +399,10 @@ void RenderTextWin::ItemizeLogicalText() {
for (int run_break = 0; run_break < text_length;) {
internal::TextRun* run = new internal::TextRun();
run->range.set_start(run_break);
- run->font = !style->underline ? style->font :
- style->font.DeriveFont(0, style->font.GetStyle() | Font::UNDERLINED);
+ run->font = style->font;
run->foreground = style->foreground;
run->strike = style->strike;
+ run->underline = style->underline;
run->script_analysis = script_item->a;
// Find the range end and advance the structures as needed.
@@ -516,7 +556,7 @@ SelectionModel RenderTextWin::LeftSelectionModel(
caret = IndexOfAdjacentGrapheme(caret, false);
return SelectionModel(caret, caret, SelectionModel::LEADING);
}
- } else { // The caret's associated character is in a RTL run.
+ } else { // The caret's associated character is in a RTL run.
if (caret_placement == SelectionModel::LEADING) {
size_t cursor = IndexOfAdjacentGrapheme(caret, true);
return SelectionModel(cursor, caret, SelectionModel::TRAILING);
@@ -554,7 +594,7 @@ SelectionModel RenderTextWin::RightSelectionModel(
size_t cursor = IndexOfAdjacentGrapheme(caret, true);
return SelectionModel(cursor, caret, SelectionModel::TRAILING);
}
- } else { // The caret's associated character is in a RTL run.
+ } else { // The caret's associated character is in a RTL run.
if (caret_placement == SelectionModel::TRAILING)
return SelectionModel(caret, caret, SelectionModel::LEADING);
else if (caret > run->range.start()) {
@@ -590,12 +630,12 @@ void RenderTextWin::DrawVisualText(Canvas* canvas) {
// TODO(msw): Establish a vertical baseline for strings of mixed font heights.
size_t height = default_style().font.GetHeight();
- float base_x = SkIntToScalar(offset.x());
- float base_y = SkIntToScalar(offset.y());
+ SkScalar x = SkIntToScalar(offset.x());
+ SkScalar y = SkIntToScalar(offset.y());
// Center the text vertically in the display area.
- base_y += (display_rect().height() - height) / 2;
+ y += (display_rect().height() - height) / 2;
// Offset by the font size to account for Skia expecting y to be the bottom.
- base_y += default_style().font.GetFontSize();
+ y += default_style().font.GetFontSize();
SkPaint paint;
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
@@ -604,15 +644,15 @@ void RenderTextWin::DrawVisualText(Canvas* canvas) {
paint.setSubpixelText(true);
paint.setLCDRenderText(true);
- scoped_array<SkPoint> pos;
+ std::vector<SkPoint> pos;
for (size_t i = 0; i < runs_.size(); ++i) {
// Get the run specified by the visual-to-logical map.
internal::TextRun* run = runs_[visual_to_logical_[i]];
// TODO(msw): Font default/fallback and style integration.
- std::string font(run->font.GetFontName());
SkTypeface::Style style = SkTypeface::kNormal;
- SkTypeface* typeface = SkTypeface::CreateFromName(font.c_str(), style);
+ SkTypeface* typeface =
+ SkTypeface::CreateFromName(run->font.GetFontName().c_str(), style);
if (typeface) {
paint.setTypeface(typeface);
// |paint| adds its own ref. Release the ref from CreateFromName.
@@ -621,31 +661,21 @@ void RenderTextWin::DrawVisualText(Canvas* canvas) {
paint.setTextSize(run->font.GetFontSize());
paint.setColor(run->foreground);
+ SkScalar run_x = x;
+
// Based on WebCore::skiaDrawText.
- pos.reset(new SkPoint[run->glyph_count]);
+ pos.resize(run->glyph_count);
for (int glyph = 0; glyph < run->glyph_count; glyph++) {
- pos[glyph].set(base_x + run->offsets[glyph].du,
- base_y + run->offsets[glyph].dv);
- base_x += SkIntToScalar(run->advance_widths[glyph]);
+ pos[glyph].set(x + run->offsets[glyph].du,
+ y + run->offsets[glyph].dv);
+ x += SkIntToScalar(run->advance_widths[glyph]);
}
+
size_t byte_length = run->glyph_count * sizeof(WORD);
- canvas_skia->drawPosText(run->glyphs.get(), byte_length, pos.get(), paint);
-
- // Draw the strikethrough.
- if (run->strike) {
- Rect bounds(offset, Size(run->width, run->font.GetHeight()));
- SkPaint strike;
- strike.setAntiAlias(true);
- strike.setStyle(SkPaint::kFill_Style);
- strike.setColor(run->foreground);
- strike.setStrokeWidth(kStrikeWidth);
- canvas_skia->drawLine(SkIntToScalar(bounds.x()),
- SkIntToScalar(bounds.bottom()),
- SkIntToScalar(bounds.right()),
- SkIntToScalar(bounds.y()),
- strike);
- }
- offset.Offset(run->width, 0);
+ canvas_skia->drawPosText(run->glyphs.get(), byte_length, &pos[0], paint);
+
+ if (run->strike || run->underline)
+ DrawTextRunDecorations(canvas_skia, paint, *run, run_x, y);
}
}
diff --git a/ui/gfx/render_text_win.h b/ui/gfx/render_text_win.h
index 2491b62..9ed6de2 100644
--- a/ui/gfx/render_text_win.h
+++ b/ui/gfx/render_text_win.h
@@ -8,6 +8,8 @@
#include <usp10.h>
+#include <vector>
+
#include "base/memory/scoped_ptr.h"
#include "ui/gfx/render_text.h"
@@ -25,6 +27,7 @@ struct TextRun {
// See the example at: http://www.catch22.net/tuts/neatpad/12.
SkColor foreground;
bool strike;
+ bool underline;
int width;
// The cumulative widths of preceding runs.