Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: content/browser/renderer_host/render_widget_host_view_mac.mm

Issue 10656019: Use cached composition bounds for firstRectForCharacterRange (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Address comments Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "content/browser/renderer_host/render_widget_host_view_mac.h" 5 #include "content/browser/renderer_host/render_widget_host_view_mac.h"
6 6
7 #include <QuartzCore/QuartzCore.h> 7 #include <QuartzCore/QuartzCore.h>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
(...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 void RenderWidgetHostViewMac::ImeCancelComposition() { 640 void RenderWidgetHostViewMac::ImeCancelComposition() {
641 [cocoa_view_ cancelComposition]; 641 [cocoa_view_ cancelComposition];
642 } 642 }
643 643
644 void RenderWidgetHostViewMac::ImeCompositionRangeChanged( 644 void RenderWidgetHostViewMac::ImeCompositionRangeChanged(
645 const ui::Range& range, 645 const ui::Range& range,
646 const std::vector<gfx::Rect>& character_bounds) { 646 const std::vector<gfx::Rect>& character_bounds) {
647 // The RangeChanged message is only sent with valid values. The current 647 // The RangeChanged message is only sent with valid values. The current
648 // caret position (start == end) will be sent if there is no IME range. 648 // caret position (start == end) will be sent if there is no IME range.
649 [cocoa_view_ setMarkedRange:range.ToNSRange()]; 649 [cocoa_view_ setMarkedRange:range.ToNSRange()];
650 composition_range_ = range;
651 composition_bounds_ = character_bounds;
650 } 652 }
651 653
652 void RenderWidgetHostViewMac::DidUpdateBackingStore( 654 void RenderWidgetHostViewMac::DidUpdateBackingStore(
653 const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy, 655 const gfx::Rect& scroll_rect, int scroll_dx, int scroll_dy,
654 const std::vector<gfx::Rect>& copy_rects) { 656 const std::vector<gfx::Rect>& copy_rects) {
655 GotSoftwareFrame(); 657 GotSoftwareFrame();
656 658
657 if (!is_hidden_) { 659 if (!is_hidden_) {
658 std::vector<gfx::Rect> rects(copy_rects); 660 std::vector<gfx::Rect> rects(copy_rects);
659 661
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
1032 pending_swap_buffers_acks_.front().first, 1034 pending_swap_buffers_acks_.front().first,
1033 pending_swap_buffers_acks_.front().second, 1035 pending_swap_buffers_acks_.front().second,
1034 0); 1036 0);
1035 if (render_widget_host_) 1037 if (render_widget_host_)
1036 render_widget_host_->AcknowledgeSwapBuffersToRenderer(); 1038 render_widget_host_->AcknowledgeSwapBuffersToRenderer();
1037 } 1039 }
1038 pending_swap_buffers_acks_.erase(pending_swap_buffers_acks_.begin()); 1040 pending_swap_buffers_acks_.erase(pending_swap_buffers_acks_.begin());
1039 } 1041 }
1040 } 1042 }
1041 1043
1044 bool RenderWidgetHostViewMac::GetLineBreakIdx(
1045 const std::vector<gfx::Rect>& bounds,
1046 const ui::Range& range,
1047 size_t* line_break_point) {
1048 DCHECK(line_break_point);
1049 if (range.start() >= bounds.size() || range.is_reversed() || range.is_empty())
1050 return false;
1051
1052 // We can't check line breaking completely from only rectangle array. Thus we
1053 // assume the line breaking as the next character's y offset is larger than
1054 // a threshold. Currently the threshold is determined as minimum y offset plus
1055 // 75% of maximum height.
1056 // TODO(nona): Check the threshold is reliable or not.
1057 // TODO(nona): Bidi support.
1058 const size_t loop_end_idx = std::min(bounds.size(), range.end());
1059 int max_height = 0;
1060 int min_y_offset = kint32max;
1061 for (size_t idx = range.start(); idx < loop_end_idx; ++idx) {
1062 max_height = std::max(max_height, bounds[idx].height());
1063 min_y_offset = std::min(min_y_offset, bounds[idx].y());
1064 }
1065 int line_break_threshold = min_y_offset + (max_height * 3 / 4);
1066 for (size_t idx = range.start(); idx < loop_end_idx; ++idx) {
1067 if (bounds[idx].y() > line_break_threshold) {
1068 *line_break_point = idx;
1069 return true;
1070 }
1071 }
1072 return false;
1073 }
1074
1075 gfx::Rect RenderWidgetHostViewMac::GetFirstRectForCompositionRange(
1076 const ui::Range& range,
1077 ui::Range* actual_range) {
1078 DCHECK(actual_range);
1079 DCHECK(!composition_bounds_.empty());
1080 DCHECK(range.start() < composition_bounds_.size());
James Su 2012/07/06 01:28:47 range.start and range.end might be equal to compos
Seigo Nonaka 2012/07/06 02:04:42 Done.
1081 DCHECK(range.end() < composition_bounds_.size());
1082
1083 if (range.is_empty()) {
1084 *actual_range = range;
1085 if (range.start() == composition_bounds_.size()) {
1086 return gfx::Rect(composition_bounds_[range.start() - 1].right(),
1087 composition_bounds_[range.start() - 1].y(),
1088 0,
1089 composition_bounds_[range.start() - 1].height());
1090 } else {
1091 return gfx::Rect(composition_bounds_[range.start()].x(),
1092 composition_bounds_[range.start()].y(),
1093 0,
1094 composition_bounds_[range.start()].height());
1095 }
1096 }
1097
1098 size_t end_idx;
1099 if (!GetLineBreakIdx(composition_bounds_, range, &end_idx)) {
1100 end_idx = range.end();
1101 }
1102 *actual_range = ui::Range(range.start(), end_idx);
1103 gfx::Rect rect = composition_bounds_[range.start()];
1104 for (size_t i = range.start() + 1; i < end_idx; ++i) {
1105 rect = rect.Union(composition_bounds_[i]);
1106 }
1107 return rect;
1108 }
1109
1110 ui::Range RenderWidgetHostViewMac::ConvertCharacterRangeToCompositionRange(
1111 const ui::Range& request_range) {
1112 if (composition_range_.is_empty())
James Su 2012/07/06 01:28:47 I think we need to cover one more case: The IME mi
Seigo Nonaka 2012/07/06 02:04:42 Yes, it works with current logic because if this f
James Su 2012/07/06 02:17:23 I mean, for such case, we can cache the caret rect
Seigo Nonaka 2012/07/06 05:31:11 Done.
1113 return ui::Range::InvalidRange();
1114
1115 if (request_range.is_reversed())
1116 return ui::Range::InvalidRange();
1117
1118 if (request_range.start() < composition_range_.start() ||
1119 request_range.start() > composition_range_.end() ||
1120 request_range.end() > composition_range_.end()) {
1121 return ui::Range::InvalidRange();
1122 }
1123
1124 return ui::Range(
1125 request_range.start() - composition_range_.start(),
1126 request_range.end() - composition_range_.start());
1127 }
1128
1129 bool RenderWidgetHostViewMac::GetCachedFirstRectForCharacterRange(
1130 NSRange range,
1131 NSRect* rect,
1132 NSRange* actual_range) {
1133 TRACE_EVENT0("browser",
1134 "RenderWidgetHostViewMac::GetFirstRectForCharacterRange");
1135 const ui::Range request_range_in_composition =
1136 ConvertCharacterRangeToCompositionRange(ui::Range(range));
1137 if (request_range_in_composition == ui::Range::InvalidRange())
1138 return false;
1139 ui::Range ui_actual_range;
1140 *rect = NSRectFromCGRect(GetFirstRectForCompositionRange(
1141 request_range_in_composition,
1142 &ui_actual_range).ToCGRect());
1143 if (actual_range) {
1144 *actual_range = ui::Range(
1145 composition_range_.start() + ui_actual_range.start(),
1146 composition_range_.start() + ui_actual_range.end()).ToNSRange();
1147 }
1148 return true;
1149 }
1150
1042 void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped( 1151 void RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped(
1043 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, 1152 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params,
1044 int gpu_host_id) { 1153 int gpu_host_id) {
1045 TRACE_EVENT0("browser", 1154 TRACE_EVENT0("browser",
1046 "RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped"); 1155 "RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped");
1047 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1048 1157
1049 pending_swap_buffers_acks_.push_back(std::make_pair(params.route_id, 1158 pending_swap_buffers_acks_.push_back(std::make_pair(params.route_id,
1050 gpu_host_id)); 1159 gpu_host_id));
1051 1160
(...skipping 1622 matching lines...) Expand 10 before | Expand all | Expand 10 after
2674 2783
2675 NSUInteger index = 2784 NSUInteger index =
2676 TextInputClientMac::GetInstance()->GetCharacterIndexAtPoint( 2785 TextInputClientMac::GetInstance()->GetCharacterIndexAtPoint(
2677 renderWidgetHostView_->render_widget_host_, 2786 renderWidgetHostView_->render_widget_host_,
2678 gfx::Point(thePoint.x, thePoint.y)); 2787 gfx::Point(thePoint.x, thePoint.y));
2679 return index; 2788 return index;
2680 } 2789 }
2681 2790
2682 - (NSRect)firstRectForCharacterRange:(NSRange)theRange 2791 - (NSRect)firstRectForCharacterRange:(NSRange)theRange
2683 actualRange:(NSRangePointer)actualRange { 2792 actualRange:(NSRangePointer)actualRange {
2684 // TODO(thakis): Pipe |actualRange| through TextInputClientMac machinery. 2793 NSRect rect;
2685 if (actualRange) 2794 if (!renderWidgetHostView_->GetCachedFirstRectForCharacterRange(
2686 *actualRange = theRange; 2795 theRange,
2687 NSRect rect = TextInputClientMac::GetInstance()->GetFirstRectForRange( 2796 &rect,
2688 renderWidgetHostView_->render_widget_host_, theRange); 2797 actualRange)) {
2798 rect = TextInputClientMac::GetInstance()->GetFirstRectForRange(
2799 renderWidgetHostView_->render_widget_host_, theRange);
2800
2801 // TODO(thakis): Pipe |actualRange| through TextInputClientMac machinery.
2802 if (actualRange)
2803 *actualRange = theRange;
2804 }
2689 2805
2690 // The returned rectangle is in WebKit coordinates (upper left origin), so 2806 // The returned rectangle is in WebKit coordinates (upper left origin), so
2691 // flip the coordinate system and then convert it into screen coordinates for 2807 // flip the coordinate system and then convert it into screen coordinates for
2692 // return. 2808 // return.
2693 NSRect viewFrame = [self frame]; 2809 NSRect viewFrame = [self frame];
2694 rect.origin.y = NSHeight(viewFrame) - rect.origin.y; 2810 rect.origin.y = NSHeight(viewFrame) - rect.origin.y;
2695 rect.origin.y -= rect.size.height; 2811 rect.origin.y -= rect.size.height;
2696 rect = [self convertRectToBase:rect]; 2812 rect = [self convertRectToBase:rect];
2697 rect.origin = [[self window] convertBaseToScreen:rect.origin]; 2813 rect.origin = [[self window] convertBaseToScreen:rect.origin];
2698 return rect; 2814 return rect;
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
3091 if (!string) return NO; 3207 if (!string) return NO;
3092 3208
3093 // If the user is currently using an IME, confirm the IME input, 3209 // If the user is currently using an IME, confirm the IME input,
3094 // and then insert the text from the service, the same as TextEdit and Safari. 3210 // and then insert the text from the service, the same as TextEdit and Safari.
3095 [self confirmComposition]; 3211 [self confirmComposition];
3096 [self insertText:string]; 3212 [self insertText:string];
3097 return YES; 3213 return YES;
3098 } 3214 }
3099 3215
3100 @end 3216 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698