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

Side by Side Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/omnibox/AnswerTextBuilder.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 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
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.omnibox;
6
7 import android.graphics.Color;
8 import android.graphics.Paint;
9 import android.text.Html;
10 import android.text.Spannable;
11 import android.text.SpannableStringBuilder;
12 import android.text.TextPaint;
13 import android.text.style.AbsoluteSizeSpan;
14 import android.text.style.ForegroundColorSpan;
15 import android.text.style.MetricAffectingSpan;
16 import android.util.Log;
17
18 import java.util.List;
19
20 /**
21 * Helper class that builds Spannables to represent the styled text in answers f rom Answers in
22 * Suggest.
23 */
24 class AnswerTextBuilder {
25 private static final String TAG = "AnswerTextBuilder";
26
27 // Types, sizes and colors specified at http://goto.google.com/ais_api.
28 private static final int ANSWERS_ANSWER_TEXT_TYPE = 1;
29 private static final int ANSWERS_HEADLINE_TEXT_TYPE = 2;
30 private static final int ANSWERS_TOP_ALIGNED_TEXT_TYPE = 3;
31 private static final int ANSWERS_DESCRIPTION_TEXT_TYPE = 4;
32 private static final int ANSWERS_DESCRIPTION_TEXT_NEGATIVE_TYPE = 5;
33 private static final int ANSWERS_DESCRIPTION_TEXT_POSITIVE_TYPE = 6;
34 private static final int ANSWERS_MORE_INFO_TEXT_TYPE = 7;
35 private static final int ANSWERS_SUGGESTION_TEXT_TYPE = 8;
36 private static final int ANSWERS_SUGGESTION_TEXT_POSITIVE_TYPE = 9;
37 private static final int ANSWERS_SUGGESTION_TEXT_NEGATIVE_TYPE = 10;
38 private static final int ANSWERS_SUGGESTION_LINK_COLOR_TYPE = 11;
39 private static final int ANSWERS_STATUS_TEXT_TYPE = 12;
40 private static final int ANSWERS_PERSONALIZED_SUGGESTION_TEXT_TYPE = 13;
41
42 private static final int ANSWERS_ANSWER_TEXT_SIZE_SP = 28;
43 private static final int ANSWERS_HEADLINE_TEXT_SIZE_SP = 24;
44 private static final int ANSWERS_TOP_ALIGNED_TEXT_SIZE_SP = 13;
45 private static final int ANSWERS_DESCRIPTION_TEXT_SIZE_SP = 15;
46 private static final int ANSWERS_DESCRIPTION_TEXT_NEGATIVE_SIZE_SP = 16;
47 private static final int ANSWERS_DESCRIPTION_TEXT_POSITIVE_SIZE_SP = 16;
48 private static final int ANSWERS_MORE_INFO_TEXT_SIZE_SP = 12;
49 private static final int ANSWERS_SUGGESTION_TEXT_SIZE_SP = 15;
50 private static final int ANSWERS_SUGGESTION_TEXT_POSITIVE_SIZE_SP = 15;
51 private static final int ANSWERS_SUGGESTION_TEXT_NEGATIVE_SIZE_SP = 15;
52 private static final int ANSWERS_SUGGESTION_LINK_COLOR_SIZE_SP = 15;
53 private static final int ANSWERS_STATUS_TEXT_SIZE_SP = 13;
54 private static final int ANSWERS_PERSONALIZED_SUGGESTION_TEXT_SIZE_SP = 15;
55
56 private static final int ANSWERS_ANSWER_TEXT_COLOR = Color.BLACK;
57 private static final int ANSWERS_HEADLINE_TEXT_COLOR = Color.BLACK;
58 private static final int ANSWERS_TOP_ALIGNED_TEXT_COLOR = Color.GRAY;
59 private static final int ANSWERS_DESCRIPTION_TEXT_COLOR = Color.BLACK;
60 private static final int ANSWERS_DESCRIPTION_TEXT_NEGATIVE_COLOR = 0xFFC5392 9;
61 private static final int ANSWERS_DESCRIPTION_TEXT_POSITIVE_COLOR = 0xFF0B804 3;
62 private static final int ANSWERS_MORE_INFO_TEXT_COLOR = Color.BLACK;
63 private static final int ANSWERS_SUGGESTION_TEXT_COLOR = Color.BLACK;
64 private static final int ANSWERS_SUGGESTION_TEXT_POSITIVE_COLOR = Color.GREE N;
65 private static final int ANSWERS_SUGGESTION_TEXT_NEGATIVE_COLOR = Color.RED;
66 // TODO(jdonnelly): Links should be purple if visited.
67 private static final int ANSWERS_SUGGESTION_LINK_COLOR_COLOR = Color.BLUE;
68 private static final int ANSWERS_STATUS_TEXT_COLOR = Color.GRAY;
69 private static final int ANSWERS_PERSONALIZED_SUGGESTION_TEXT_COLOR = Color. BLACK;
70
71 /**
72 * Builds a Spannable containing all of the styled text in the supplied Imag eLine.
73 *
74 * @param line All text fields within this line will be added to the returne d Spannable.
75 * types.
76 * @param metrics Font metrics which will be used to properly size and layou t images and top-
77 * aligned text.
78 * @param density Screen density which will be used to properly size and lay out images and top-
79 * aligned text.
80 */
81 static Spannable buildSpannable(
82 SuggestionAnswer.ImageLine line, Paint.FontMetrics metrics, float de nsity) {
83 SpannableStringBuilder builder = new SpannableStringBuilder();
84
85 // Determine the height of the largest text element in the line. This
86 // will be used to top-align text and scale images.
87 int maxTextHeightSp = getMaxTextHeightSp(line);
88
89 List<SuggestionAnswer.TextField> textFields = line.getTextFields();
90 for (int i = 0; i < textFields.size(); i++) {
91 appendAndStyleText(builder, textFields.get(i), maxTextHeightSp, metr ics, density);
92 }
93 if (line.hasAdditionalText()) {
94 builder.append(" ");
95 SuggestionAnswer.TextField additionalText = line.getAdditionalText() ;
96 appendAndStyleText(builder, additionalText, maxTextHeightSp, metrics , density);
97 }
98 if (line.hasStatusText()) {
99 builder.append(" ");
100 SuggestionAnswer.TextField statusText = line.getStatusText();
101 appendAndStyleText(builder, statusText, maxTextHeightSp, metrics, de nsity);
102 }
103
104 return builder;
105 }
106
107 /**
108 * Determine the height of the largest text field in the entire line.
109 *
110 * @param line An ImageLine containing the text fields.
111 * @return The height in SP.
112 */
113 static int getMaxTextHeightSp(SuggestionAnswer.ImageLine line) {
114 int maxHeightSp = 0;
115
116 List<SuggestionAnswer.TextField> textFields = line.getTextFields();
117 for (int i = 0; i < textFields.size(); i++) {
118 int height = getAnswerTextSizeSp(textFields.get(i).getType());
119 if (height > maxHeightSp) {
120 maxHeightSp = height;
121 }
122 }
123 if (line.hasAdditionalText()) {
124 int height = getAnswerTextSizeSp(line.getAdditionalText().getType()) ;
125 if (height > maxHeightSp) {
126 maxHeightSp = height;
127 }
128 }
129 if (line.hasStatusText()) {
130 int height = getAnswerTextSizeSp(line.getStatusText().getType());
131 if (height > maxHeightSp) {
132 maxHeightSp = height;
133 }
134 }
135
136 return maxHeightSp;
137 }
138
139 /**
140 * Append the styled text in textField to the supplied builder.
141 *
142 * @param builder The builder to append the text to.
143 * @param textField The text field (with text and type) to append.
144 * @param maxTextHeightSp The height in SP of the largest text field in the entire line. Used to
145 * top-align text when specified.
146 * @param metrics Font metrics which will be used to properly size and layou t images and top-
147 * aligned text.
148 * @param density Screen density which will be used to properly size and lay out images and top-
149 * aligned text.
150 */
151 private static void appendAndStyleText(
152 SpannableStringBuilder builder, SuggestionAnswer.TextField textField ,
153 int maxTextHeightSp, Paint.FontMetrics metrics, float density) {
154 String text = textField.getText();
155 int type = textField.getType();
156
157 // Unescape HTML entities (e.g. "&quot;", "&gt;").
158 text = Html.fromHtml(text).toString();
159
160 // Append as HTML (answer responses contain simple markup).
161 int start = builder.length();
162 builder.append(Html.fromHtml(text));
163 int end = builder.length();
164
165 // Apply styles according to the type.
166 AbsoluteSizeSpan sizeSpan = new AbsoluteSizeSpan(getAnswerTextSizeSp(typ e), true);
167 builder.setSpan(sizeSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
168
169 ForegroundColorSpan colorSpan = new ForegroundColorSpan(getAnswerTextCol or(type));
170 builder.setSpan(colorSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIV E);
171
172 if (type == ANSWERS_TOP_ALIGNED_TEXT_TYPE) {
173 TopAlignedSpan topAlignedSpan =
174 new TopAlignedSpan(
175 ANSWERS_TOP_ALIGNED_TEXT_SIZE_SP, maxTextHeightSp, m etrics, density);
176 builder.setSpan(topAlignedSpan, start, end, Spannable.SPAN_EXCLUSIVE _EXCLUSIVE);
177 }
178 }
179
180 /**
181 * Return the SP text height for the specified answer text type.
182 *
183 * @param type The answer type as specified at http://goto.google.com/ais_ap i.
184 */
185 private static int getAnswerTextSizeSp(int type) {
186 switch (type) {
187 case ANSWERS_ANSWER_TEXT_TYPE:
188 return ANSWERS_ANSWER_TEXT_SIZE_SP;
189 case ANSWERS_HEADLINE_TEXT_TYPE:
190 return ANSWERS_HEADLINE_TEXT_SIZE_SP;
191 case ANSWERS_TOP_ALIGNED_TEXT_TYPE:
192 return ANSWERS_TOP_ALIGNED_TEXT_SIZE_SP;
193 case ANSWERS_DESCRIPTION_TEXT_TYPE:
194 return ANSWERS_DESCRIPTION_TEXT_SIZE_SP;
195 case ANSWERS_DESCRIPTION_TEXT_NEGATIVE_TYPE:
196 return ANSWERS_DESCRIPTION_TEXT_NEGATIVE_SIZE_SP;
197 case ANSWERS_DESCRIPTION_TEXT_POSITIVE_TYPE:
198 return ANSWERS_DESCRIPTION_TEXT_POSITIVE_SIZE_SP;
199 case ANSWERS_MORE_INFO_TEXT_TYPE:
200 return ANSWERS_MORE_INFO_TEXT_SIZE_SP;
201 case ANSWERS_SUGGESTION_TEXT_TYPE:
202 return ANSWERS_SUGGESTION_TEXT_SIZE_SP;
203 case ANSWERS_SUGGESTION_TEXT_POSITIVE_TYPE:
204 return ANSWERS_SUGGESTION_TEXT_POSITIVE_SIZE_SP;
205 case ANSWERS_SUGGESTION_TEXT_NEGATIVE_TYPE:
206 return ANSWERS_SUGGESTION_TEXT_NEGATIVE_SIZE_SP;
207 case ANSWERS_SUGGESTION_LINK_COLOR_TYPE:
208 return ANSWERS_SUGGESTION_LINK_COLOR_SIZE_SP;
209 case ANSWERS_STATUS_TEXT_TYPE:
210 return ANSWERS_STATUS_TEXT_SIZE_SP;
211 case ANSWERS_PERSONALIZED_SUGGESTION_TEXT_TYPE:
212 return ANSWERS_PERSONALIZED_SUGGESTION_TEXT_SIZE_SP;
213 default:
214 Log.w(TAG, "Unknown answer type: " + type);
215 return ANSWERS_SUGGESTION_TEXT_SIZE_SP;
216 }
217 }
218
219 /**
220 * Return the color code for the specified answer text type.
221 *
222 * @param type The answer type as specified at http://goto.google.com/ais_ap i.
223 */
224 private static int getAnswerTextColor(int type) {
225 switch (type) {
226 case ANSWERS_ANSWER_TEXT_TYPE:
227 return ANSWERS_ANSWER_TEXT_COLOR;
228 case ANSWERS_HEADLINE_TEXT_TYPE:
229 return ANSWERS_HEADLINE_TEXT_COLOR;
230 case ANSWERS_TOP_ALIGNED_TEXT_TYPE:
231 return ANSWERS_TOP_ALIGNED_TEXT_COLOR;
232 case ANSWERS_DESCRIPTION_TEXT_TYPE:
233 return ANSWERS_DESCRIPTION_TEXT_COLOR;
234 case ANSWERS_DESCRIPTION_TEXT_NEGATIVE_TYPE:
235 return ANSWERS_DESCRIPTION_TEXT_NEGATIVE_COLOR;
236 case ANSWERS_DESCRIPTION_TEXT_POSITIVE_TYPE:
237 return ANSWERS_DESCRIPTION_TEXT_POSITIVE_COLOR;
238 case ANSWERS_MORE_INFO_TEXT_TYPE:
239 return ANSWERS_MORE_INFO_TEXT_COLOR;
240 case ANSWERS_SUGGESTION_TEXT_TYPE:
241 return ANSWERS_SUGGESTION_TEXT_COLOR;
242 case ANSWERS_SUGGESTION_TEXT_POSITIVE_TYPE:
243 return ANSWERS_SUGGESTION_TEXT_POSITIVE_COLOR;
244 case ANSWERS_SUGGESTION_TEXT_NEGATIVE_TYPE:
245 return ANSWERS_SUGGESTION_TEXT_NEGATIVE_COLOR;
246 case ANSWERS_SUGGESTION_LINK_COLOR_TYPE:
247 return ANSWERS_SUGGESTION_LINK_COLOR_COLOR;
248 case ANSWERS_STATUS_TEXT_TYPE:
249 return ANSWERS_STATUS_TEXT_COLOR;
250 case ANSWERS_PERSONALIZED_SUGGESTION_TEXT_TYPE:
251 return ANSWERS_PERSONALIZED_SUGGESTION_TEXT_COLOR;
252 default:
253 Log.w(TAG, "Unknown answer type: " + type);
254 return ANSWERS_SUGGESTION_TEXT_COLOR;
255 }
256 }
257
258 /**
259 * Aligns the top of the spanned text with the top of some other specified t ext height. This is
260 * done by calculating the ascent of both text heights and shifting the base line of the spanned
261 * text by the difference. As a result, "top aligned" means the top of the ascents are
262 * aligned, which looks as expected in most cases (some glyphs in some fonts are drawn above
263 * the top of the ascent).
264 */
265 private static class TopAlignedSpan extends MetricAffectingSpan {
266 private int mBaselineShift;
267
268 /**
269 * Constructor for TopAlignedSpan.
270 *
271 * @param textHeightSp The total height in SP of the text covered by thi s span.
272 * @param maxTextHeightSp The total height in SP of the text we wish to top-align with.
273 * @param metrics The font metrics used to determine what proportion of the font height is
274 * the ascent.
275 * @param density The display density.
276 */
277 public TopAlignedSpan(
278 int textHeightSp, int maxTextHeightSp, Paint.FontMetrics metrics , float density) {
279 float ascentProportion = metrics.ascent / (metrics.top - metrics.bot tom);
280
281 int textAscentPx = (int) (textHeightSp * ascentProportion * density) ;
282 int maxTextAscentPx = (int) (maxTextHeightSp * ascentProportion * de nsity);
283
284 this.mBaselineShift = -(maxTextAscentPx - textAscentPx); // Up is - y.
285 }
286
287 @Override
288 public void updateDrawState(TextPaint tp) {
289 tp.baselineShift += mBaselineShift;
290 }
291
292 @Override
293 public void updateMeasureState(TextPaint tp) {
294 tp.baselineShift += mBaselineShift;
295 }
296 }
297 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698