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_pango.h" | 5 #include "ui/gfx/render_text_pango.h" |
6 | 6 |
7 #include <pango/pangocairo.h> | 7 #include <pango/pangocairo.h> |
8 #include <algorithm> | 8 #include <algorithm> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 ApplyTextShadows(&renderer); | 403 ApplyTextShadows(&renderer); |
404 renderer.SetFontRenderParams( | 404 renderer.SetFontRenderParams( |
405 font_list().GetPrimaryFont().GetFontRenderParams(), | 405 font_list().GetPrimaryFont().GetFontRenderParams(), |
406 background_is_transparent()); | 406 background_is_transparent()); |
407 | 407 |
408 // Temporarily apply composition underlines and selection colors. | 408 // Temporarily apply composition underlines and selection colors. |
409 ApplyCompositionAndSelectionStyles(); | 409 ApplyCompositionAndSelectionStyles(); |
410 | 410 |
411 internal::StyleIterator style(colors(), styles()); | 411 internal::StyleIterator style(colors(), styles()); |
412 for (GSList* it = current_line_->runs; it; it = it->next) { | 412 for (GSList* it = current_line_->runs; it; it = it->next) { |
| 413 // Skip painting runs outside the display area. |
| 414 if (SkScalarTruncToInt(x) >= display_rect().right()) |
| 415 break; |
| 416 |
413 PangoLayoutRun* run = reinterpret_cast<PangoLayoutRun*>(it->data); | 417 PangoLayoutRun* run = reinterpret_cast<PangoLayoutRun*>(it->data); |
414 int glyph_count = run->glyphs->num_glyphs; | 418 int glyph_count = run->glyphs->num_glyphs; |
415 // TODO(msw): Skip painting runs outside the display rect area, like Win. | |
416 if (glyph_count == 0) | 419 if (glyph_count == 0) |
417 continue; | 420 continue; |
418 | 421 |
419 ScopedPangoFontDescription desc( | 422 ScopedPangoFontDescription desc( |
420 pango_font_describe(run->item->analysis.font)); | 423 pango_font_describe(run->item->analysis.font)); |
421 const std::string family_name = | 424 const std::string family_name = |
422 pango_font_description_get_family(desc.get()); | 425 pango_font_description_get_family(desc.get()); |
423 renderer.SetTextSize(GetPangoFontSizeInPixels(desc.get())); | 426 renderer.SetTextSize(GetPangoFontSizeInPixels(desc.get())); |
424 | 427 |
425 glyphs.resize(glyph_count); | 428 glyphs.resize(glyph_count); |
(...skipping 13 matching lines...) Expand all Loading... |
439 do { | 442 do { |
440 const PangoGlyphInfo& glyph = run->glyphs->glyphs[glyph_index]; | 443 const PangoGlyphInfo& glyph = run->glyphs->glyphs[glyph_index]; |
441 glyphs[glyph_index] = static_cast<uint16>(glyph.glyph); | 444 glyphs[glyph_index] = static_cast<uint16>(glyph.glyph); |
442 // Use pango_units_to_double() rather than PANGO_PIXELS() here, so units | 445 // Use pango_units_to_double() rather than PANGO_PIXELS() here, so units |
443 // are not rounded to the pixel grid if subpixel positioning is enabled. | 446 // are not rounded to the pixel grid if subpixel positioning is enabled. |
444 pos[glyph_index].set(x + pango_units_to_double(glyph.geometry.x_offset), | 447 pos[glyph_index].set(x + pango_units_to_double(glyph.geometry.x_offset), |
445 y + pango_units_to_double(glyph.geometry.y_offset)); | 448 y + pango_units_to_double(glyph.geometry.y_offset)); |
446 x += pango_units_to_double(glyph.geometry.width); | 449 x += pango_units_to_double(glyph.geometry.width); |
447 | 450 |
448 ++glyph_index; | 451 ++glyph_index; |
| 452 // If this is the last glyph of the range or the last glyph inside the |
| 453 // display area (which would cause early termination of the loop), paint |
| 454 // the range. |
449 const size_t glyph_text_index = (glyph_index == glyph_count) ? | 455 const size_t glyph_text_index = (glyph_index == glyph_count) ? |
450 style_range.end() : GetGlyphTextIndex(run, glyph_index); | 456 style_range.end() : GetGlyphTextIndex(run, glyph_index); |
451 if (!IndexInRange(style_range, glyph_text_index)) { | 457 if (!IndexInRange(style_range, glyph_text_index) || |
| 458 SkScalarTruncToInt(x) >= display_rect().right()) { |
452 // TODO(asvitkine): For cases like "fi", where "fi" is a single glyph | 459 // TODO(asvitkine): For cases like "fi", where "fi" is a single glyph |
453 // but can span multiple styles, Pango splits the | 460 // but can span multiple styles, Pango splits the |
454 // styles evenly over the glyph. We can do this too by | 461 // styles evenly over the glyph. We can do this too by |
455 // clipping and drawing the glyph several times. | 462 // clipping and drawing the glyph several times. |
456 renderer.SetForegroundColor(style.color()); | 463 renderer.SetForegroundColor(style.color()); |
457 const int font_style = (style.style(BOLD) ? Font::BOLD : 0) | | 464 const int font_style = (style.style(BOLD) ? Font::BOLD : 0) | |
458 (style.style(ITALIC) ? Font::ITALIC : 0); | 465 (style.style(ITALIC) ? Font::ITALIC : 0); |
459 renderer.SetFontFamilyWithStyle(family_name, font_style); | 466 renderer.SetFontFamilyWithStyle(family_name, font_style); |
460 renderer.DrawPosText(&pos[style_start_glyph_index], | 467 renderer.DrawPosText(&pos[style_start_glyph_index], |
461 &glyphs[style_start_glyph_index], | 468 &glyphs[style_start_glyph_index], |
462 glyph_index - style_start_glyph_index); | 469 glyph_index - style_start_glyph_index); |
463 if (style.style(UNDERLINE)) | 470 if (style.style(UNDERLINE)) |
464 SetPangoUnderlineMetrics(desc.get(), &renderer); | 471 SetPangoUnderlineMetrics(desc.get(), &renderer); |
465 renderer.DrawDecorations(style_start_x, y, x - style_start_x, | 472 renderer.DrawDecorations(style_start_x, y, x - style_start_x, |
466 style.style(UNDERLINE), style.style(STRIKE), | 473 style.style(UNDERLINE), style.style(STRIKE), |
467 style.style(DIAGONAL_STRIKE)); | 474 style.style(DIAGONAL_STRIKE)); |
468 style.UpdatePosition(glyph_text_index); | 475 style.UpdatePosition(glyph_text_index); |
469 style_range = style.GetRange(); | 476 style_range = style.GetRange(); |
470 style_start_glyph_index = glyph_index; | 477 style_start_glyph_index = glyph_index; |
471 style_start_x = x; | 478 style_start_x = x; |
472 } | 479 } |
473 } while (glyph_index < glyph_count); | 480 // Terminates loop when the end of the range has been reached or the next |
| 481 // glyph falls outside the display area. |
| 482 } while (glyph_index < glyph_count && |
| 483 SkScalarTruncToInt(x) < display_rect().right()); |
474 } | 484 } |
475 | 485 |
476 renderer.EndDiagonalStrike(); | 486 renderer.EndDiagonalStrike(); |
477 | 487 |
478 // Undo the temporarily applied composition underlines and selection colors. | 488 // Undo the temporarily applied composition underlines and selection colors. |
479 UndoCompositionAndSelectionStyles(); | 489 UndoCompositionAndSelectionStyles(); |
480 } | 490 } |
481 | 491 |
482 GSList* RenderTextPango::GetRunContainingCaret( | 492 GSList* RenderTextPango::GetRunContainingCaret( |
483 const SelectionModel& caret) const { | 493 const SelectionModel& caret) const { |
(...skipping 28 matching lines...) Expand all Loading... |
512 int glyph_index) const { | 522 int glyph_index) const { |
513 return LayoutIndexToTextIndex(run->item->offset + | 523 return LayoutIndexToTextIndex(run->item->offset + |
514 run->glyphs->log_clusters[glyph_index]); | 524 run->glyphs->log_clusters[glyph_index]); |
515 } | 525 } |
516 | 526 |
517 RenderText* RenderText::CreateNativeInstance() { | 527 RenderText* RenderText::CreateNativeInstance() { |
518 return new RenderTextPango; | 528 return new RenderTextPango; |
519 } | 529 } |
520 | 530 |
521 } // namespace gfx | 531 } // namespace gfx |
OLD | NEW |