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 |