Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/gfx/render_text.h" | 5 #include "ui/gfx/render_text.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <climits> | 8 #include <climits> |
| 9 | 9 |
| 10 #include "base/i18n/break_iterator.h" | 10 #include "base/i18n/break_iterator.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 14 #include "third_party/icu/source/common/unicode/rbbi.h" | 14 #include "third_party/icu/source/common/unicode/rbbi.h" |
| 15 #include "third_party/icu/source/common/unicode/utf16.h" | 15 #include "third_party/icu/source/common/unicode/utf16.h" |
| 16 #include "third_party/skia/include/core/SkTypeface.h" | 16 #include "third_party/skia/include/core/SkTypeface.h" |
| 17 #include "third_party/skia/include/effects/SkGradientShader.h" | 17 #include "third_party/skia/include/effects/SkGradientShader.h" |
| 18 #include "ui/gfx/canvas.h" | 18 #include "ui/gfx/canvas.h" |
| 19 #include "ui/gfx/insets.h" | 19 #include "ui/gfx/insets.h" |
| 20 #include "ui/gfx/render_text_harfbuzz.h" | |
| 21 #include "ui/gfx/scoped_canvas.h" | |
| 20 #include "ui/gfx/skia_util.h" | 22 #include "ui/gfx/skia_util.h" |
| 21 #include "ui/gfx/text_constants.h" | 23 #include "ui/gfx/text_constants.h" |
| 22 #include "ui/gfx/text_elider.h" | 24 #include "ui/gfx/text_elider.h" |
| 23 #include "ui/gfx/text_utils.h" | 25 #include "ui/gfx/text_utils.h" |
| 24 #include "ui/gfx/utf16_indexing.h" | 26 #include "ui/gfx/utf16_indexing.h" |
| 25 | 27 |
| 26 namespace gfx { | 28 namespace gfx { |
| 27 | 29 |
| 28 namespace { | 30 namespace { |
| 29 | 31 |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 } | 213 } |
| 212 | 214 |
| 213 void SkiaTextRenderer::SetTextSize(SkScalar size) { | 215 void SkiaTextRenderer::SetTextSize(SkScalar size) { |
| 214 paint_.setTextSize(size); | 216 paint_.setTextSize(size); |
| 215 } | 217 } |
| 216 | 218 |
| 217 void SkiaTextRenderer::SetFontFamilyWithStyle(const std::string& family, | 219 void SkiaTextRenderer::SetFontFamilyWithStyle(const std::string& family, |
| 218 int style) { | 220 int style) { |
| 219 DCHECK(!family.empty()); | 221 DCHECK(!family.empty()); |
| 220 | 222 |
| 221 SkTypeface::Style skia_style = ConvertFontStyleToSkiaTypefaceStyle(style); | 223 skia::RefPtr<SkTypeface> typeface = CreateSkiaTypeface(family.c_str(), style); |
| 222 skia::RefPtr<SkTypeface> typeface = | |
| 223 skia::AdoptRef(SkTypeface::CreateFromName(family.c_str(), skia_style)); | |
| 224 if (typeface) { | 224 if (typeface) { |
| 225 // |paint_| adds its own ref. So don't |release()| it from the ref ptr here. | 225 // |paint_| adds its own ref. So don't |release()| it from the ref ptr here. |
| 226 SetTypeface(typeface.get()); | 226 SetTypeface(typeface.get()); |
| 227 | 227 |
| 228 // Enable fake bold text if bold style is needed but new typeface does not | 228 // Enable fake bold text if bold style is needed but new typeface does not |
| 229 // have it. | 229 // have it. |
| 230 paint_.setFakeBoldText((skia_style & SkTypeface::kBold) && | 230 paint_.setFakeBoldText((style & gfx::Font::BOLD) && !typeface->isBold()); |
| 231 !typeface->isBold()); | |
| 232 } | 231 } |
| 233 } | 232 } |
| 234 | 233 |
| 235 void SkiaTextRenderer::SetForegroundColor(SkColor foreground) { | 234 void SkiaTextRenderer::SetForegroundColor(SkColor foreground) { |
| 236 paint_.setColor(foreground); | 235 paint_.setColor(foreground); |
| 237 } | 236 } |
| 238 | 237 |
| 239 void SkiaTextRenderer::SetShader(SkShader* shader, const Rect& bounds) { | 238 void SkiaTextRenderer::SetShader(SkShader* shader, const Rect& bounds) { |
| 240 bounds_ = RectToSkRect(bounds); | 239 bounds_ = RectToSkRect(bounds); |
| 241 paint_.setShader(shader); | 240 paint_.setShader(shader); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 312 const SkScalar height = SkScalarMul(text_size, kLineThickness); | 311 const SkScalar height = SkScalarMul(text_size, kLineThickness); |
| 313 const SkScalar offset = SkScalarMulAdd(text_size, kStrikeThroughOffset, y); | 312 const SkScalar offset = SkScalarMulAdd(text_size, kStrikeThroughOffset, y); |
| 314 const SkRect r = SkRect::MakeLTRB(x, offset, x + width, offset + height); | 313 const SkRect r = SkRect::MakeLTRB(x, offset, x + width, offset + height); |
| 315 canvas_skia_->drawRect(r, paint_); | 314 canvas_skia_->drawRect(r, paint_); |
| 316 } | 315 } |
| 317 | 316 |
| 318 SkiaTextRenderer::DiagonalStrike::DiagonalStrike(Canvas* canvas, | 317 SkiaTextRenderer::DiagonalStrike::DiagonalStrike(Canvas* canvas, |
| 319 Point start, | 318 Point start, |
| 320 const SkPaint& paint) | 319 const SkPaint& paint) |
| 321 : canvas_(canvas), | 320 : canvas_(canvas), |
| 321 matrix_(canvas->sk_canvas()->getTotalMatrix()), | |
|
msw
2014/04/29 06:24:45
nit: can this just be calculated in DiagonalStrike
ckocagil
2014/05/01 22:02:01
No, because for each text run we do a matrix trans
msw
2014/05/02 05:08:21
This wasn't previously necessary, is it related to
ckocagil
2014/05/06 03:38:40
Actually these changes are intended. When we want
msw
2014/05/09 22:55:18
Ah, so we could apply canvas translations in Rende
ckocagil
2014/05/12 09:53:29
It doesn't simplify SkiaTextRenderer. Sure, I will
| |
| 322 start_(start), | 322 start_(start), |
| 323 paint_(paint), | 323 paint_(paint), |
| 324 total_length_(0) { | 324 total_length_(0) { |
| 325 } | 325 } |
| 326 | 326 |
| 327 SkiaTextRenderer::DiagonalStrike::~DiagonalStrike() { | 327 SkiaTextRenderer::DiagonalStrike::~DiagonalStrike() { |
| 328 } | 328 } |
| 329 | 329 |
| 330 void SkiaTextRenderer::DiagonalStrike::AddPiece(int length, SkColor color) { | 330 void SkiaTextRenderer::DiagonalStrike::AddPiece(int length, SkColor color) { |
| 331 pieces_.push_back(Piece(length, color)); | 331 pieces_.push_back(Piece(length, color)); |
| 332 total_length_ += length; | 332 total_length_ += length; |
| 333 } | 333 } |
| 334 | 334 |
| 335 void SkiaTextRenderer::DiagonalStrike::Draw() { | 335 void SkiaTextRenderer::DiagonalStrike::Draw() { |
| 336 const SkScalar text_size = paint_.getTextSize(); | 336 const SkScalar text_size = paint_.getTextSize(); |
| 337 const SkScalar offset = SkScalarMul(text_size, kDiagonalStrikeMarginOffset); | 337 const SkScalar offset = SkScalarMul(text_size, kDiagonalStrikeMarginOffset); |
| 338 const int thickness = | 338 const int thickness = |
| 339 SkScalarCeilToInt(SkScalarMul(text_size, kLineThickness) * 2); | 339 SkScalarCeilToInt(SkScalarMul(text_size, kLineThickness) * 2); |
| 340 const int height = SkScalarCeilToInt(text_size - offset); | 340 const int height = SkScalarCeilToInt(text_size - offset); |
| 341 const Point end = start_ + Vector2d(total_length_, -height); | 341 const Point end = start_ + Vector2d(total_length_, -height); |
| 342 const int clip_height = height + 2 * thickness; | |
| 342 | 343 |
| 343 paint_.setAntiAlias(true); | 344 paint_.setAntiAlias(true); |
| 344 paint_.setStrokeWidth(thickness); | 345 paint_.setStrokeWidth(thickness); |
| 345 | 346 |
| 347 ScopedCanvas scoped_canvas(canvas_); | |
|
msw
2014/04/29 06:24:45
Why this is needed over doing Canvas::Save/Restore
ckocagil
2014/05/01 22:02:01
This is just another way of doing Save/Restore, no
msw
2014/05/02 05:08:21
Reducing the amount of churn in this change is hig
ckocagil
2014/05/06 03:38:40
Done, this is now a Save/Restore pair.
msw
2014/05/09 22:55:18
It doesn't look like you updated the latest patch
| |
| 348 | |
| 349 SkCanvas* sk_canvas = canvas_->sk_canvas(); | |
| 350 sk_canvas->setMatrix(matrix_); | |
| 351 | |
| 346 const bool clipped = pieces_.size() > 1; | 352 const bool clipped = pieces_.size() > 1; |
| 347 int x = start_.x(); | 353 int x = start_.x(); |
| 348 for (size_t i = 0; i < pieces_.size(); ++i) { | 354 for (size_t i = 0; i < pieces_.size(); ++i) { |
| 349 paint_.setColor(pieces_[i].second); | 355 paint_.setColor(pieces_[i].second); |
| 350 | 356 |
| 351 if (clipped) { | 357 if (clipped) { |
| 352 canvas_->Save(); | 358 sk_canvas->clipRect(RectToSkRect( |
| 353 canvas_->ClipRect(Rect(x, 0, pieces_[i].first, start_.y() + thickness)); | 359 Rect(x, end.y() - thickness, pieces_[i].first, clip_height)), |
|
msw
2014/05/09 22:55:18
I think you'll need to still respect start_.y() fo
ckocagil
2014/05/12 09:53:29
We're already respecting that value by using end.y
| |
| 360 SkRegion::kReplace_Op); | |
| 354 } | 361 } |
| 355 | 362 |
| 356 canvas_->DrawLine(start_, end, paint_); | 363 canvas_->DrawLine(start_, end, paint_); |
| 357 | 364 |
| 358 if (clipped) | |
| 359 canvas_->Restore(); | |
| 360 | |
| 361 x += pieces_[i].first; | 365 x += pieces_[i].first; |
| 362 } | 366 } |
| 363 } | 367 } |
| 364 | 368 |
| 365 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, | 369 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, |
| 366 const std::vector<BreakList<bool> >& styles) | 370 const std::vector<BreakList<bool> >& styles) |
| 367 : colors_(colors), | 371 : colors_(colors), |
| 368 styles_(styles) { | 372 styles_(styles) { |
| 369 color_ = colors_.breaks().begin(); | 373 color_ = colors_.breaks().begin(); |
| 370 for (size_t i = 0; i < styles_.size(); ++i) | 374 for (size_t i = 0; i < styles_.size(); ++i) |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 387 } | 391 } |
| 388 | 392 |
| 389 LineSegment::LineSegment() : run(0) {} | 393 LineSegment::LineSegment() : run(0) {} |
| 390 | 394 |
| 391 LineSegment::~LineSegment() {} | 395 LineSegment::~LineSegment() {} |
| 392 | 396 |
| 393 Line::Line() : preceding_heights(0), baseline(0) {} | 397 Line::Line() : preceding_heights(0), baseline(0) {} |
| 394 | 398 |
| 395 Line::~Line() {} | 399 Line::~Line() {} |
| 396 | 400 |
| 401 skia::RefPtr<SkTypeface> CreateSkiaTypeface(const std::string& family, | |
| 402 int style) { | |
| 403 SkTypeface::Style skia_style = ConvertFontStyleToSkiaTypefaceStyle(style); | |
| 404 return skia::AdoptRef(SkTypeface::CreateFromName(family.c_str(), skia_style)); | |
| 405 } | |
| 406 | |
| 397 } // namespace internal | 407 } // namespace internal |
| 398 | 408 |
| 399 RenderText::~RenderText() { | 409 RenderText::~RenderText() { |
| 400 } | 410 } |
| 401 | 411 |
| 412 RenderText* RenderText::CreateInstance() { | |
| 413 if (CommandLine::ForCurrentProcess()->HasSwitch("use-harfbuzz-rendertext")) | |
|
msw
2014/04/29 06:24:45
Make "use-harfbuzz-rendertext" a proper ui/gfx/swi
ckocagil
2014/05/01 22:02:01
Done. I added the strings to chrome/app/generated_
msw
2014/05/02 05:08:21
Good, the file I suggested for strings was wrong,
| |
| 414 return new RenderTextHarfBuzz; | |
| 415 return CreateNativeInstance(); | |
| 416 } | |
| 417 | |
| 402 void RenderText::SetText(const base::string16& text) { | 418 void RenderText::SetText(const base::string16& text) { |
| 403 DCHECK(!composition_range_.IsValid()); | 419 DCHECK(!composition_range_.IsValid()); |
| 404 if (text_ == text) | 420 if (text_ == text) |
| 405 return; | 421 return; |
| 406 text_ = text; | 422 text_ = text; |
| 407 | 423 |
| 408 // Adjust ranged styles and colors to accommodate a new text length. | 424 // Adjust ranged styles and colors to accommodate a new text length. |
| 409 const size_t text_length = text_.length(); | 425 const size_t text_length = text_.length(); |
| 410 colors_.SetMax(text_length); | 426 colors_.SetMax(text_length); |
| 411 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 427 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) |
| (...skipping 889 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1301 cursor_bounds_ += delta_offset; | 1317 cursor_bounds_ += delta_offset; |
| 1302 } | 1318 } |
| 1303 | 1319 |
| 1304 void RenderText::DrawSelection(Canvas* canvas) { | 1320 void RenderText::DrawSelection(Canvas* canvas) { |
| 1305 const std::vector<Rect> sel = GetSubstringBounds(selection()); | 1321 const std::vector<Rect> sel = GetSubstringBounds(selection()); |
| 1306 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) | 1322 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) |
| 1307 canvas->FillRect(*i, selection_background_focused_color_); | 1323 canvas->FillRect(*i, selection_background_focused_color_); |
| 1308 } | 1324 } |
| 1309 | 1325 |
| 1310 } // namespace gfx | 1326 } // namespace gfx |
| OLD | NEW |