Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
ExtractStyle.java
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5package org.qtproject.qt.android;
6
7import android.annotation.SuppressLint;
8import android.content.Context;
9import android.content.res.ColorStateList;
10import android.content.res.Configuration;
11import android.content.res.Resources;
12import android.content.res.TypedArray;
13import android.content.res.XmlResourceParser;
14import android.graphics.Bitmap;
15import android.graphics.Bitmap.Config;
16import android.graphics.Canvas;
17import android.graphics.NinePatch;
18import android.graphics.Rect;
19import android.graphics.drawable.AnimatedStateListDrawable;
20import android.graphics.drawable.AnimationDrawable;
21import android.graphics.drawable.BitmapDrawable;
22import android.graphics.drawable.ClipDrawable;
23import android.graphics.drawable.ColorDrawable;
24import android.graphics.drawable.Drawable;
25import android.graphics.drawable.GradientDrawable;
26import android.graphics.drawable.GradientDrawable.Orientation;
27import android.graphics.drawable.InsetDrawable;
28import android.graphics.drawable.LayerDrawable;
29import android.graphics.drawable.NinePatchDrawable;
30import android.graphics.drawable.RippleDrawable;
31import android.graphics.drawable.RotateDrawable;
32import android.graphics.drawable.ScaleDrawable;
33import android.graphics.drawable.StateListDrawable;
34import android.graphics.drawable.VectorDrawable;
35import android.os.Build;
36import android.util.AttributeSet;
37import android.util.Log;
38import android.util.TypedValue;
39import android.util.Xml;
40import android.view.ContextThemeWrapper;
41import android.view.inputmethod.EditorInfo;
42
43import org.json.JSONArray;
44import org.json.JSONException;
45import org.json.JSONObject;
46import org.xmlpull.v1.XmlPullParser;
47
48import java.io.File;
49import java.io.FileOutputStream;
50import java.io.IOException;
51import java.io.OutputStreamWriter;
52import java.lang.reflect.Field;
53import java.nio.file.Files;
54import java.nio.file.Paths;
55import java.util.ArrayList;
56import java.util.Arrays;
57import java.util.HashMap;
58import java.util.Map;
59import java.util.Objects;
60
61@SuppressWarnings("deprecation")
62class ExtractStyle {
63 // This used to be retrieved from android.R.styleable.ViewDrawableStates field via reflection,
64 // but since the access to that is restricted, we need to have hard-coded here.
65 final int[] viewDrawableStatesState = new int[]{
66 android.R.attr.state_focused,
67 android.R.attr.state_window_focused,
68 android.R.attr.state_enabled,
69 android.R.attr.state_selected,
70 android.R.attr.state_pressed,
71 android.R.attr.state_activated,
72 android.R.attr.state_accelerated,
73 android.R.attr.state_hovered,
74 android.R.attr.state_drag_can_accept,
75 android.R.attr.state_drag_hovered
76 };
77 final int[] EMPTY_STATE_SET = {};
78 final int[] ENABLED_STATE_SET = {android.R.attr.state_enabled};
79 final int[] FOCUSED_STATE_SET = {android.R.attr.state_focused};
80 final int[] SELECTED_STATE_SET = {android.R.attr.state_selected};
81 final int[] PRESSED_STATE_SET = {android.R.attr.state_pressed};
82 final int[] WINDOW_FOCUSED_STATE_SET = {android.R.attr.state_window_focused};
83 final int[] ENABLED_FOCUSED_STATE_SET = stateSetUnion(ENABLED_STATE_SET, FOCUSED_STATE_SET);
84 final int[] ENABLED_SELECTED_STATE_SET = stateSetUnion(ENABLED_STATE_SET, SELECTED_STATE_SET);
85 final int[] ENABLED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
86 final int[] FOCUSED_SELECTED_STATE_SET = stateSetUnion(FOCUSED_STATE_SET, SELECTED_STATE_SET);
87 final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
88 final int[] SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
89 final int[] ENABLED_FOCUSED_SELECTED_STATE_SET = stateSetUnion(ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
90 final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
91 final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
92 final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
93 final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(ENABLED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
94 final int[] PRESSED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
95 final int[] PRESSED_SELECTED_STATE_SET = stateSetUnion(PRESSED_STATE_SET, SELECTED_STATE_SET);
96 final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
97 final int[] PRESSED_FOCUSED_STATE_SET = stateSetUnion(PRESSED_STATE_SET, FOCUSED_STATE_SET);
98 final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
99 final int[] PRESSED_FOCUSED_SELECTED_STATE_SET = stateSetUnion(PRESSED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
100 final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
101 final int[] PRESSED_ENABLED_STATE_SET = stateSetUnion(PRESSED_STATE_SET, ENABLED_STATE_SET);
102 final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
103 final int[] PRESSED_ENABLED_SELECTED_STATE_SET = stateSetUnion(PRESSED_ENABLED_STATE_SET, SELECTED_STATE_SET);
104 final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
105 final int[] PRESSED_ENABLED_FOCUSED_STATE_SET = stateSetUnion(PRESSED_ENABLED_STATE_SET, FOCUSED_STATE_SET);
106 final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
107 final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
108 final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
109 final Resources.Theme m_theme;
110 final String m_extractPath;
111 final int defaultBackgroundColor;
112 final int defaultTextColor;
113 final boolean m_minimal;
114 final int[] DrawableStates = { android.R.attr.state_active, android.R.attr.state_checked,
115 android.R.attr.state_enabled, android.R.attr.state_focused,
116 android.R.attr.state_pressed, android.R.attr.state_selected,
117 android.R.attr.state_window_focused, 16908288, android.R.attr.state_multiline,
118 android.R.attr.state_activated, android.R.attr.state_accelerated};
119 final String[] DrawableStatesLabels = {"active", "checked", "enabled", "focused", "pressed",
120 "selected", "window_focused", "background", "multiline", "activated", "accelerated"};
121 final String[] DisableDrawableStatesLabels = {"inactive", "unchecked", "disabled",
122 "not_focused", "no_pressed", "unselected", "window_not_focused", "background",
123 "multiline", "activated", "accelerated"};
124 final String[] sScaleTypeArray = {
125 "MATRIX",
126 "FIT_XY",
127 "FIT_START",
128 "FIT_CENTER",
129 "FIT_END",
130 "CENTER",
131 "CENTER_CROP",
132 "CENTER_INSIDE"
133 };
134 Context m_context;
135 private final HashMap<String, DrawableCache> m_drawableCache = new HashMap<>();
136
137 private static boolean m_missingNormalStyle = false;
138 private static boolean m_missingDarkStyle = false;
139 private static String m_stylePath = null;
140 private static boolean m_extractMinimal = false;
141
142 private static final String QtTAG = "QtExtractStyle";
143
144 private static boolean isUiModeDark(Configuration config)
145 {
146 return (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
147 }
148
149 static String setup(Context context, String extractOption, int dpi) {
150
151 String dataDir = context.getApplicationInfo().dataDir;
152 m_stylePath = dataDir + "/qt-reserved-files/android-style/" + dpi + "/";
153
154 if (extractOption.equals("none"))
155 return m_stylePath;
156
157 if (extractOption.isEmpty())
158 extractOption = "minimal";
159
160 if (!extractOption.equals("default") && !extractOption.equals("full")
161 && !extractOption.equals("minimal") && !extractOption.equals("none")) {
162 Log.e(QtTAG, "Invalid extract_android_style option \"" + extractOption
163 + "\", defaulting to \"minimal\"");
164 extractOption = "minimal";
165 }
166
167 // QTBUG-69810: The extraction code will trigger compatibility warnings on Android
168 // SDK version >= 28 when the target SDK version is set to something lower then 28,
169 // so default to "none" and issue a warning if that is the case.
170 if (extractOption.equals("default")) {
171 int targetSdk = context.getApplicationInfo().targetSdkVersion;
172 if (targetSdk < 28 && Build.VERSION.SDK_INT >= 28) {
173 Log.e(QtTAG, "extract_android_style option set to \"none\" when " +
174 "targetSdkVersion is less then 28");
175 extractOption = "none";
176 }
177 }
178
179 boolean darkModeFileMissing = !(new File(m_stylePath + "darkUiMode/style.json").exists());
180 m_missingDarkStyle = Build.VERSION.SDK_INT > 28 && darkModeFileMissing;
181 m_missingNormalStyle = !(new File(m_stylePath + "style.json").exists());
182 m_extractMinimal = extractOption.equals("minimal");
183
184 ExtractStyle.runIfNeeded(context, isUiModeDark(context.getResources().getConfiguration()));
185
186 return m_stylePath;
187 }
188
189 static void runIfNeeded(Context context, boolean extractDarkMode) {
190 if (m_stylePath == null)
191 return;
192 if (extractDarkMode) {
193 if (m_missingDarkStyle) {
194 new ExtractStyle(context, m_stylePath + "darkUiMode/", m_extractMinimal);
195 m_missingDarkStyle = false;
196 }
197 } else if (m_missingNormalStyle) {
198 new ExtractStyle(context, m_stylePath, m_extractMinimal);
199 m_missingNormalStyle = false;
200 }
201 }
202
203 ExtractStyle(Context context, String extractPath, boolean minimal) {
204 m_minimal = minimal;
205 m_extractPath = extractPath + "/";
206 boolean dirCreated = new File(m_extractPath).mkdirs();
207 if (!dirCreated)
208 Log.w(QtNative.QtTAG, "Cannot create Android style directory.");
209 m_context = context;
210 m_theme = context.getTheme();
211 TypedArray array = m_theme.obtainStyledAttributes(new int[]{
212 android.R.attr.colorBackground,
213 android.R.attr.textColorPrimary,
214 android.R.attr.textColor
215 });
216 defaultBackgroundColor = array.getColor(0, 0);
217 int textColor = array.getColor(1, 0xFFFFFF);
218 if (textColor == 0xFFFFFF)
219 textColor = array.getColor(2, 0xFFFFFF);
220 defaultTextColor = textColor;
221 array.recycle();
222
223 try {
224 SimpleJsonWriter jsonWriter = new SimpleJsonWriter(m_extractPath + "style.json");
225 jsonWriter.beginObject();
226 try {
227 jsonWriter.name("defaultStyle").value(extractDefaultPalette());
228 extractWindow(jsonWriter);
229 jsonWriter.name("buttonStyle").value(extractTextAppearanceInformation(android.R.attr.buttonStyle, "QPushButton"));
230 jsonWriter.name("spinnerStyle").value(extractTextAppearanceInformation(android.R.attr.spinnerStyle, "QComboBox"));
231 extractProgressBar(jsonWriter, android.R.attr.progressBarStyleHorizontal, "progressBarStyleHorizontal", "QProgressBar");
232 extractProgressBar(jsonWriter, android.R.attr.progressBarStyleLarge, "progressBarStyleLarge", null);
233 extractProgressBar(jsonWriter, android.R.attr.progressBarStyleSmall, "progressBarStyleSmall", null);
234 extractProgressBar(jsonWriter, android.R.attr.progressBarStyle, "progressBarStyle", null);
235 extractAbsSeekBar(jsonWriter);
236 extractSwitch(jsonWriter);
237 extractCompoundButton(jsonWriter, android.R.attr.checkboxStyle, "checkboxStyle", "QCheckBox");
238 jsonWriter.name("editTextStyle").value(extractTextAppearanceInformation(android.R.attr.editTextStyle, "QLineEdit"));
239 extractCompoundButton(jsonWriter, android.R.attr.radioButtonStyle, "radioButtonStyle", "QRadioButton");
240 jsonWriter.name("textViewStyle").value(extractTextAppearanceInformation(android.R.attr.textViewStyle, "QWidget"));
241 jsonWriter.name("scrollViewStyle").value(extractTextAppearanceInformation(android.R.attr.scrollViewStyle, "QAbstractScrollArea"));
242 extractListView(jsonWriter);
243 jsonWriter.name("listSeparatorTextViewStyle").value(extractTextAppearanceInformation(android.R.attr.listSeparatorTextViewStyle, null));
244 extractItemsStyle(jsonWriter);
245 extractCompoundButton(jsonWriter, android.R.attr.buttonStyleToggle, "buttonStyleToggle", null);
246 extractCalendar(jsonWriter);
247 extractToolBar(jsonWriter);
248 jsonWriter.name("actionButtonStyle").value(extractTextAppearanceInformation(android.R.attr.actionButtonStyle, "QToolButton"));
249 jsonWriter.name("actionBarTabTextStyle").value(extractTextAppearanceInformation(android.R.attr.actionBarTabTextStyle, null));
250 jsonWriter.name("actionBarTabStyle").value(extractTextAppearanceInformation(android.R.attr.actionBarTabStyle, null));
251 jsonWriter.name("actionOverflowButtonStyle").value(extractImageViewInformation(android.R.attr.actionOverflowButtonStyle, null));
252 extractTabBar(jsonWriter);
253 } catch (Exception e) {
254 e.printStackTrace();
255 }
256 jsonWriter.endObject();
257 jsonWriter.close();
258 } catch (Exception e) {
259 e.printStackTrace();
260 }
261 }
262
263 native static int[] extractNativeChunkInfo20(long nativeChunk);
264
265 private int[] stateSetUnion(final int[] stateSet1, final int[] stateSet2) {
266 try {
267 final int stateSet1Length = stateSet1.length;
268 final int stateSet2Length = stateSet2.length;
269 final int[] newSet = new int[stateSet1Length + stateSet2Length];
270 int k = 0;
271 int i = 0;
272 int j = 0;
273 // This is a merge of the two input state sets and assumes that the
274 // input sets are sorted by the order imposed by ViewDrawableStates.
275 for (int viewState : viewDrawableStatesState) {
276 if (i < stateSet1Length && stateSet1[i] == viewState) {
277 newSet[k++] = viewState;
278 i++;
279 } else if (j < stateSet2Length && stateSet2[j] == viewState) {
280 newSet[k++] = viewState;
281 j++;
282 }
283 assert k <= 1 || (newSet[k - 1] > newSet[k - 2]);
284 }
285 return newSet;
286 } catch (Exception e) {
287 e.printStackTrace();
288 }
289 return null;
290 }
291
292 Field getAccessibleField(Class<?> clazz, String fieldName) {
293 try {
294 Field f = clazz.getDeclaredField(fieldName);
295 f.setAccessible(true);
296 return f;
297 } catch (Exception e) {
298 e.printStackTrace();
299 }
300 return null;
301 }
302
303 Field tryGetAccessibleField(Class<?> clazz, String fieldName) {
304 if (clazz == null)
305 return null;
306
307 try {
308 Field f = clazz.getDeclaredField(fieldName);
309 f.setAccessible(true);
310 return f;
311 } catch (Exception e) {
312 for (Class<?> c : clazz.getInterfaces()) {
313 Field f = tryGetAccessibleField(c, fieldName);
314 if (f != null)
315 return f;
316 }
317 }
318 return tryGetAccessibleField(clazz.getSuperclass(), fieldName);
319 }
320
321 JSONObject getColorStateList(ColorStateList colorList) {
322 JSONObject json = new JSONObject();
323 try {
324 json.put("EMPTY_STATE_SET", colorList.getColorForState(EMPTY_STATE_SET, 0));
325 json.put("WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(WINDOW_FOCUSED_STATE_SET, 0));
326 json.put("SELECTED_STATE_SET", colorList.getColorForState(SELECTED_STATE_SET, 0));
327 json.put("SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
328 json.put("FOCUSED_STATE_SET", colorList.getColorForState(FOCUSED_STATE_SET, 0));
329 json.put("FOCUSED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(FOCUSED_WINDOW_FOCUSED_STATE_SET, 0));
330 json.put("FOCUSED_SELECTED_STATE_SET", colorList.getColorForState(FOCUSED_SELECTED_STATE_SET, 0));
331 json.put("FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
332 json.put("ENABLED_STATE_SET", colorList.getColorForState(ENABLED_STATE_SET, 0));
333 json.put("ENABLED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(ENABLED_WINDOW_FOCUSED_STATE_SET, 0));
334 json.put("ENABLED_SELECTED_STATE_SET", colorList.getColorForState(ENABLED_SELECTED_STATE_SET, 0));
335 json.put("ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
336 json.put("ENABLED_FOCUSED_STATE_SET", colorList.getColorForState(ENABLED_FOCUSED_STATE_SET, 0));
337 json.put("ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET, 0));
338 json.put("ENABLED_FOCUSED_SELECTED_STATE_SET", colorList.getColorForState(ENABLED_FOCUSED_SELECTED_STATE_SET, 0));
339 json.put("ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
340 json.put("PRESSED_STATE_SET", colorList.getColorForState(PRESSED_STATE_SET, 0));
341 json.put("PRESSED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_WINDOW_FOCUSED_STATE_SET, 0));
342 json.put("PRESSED_SELECTED_STATE_SET", colorList.getColorForState(PRESSED_SELECTED_STATE_SET, 0));
343 json.put("PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
344 json.put("PRESSED_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_FOCUSED_STATE_SET, 0));
345 json.put("PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET, 0));
346 json.put("PRESSED_FOCUSED_SELECTED_STATE_SET", colorList.getColorForState(PRESSED_FOCUSED_SELECTED_STATE_SET, 0));
347 json.put("PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
348 json.put("PRESSED_ENABLED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_STATE_SET, 0));
349 json.put("PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET, 0));
350 json.put("PRESSED_ENABLED_SELECTED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_SELECTED_STATE_SET, 0));
351 json.put("PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
352 json.put("PRESSED_ENABLED_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_FOCUSED_STATE_SET, 0));
353 json.put("PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET, 0));
354 json.put("PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, 0));
355 json.put("PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0));
356 } catch (JSONException e) {
357 e.printStackTrace();
358 }
359
360 return json;
361 }
362
363 JSONObject getStatesList(int[] states) throws JSONException {
364 JSONObject json = new JSONObject();
365 for (int s : states) {
366 boolean found = false;
367 for (int d = 0; d < DrawableStates.length; d++) {
368 if (s == DrawableStates[d]) {
369 json.put(DrawableStatesLabels[d], true);
370 found = true;
371 break;
372 } else if (s == -DrawableStates[d]) {
373 json.put(DrawableStatesLabels[d], false);
374
375 found = true;
376 break;
377 }
378 }
379 if (!found) {
380 json.put("unhandled_state_" + s, s > 0);
381 }
382 }
383 return json;
384 }
385
386 String getStatesName(int[] states) {
387 StringBuilder statesName = new StringBuilder();
388 for (int s : states) {
389 boolean found = false;
390 for (int d = 0; d < DrawableStates.length; d++) {
391 if (s == DrawableStates[d]) {
392 if (statesName.length() > 0)
393 statesName.append("__");
394 statesName.append(DrawableStatesLabels[d]);
395 found = true;
396 break;
397 } else if (s == -DrawableStates[d]) {
398 if (statesName.length() > 0)
399 statesName.append("__");
400 statesName.append(DisableDrawableStatesLabels[d]);
401 found = true;
402 break;
403 }
404 }
405 if (!found) {
406 if (statesName.length() > 0)
407 statesName.append(";");
408 statesName.append(s);
409 }
410 }
411 if (statesName.length() > 0)
412 return statesName.toString();
413 return "empty";
414 }
415
416 private JSONObject getLayerDrawable(Object drawable, String filename) {
417 JSONObject json = new JSONObject();
418 LayerDrawable layers = (LayerDrawable) drawable;
419 final int nr = layers.getNumberOfLayers();
420 try {
421 JSONArray array = new JSONArray();
422 for (int i = 0; i < nr; i++) {
423 int id = layers.getId(i);
424 if (id == -1)
425 id = i;
426 JSONObject layerJsonObject = getDrawable(layers.getDrawable(i), filename + "__" + id, null);
427 layerJsonObject.put("id", id);
428 array.put(layerJsonObject);
429 }
430 json.put("type", "layer");
431 Rect padding = new Rect();
432 if (layers.getPadding(padding))
433 json.put("padding", getJsonRect(padding));
434 json.put("layers", array);
435 } catch (JSONException e) {
436 e.printStackTrace();
437 }
438 return json;
439 }
440
441 private JSONObject getStateListDrawable(Object drawable, String filename) {
442 JSONObject json = new JSONObject();
443 try {
444 StateListDrawable stateList = (StateListDrawable) drawable;
445 JSONArray array = new JSONArray();
446 final int numStates;
447 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
448 numStates = (Integer) StateListDrawable.class.getMethod("getStateCount").invoke(stateList);
449 else
450 numStates = stateList.getStateCount();
451 for (int i = 0; i < numStates; i++) {
452 JSONObject stateJson = new JSONObject();
453 final Drawable d = (Drawable) StateListDrawable.class.getMethod("getStateDrawable", Integer.TYPE).invoke(stateList, i);
454 final int[] states = (int[]) StateListDrawable.class.getMethod("getStateSet", Integer.TYPE).invoke(stateList, i);
455 if (states != null)
456 stateJson.put("states", getStatesList(states));
457 stateJson.put("drawable", getDrawable(d, filename + "__" + (states != null ? getStatesName(states) : ("state_pos_" + i)), null));
458 array.put(stateJson);
459 }
460 json.put("type", "stateslist");
461 Rect padding = new Rect();
462 if (stateList.getPadding(padding))
463 json.put("padding", getJsonRect(padding));
464 json.put("stateslist", array);
465 } catch (Exception e) {
466 e.printStackTrace();
467 }
468 return json;
469 }
470
471 private JSONObject getGradientDrawable(GradientDrawable drawable) {
472 JSONObject json = new JSONObject();
473 try {
474 json.put("type", "gradient");
475 Object obj = drawable.getConstantState();
476 Class<?> gradientStateClass = obj.getClass();
477 json.put("shape", gradientStateClass.getField("mShape").getInt(obj));
478 json.put("gradient", gradientStateClass.getField("mGradient").getInt(obj));
479 GradientDrawable.Orientation orientation = (Orientation) gradientStateClass.getField("mOrientation").get(obj);
480 if (orientation != null)
481 json.put("orientation", orientation.name());
482 int[] intArray = (int[]) gradientStateClass.getField("mGradientColors").get(obj);
483 if (intArray != null)
484 json.put("colors", getJsonArray(intArray, 0, intArray.length));
485 json.put("positions", getJsonArray((float[]) gradientStateClass.getField("mPositions").get(obj)));
486 json.put("strokeWidth", gradientStateClass.getField("mStrokeWidth").getInt(obj));
487 json.put("strokeDashWidth", gradientStateClass.getField("mStrokeDashWidth").getFloat(obj));
488 json.put("strokeDashGap", gradientStateClass.getField("mStrokeDashGap").getFloat(obj));
489 json.put("radius", gradientStateClass.getField("mRadius").getFloat(obj));
490 float[] floatArray = (float[]) gradientStateClass.getField("mRadiusArray").get(obj);
491 if (floatArray != null)
492 json.put("radiusArray", getJsonArray(floatArray));
493 Rect rc = (Rect) gradientStateClass.getField("mPadding").get(obj);
494 if (rc != null)
495 json.put("padding", getJsonRect(rc));
496 json.put("width", gradientStateClass.getField("mWidth").getInt(obj));
497 json.put("height", gradientStateClass.getField("mHeight").getInt(obj));
498 json.put("innerRadiusRatio", gradientStateClass.getField("mInnerRadiusRatio").getFloat(obj));
499 json.put("thicknessRatio", gradientStateClass.getField("mThicknessRatio").getFloat(obj));
500 json.put("innerRadius", gradientStateClass.getField("mInnerRadius").getInt(obj));
501 json.put("thickness", gradientStateClass.getField("mThickness").getInt(obj));
502 } catch (Exception e) {
503 e.printStackTrace();
504 }
505 return json;
506 }
507
508 private JSONObject getRotateDrawable(RotateDrawable drawable, String filename) {
509 JSONObject json = new JSONObject();
510 try {
511 json.put("type", "rotate");
512 Object obj = drawable.getConstantState();
513 Class<?> rotateStateClass = obj.getClass();
514 json.put("drawable", getDrawable(drawable.getClass().getMethod("getDrawable").invoke(drawable), filename, null));
515 json.put("pivotX", getAccessibleField(rotateStateClass, "mPivotX").getFloat(obj));
516 json.put("pivotXRel", getAccessibleField(rotateStateClass, "mPivotXRel").getBoolean(obj));
517 json.put("pivotY", getAccessibleField(rotateStateClass, "mPivotY").getFloat(obj));
518 json.put("pivotYRel", getAccessibleField(rotateStateClass, "mPivotYRel").getBoolean(obj));
519 json.put("fromDegrees", getAccessibleField(rotateStateClass, "mFromDegrees").getFloat(obj));
520 json.put("toDegrees", getAccessibleField(rotateStateClass, "mToDegrees").getFloat(obj));
521 } catch (Exception e) {
522 e.printStackTrace();
523 }
524 return json;
525 }
526
527 private JSONObject getAnimationDrawable(AnimationDrawable drawable, String filename) {
528 JSONObject json = new JSONObject();
529 try {
530 json.put("type", "animation");
531 json.put("oneshot", drawable.isOneShot());
532 final int count = drawable.getNumberOfFrames();
533 JSONArray frames = new JSONArray();
534 for (int i = 0; i < count; ++i) {
535 JSONObject frame = new JSONObject();
536 frame.put("duration", drawable.getDuration(i));
537 frame.put("drawable", getDrawable(drawable.getFrame(i), filename + "__" + i, null));
538 frames.put(frame);
539 }
540 json.put("frames", frames);
541 } catch (Exception e) {
542 e.printStackTrace();
543 }
544 return json;
545 }
546
547 private JSONObject getJsonRect(Rect rect) throws JSONException {
548 JSONObject jsonRect = new JSONObject();
549 jsonRect.put("left", rect.left);
550 jsonRect.put("top", rect.top);
551 jsonRect.put("right", rect.right);
552 jsonRect.put("bottom", rect.bottom);
553 return jsonRect;
554
555 }
556
557 private JSONArray getJsonArray(int[] array, int pos, int len) {
558 JSONArray a = new JSONArray();
559 final int l = pos + len;
560 for (int i = pos; i < l; i++)
561 a.put(array[i]);
562 return a;
563 }
564
565 private JSONArray getJsonArray(float[] array) throws JSONException {
566 JSONArray a = new JSONArray();
567 if (array != null)
568 for (float val : array)
569 a.put(val);
570 return a;
571 }
572
573 private JSONObject getJsonChunkInfo(int[] chunkData) throws JSONException {
574 JSONObject jsonRect = new JSONObject();
575 if (chunkData == null)
576 return jsonRect;
577
578 jsonRect.put("xdivs", getJsonArray(chunkData, 3, chunkData[0]));
579 jsonRect.put("ydivs", getJsonArray(chunkData, 3 + chunkData[0], chunkData[1]));
580 jsonRect.put("colors", getJsonArray(chunkData, 3 + chunkData[0] + chunkData[1], chunkData[2]));
581 return jsonRect;
582 }
583
584 private JSONObject findPatchesMarings(Drawable d) throws JSONException, IllegalAccessException {
585 NinePatch np;
586 Field f = tryGetAccessibleField(NinePatchDrawable.class, "mNinePatch");
587 if (f != null) {
588 np = (NinePatch) f.get(d);
589 } else {
590 Object state = getAccessibleField(NinePatchDrawable.class, "mNinePatchState").get(d);
591 np = (NinePatch) getAccessibleField(Objects.requireNonNull(state).getClass(), "mNinePatch").get(state);
592 }
593 return getJsonChunkInfo(extractNativeChunkInfo20(getAccessibleField(Objects.requireNonNull(np).getClass(), "mNativeChunk").getLong(np)));
594 }
595
596 private JSONObject getRippleDrawable(Object drawable, String filename, Rect padding) {
597 JSONObject json = getLayerDrawable(drawable, filename);
598 JSONObject ripple = new JSONObject();
599 try {
600 Class<?> rippleDrawableClass = Class.forName("android.graphics.drawable.RippleDrawable");
601 final Object mState = getAccessibleField(rippleDrawableClass, "mState").get(drawable);
602 ripple.put("mask", getDrawable(getAccessibleField(rippleDrawableClass, "mMask").get(drawable), filename, padding));
603 if (mState != null) {
604 ripple.put("maxRadius", getAccessibleField(mState.getClass(), "mMaxRadius").getInt(mState));
605 ColorStateList color = (ColorStateList) getAccessibleField(mState.getClass(), "mColor").get(mState);
606 if (color != null)
607 ripple.put("color", getColorStateList(color));
608 }
609 json.put("ripple", ripple);
610 } catch (Exception e) {
611 e.printStackTrace();
612 }
613 return json;
614 }
615
616 private HashMap<Long, Long> getStateTransitions(Object sa) throws Exception {
617 HashMap<Long, Long> transitions = new HashMap<>();
618 final int sz = getAccessibleField(sa.getClass(), "mSize").getInt(sa);
619 long[] keys = (long[]) getAccessibleField(sa.getClass(), "mKeys").get(sa);
620 long[] values = (long[]) getAccessibleField(sa.getClass(), "mValues").get(sa);
621 for (int i = 0; i < sz; i++) {
622 if (keys != null && values != null)
623 transitions.put(keys[i], values[i]);
624 }
625 return transitions;
626 }
627
628 private HashMap<Integer, Integer> getStateIds(Object sa) throws Exception {
629 HashMap<Integer, Integer> states = new HashMap<>();
630 final int sz = getAccessibleField(sa.getClass(), "mSize").getInt(sa);
631 int[] keys = (int[]) getAccessibleField(sa.getClass(), "mKeys").get(sa);
632 int[] values = (int[]) getAccessibleField(sa.getClass(), "mValues").get(sa);
633 for (int i = 0; i < sz; i++) {
634 if (keys != null && values != null)
635 states.put(keys[i], values[i]);
636 }
637 return states;
638 }
639
640 private int findStateIndex(int id, HashMap<Integer, Integer> stateIds) {
641 for (Map.Entry<Integer, Integer> s : stateIds.entrySet()) {
642 if (id == s.getValue())
643 return s.getKey();
644 }
645 return -1;
646 }
647
648 private JSONObject getAnimatedStateListDrawable(Object drawable, String filename) {
649 JSONObject json = getStateListDrawable(drawable, filename);
650 try {
651 Class<?> animatedStateListDrawableClass = Class.forName("android.graphics.drawable.AnimatedStateListDrawable");
652 Object state = getAccessibleField(animatedStateListDrawableClass, "mState").get(drawable);
653
654 if (state != null) {
655 Class<?> stateClass = state.getClass();
656 HashMap<Integer, Integer> stateIds = getStateIds(Objects.requireNonNull(getAccessibleField(stateClass, "mStateIds").get(state)));
657 HashMap<Long, Long> transitions = getStateTransitions(Objects.requireNonNull(getAccessibleField(stateClass, "mTransitions").get(state)));
658
659 for (Map.Entry<Long, Long> t : transitions.entrySet()) {
660 final int toState = findStateIndex(t.getKey().intValue(), stateIds);
661 final int fromState = findStateIndex((int) (t.getKey() >> 32), stateIds);
662
663 JSONObject transition = new JSONObject();
664 transition.put("from", fromState);
665 transition.put("to", toState);
666 transition.put("reverse", (t.getValue() >> 32) != 0);
667
668 JSONArray stateslist = json.getJSONArray("stateslist");
669 JSONObject stateobj = stateslist.getJSONObject(t.getValue().intValue());
670 stateobj.put("transition", transition);
671 }
672 }
673 } catch (Exception e) {
674 e.printStackTrace();
675 }
676 return json;
677 }
678
679 private JSONObject getVPath(Object path) throws Exception {
680 JSONObject json = new JSONObject();
681 final Class<?> pathClass = path.getClass();
682 json.put("type", "path");
683 json.put("name", tryGetAccessibleField(pathClass, "mPathName").get(path));
684 Object[] mNodes = (Object[]) tryGetAccessibleField(pathClass, "mNodes").get(path);
685 JSONArray nodes = new JSONArray();
686 if (mNodes != null) {
687 for (Object n : mNodes) {
688 JSONObject node = new JSONObject();
689 node.put("type", String.valueOf(getAccessibleField(n.getClass(), "mType").getChar(n)));
690 node.put("params", getJsonArray((float[]) getAccessibleField(n.getClass(), "mParams").get(n)));
691 nodes.put(node);
692 }
693 json.put("nodes", nodes);
694 }
695 json.put("isClip", pathClass.getMethod("isClipPath").invoke(path));
696
697 if (tryGetAccessibleField(pathClass, "mStrokeColor") == null)
698 return json; // not VFullPath
699
700 json.put("strokeColor", getAccessibleField(pathClass, "mStrokeColor").getInt(path));
701 json.put("strokeWidth", getAccessibleField(pathClass, "mStrokeWidth").getFloat(path));
702 json.put("fillColor", getAccessibleField(pathClass, "mFillColor").getInt(path));
703 json.put("strokeAlpha", getAccessibleField(pathClass, "mStrokeAlpha").getFloat(path));
704 json.put("fillRule", getAccessibleField(pathClass, "mFillRule").getInt(path));
705 json.put("fillAlpha", getAccessibleField(pathClass, "mFillAlpha").getFloat(path));
706 json.put("trimPathStart", getAccessibleField(pathClass, "mTrimPathStart").getFloat(path));
707 json.put("trimPathEnd", getAccessibleField(pathClass, "mTrimPathEnd").getFloat(path));
708 json.put("trimPathOffset", getAccessibleField(pathClass, "mTrimPathOffset").getFloat(path));
709 json.put("strokeLineCap", getAccessibleField(pathClass, "mStrokeLineCap").get(path));
710 json.put("strokeLineJoin", getAccessibleField(pathClass, "mStrokeLineJoin").get(path));
711 json.put("strokeMiterlimit", getAccessibleField(pathClass, "mStrokeMiterlimit").getFloat(path));
712 return json;
713 }
714
715 @SuppressWarnings("unchecked")
716 private JSONObject getVGroup(Object group) throws Exception {
717 JSONObject json = new JSONObject();
718 json.put("type", "group");
719 final Class<?> groupClass = group.getClass();
720 json.put("name", getAccessibleField(groupClass, "mGroupName").get(group));
721 json.put("rotate", getAccessibleField(groupClass, "mRotate").getFloat(group));
722 json.put("pivotX", getAccessibleField(groupClass, "mPivotX").getFloat(group));
723 json.put("pivotY", getAccessibleField(groupClass, "mPivotY").getFloat(group));
724 json.put("scaleX", getAccessibleField(groupClass, "mScaleX").getFloat(group));
725 json.put("scaleY", getAccessibleField(groupClass, "mScaleY").getFloat(group));
726 json.put("translateX", getAccessibleField(groupClass, "mTranslateX").getFloat(group));
727 json.put("translateY", getAccessibleField(groupClass, "mTranslateY").getFloat(group));
728
729 ArrayList<Object> mChildren = (ArrayList<Object>) getAccessibleField(groupClass, "mChildren").get(group);
730 JSONArray children = new JSONArray();
731 if (mChildren != null) {
732 for (Object c : mChildren) {
733 if (groupClass.isInstance(c))
734 children.put(getVGroup(c));
735 else
736 children.put(getVPath(c));
737 }
738 json.put("children", children);
739 }
740 return json;
741 }
742
743 private JSONObject getVectorDrawable(Object drawable) {
744 JSONObject json = new JSONObject();
745 try {
746 json.put("type", "vector");
747 Class<?> vectorDrawableClass = Class.forName("android.graphics.drawable.VectorDrawable");
748 final Object state = getAccessibleField(vectorDrawableClass, "mVectorState").get(drawable);
749 final Class<?> stateClass = Objects.requireNonNull(state).getClass();
750 final ColorStateList mTint = (ColorStateList) getAccessibleField(stateClass, "mTint").get(state);
751 if (mTint != null) {
752 json.put("tintList", getColorStateList(mTint));
753 json.put("tintMode", getAccessibleField(stateClass, "mTintMode").get(state));
754 }
755 final Object mVPathRenderer = getAccessibleField(stateClass, "mVPathRenderer").get(state);
756 final Class<?> VPathRendererClass = Objects.requireNonNull(mVPathRenderer).getClass();
757 json.put("baseWidth", getAccessibleField(VPathRendererClass, "mBaseWidth").getFloat(mVPathRenderer));
758 json.put("baseHeight", getAccessibleField(VPathRendererClass, "mBaseHeight").getFloat(mVPathRenderer));
759 json.put("viewportWidth", getAccessibleField(VPathRendererClass, "mViewportWidth").getFloat(mVPathRenderer));
760 json.put("viewportHeight", getAccessibleField(VPathRendererClass, "mViewportHeight").getFloat(mVPathRenderer));
761 json.put("rootAlpha", getAccessibleField(VPathRendererClass, "mRootAlpha").getInt(mVPathRenderer));
762 json.put("rootName", getAccessibleField(VPathRendererClass, "mRootName").get(mVPathRenderer));
763 json.put("rootGroup", getVGroup(Objects.requireNonNull(getAccessibleField(VPathRendererClass, "mRootGroup").get(mVPathRenderer))));
764 } catch (Exception e) {
765 e.printStackTrace();
766 }
767 return json;
768 }
769
770 JSONObject getDrawable(Object drawable, String filename, Rect padding) {
771 if (drawable == null || m_minimal)
772 return null;
773
774 DrawableCache dc = m_drawableCache.get(filename);
775 if (dc != null) {
776 if (dc.drawable.equals(drawable))
777 return dc.object;
778 else
779 Log.e(QtNative.QtTAG, "Different drawable objects points to the same file name \"" + filename + "\"");
780 }
781 JSONObject json = new JSONObject();
782 Bitmap bmp = null;
783 if (drawable instanceof Bitmap)
784 bmp = (Bitmap) drawable;
785 else {
786 if (drawable instanceof BitmapDrawable) {
787 BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
788 bmp = bitmapDrawable.getBitmap();
789 try {
790 json.put("gravity", bitmapDrawable.getGravity());
791 json.put("tileModeX", bitmapDrawable.getTileModeX());
792 json.put("tileModeY", bitmapDrawable.getTileModeY());
793 json.put("antialias", BitmapDrawable.class.getMethod("hasAntiAlias").invoke(bitmapDrawable));
794 json.put("mipMap", BitmapDrawable.class.getMethod("hasMipMap").invoke(bitmapDrawable));
795 json.put("tintMode", BitmapDrawable.class.getMethod("getTintMode").invoke(bitmapDrawable));
796 ColorStateList tintList = (ColorStateList) BitmapDrawable.class.getMethod("getTint").invoke(bitmapDrawable);
797 if (tintList != null)
798 json.put("tintList", getColorStateList(tintList));
799 } catch (Exception e) {
800 e.printStackTrace();
801 }
802 } else {
803
804 if (drawable instanceof RippleDrawable)
805 return getRippleDrawable(drawable, filename, padding);
806
807 if (drawable instanceof AnimatedStateListDrawable)
808 return getAnimatedStateListDrawable(drawable, filename);
809
810 if (drawable instanceof VectorDrawable)
811 return getVectorDrawable(drawable);
812
813 if (drawable instanceof ScaleDrawable) {
814 return getDrawable(((ScaleDrawable) drawable).getDrawable(), filename, null);
815 }
816 if (drawable instanceof LayerDrawable) {
817 return getLayerDrawable(drawable, filename);
818 }
819 if (drawable instanceof StateListDrawable) {
820 return getStateListDrawable(drawable, filename);
821 }
822 if (drawable instanceof GradientDrawable) {
823 return getGradientDrawable((GradientDrawable) drawable);
824 }
825 if (drawable instanceof RotateDrawable) {
826 return getRotateDrawable((RotateDrawable) drawable, filename);
827 }
828 if (drawable instanceof AnimationDrawable) {
829 return getAnimationDrawable((AnimationDrawable) drawable, filename);
830 }
831 if (drawable instanceof ClipDrawable) {
832 try {
833 json.put("type", "clipDrawable");
834 Drawable.ConstantState dcs = ((ClipDrawable) drawable).getConstantState();
835 json.put("drawable", getDrawable(getAccessibleField(dcs.getClass(), "mDrawable").get(dcs), filename, null));
836 if (null != padding)
837 json.put("padding", getJsonRect(padding));
838 else {
839 Rect _padding = new Rect();
840 if (((Drawable) drawable).getPadding(_padding))
841 json.put("padding", getJsonRect(_padding));
842 }
843 } catch (Exception e) {
844 e.printStackTrace();
845 }
846 return json;
847 }
848 if (drawable instanceof ColorDrawable) {
849 bmp = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
850 Drawable d = (Drawable) drawable;
851 d.setBounds(0, 0, 1, 1);
852 d.draw(new Canvas(bmp));
853 try {
854 json.put("type", "color");
855 json.put("color", bmp.getPixel(0, 0));
856 if (null != padding)
857 json.put("padding", getJsonRect(padding));
858 else {
859 Rect _padding = new Rect();
860 if (d.getPadding(_padding))
861 json.put("padding", getJsonRect(_padding));
862 }
863 } catch (JSONException e) {
864 e.printStackTrace();
865 }
866 return json;
867 }
868 if (drawable instanceof InsetDrawable) {
869 try {
870 InsetDrawable d = (InsetDrawable) drawable;
871 Object mInsetStateObject = getAccessibleField(InsetDrawable.class, "mState").get(d);
872 Rect _padding = new Rect();
873 boolean hasPadding = d.getPadding(_padding);
874 return getDrawable(getAccessibleField(Objects.requireNonNull(mInsetStateObject).getClass(), "mDrawable").get(mInsetStateObject), filename, hasPadding ? _padding : null);
875 } catch (Exception e) {
876 e.printStackTrace();
877 }
878 } else {
879 Drawable d = (Drawable) drawable;
880 int w = d.getIntrinsicWidth();
881 int h = d.getIntrinsicHeight();
882 d.setLevel(10000);
883 if (w < 1 || h < 1) {
884 w = 100;
885 h = 100;
886 }
887 bmp = Bitmap.createBitmap(w, h, Config.ARGB_8888);
888 d.setBounds(0, 0, w, h);
889 d.draw(new Canvas(bmp));
890 if (drawable instanceof NinePatchDrawable) {
891 NinePatchDrawable npd = (NinePatchDrawable) drawable;
892 try {
893 json.put("type", "9patch");
894 json.put("drawable", getDrawable(bmp, filename, null));
895 if (padding != null)
896 json.put("padding", getJsonRect(padding));
897 else {
898 Rect _padding = new Rect();
899 if (npd.getPadding(_padding))
900 json.put("padding", getJsonRect(_padding));
901 }
902
903 json.put("chunkInfo", findPatchesMarings(d));
904 return json;
905 } catch (Exception e) {
906 e.printStackTrace();
907 }
908 }
909 }
910 }
911 }
912 FileOutputStream out;
913 try {
914 filename = m_extractPath + filename + ".png";
915 out = new FileOutputStream(filename);
916 if (bmp != null)
917 bmp.compress(Bitmap.CompressFormat.PNG, 100, out);
918 out.close();
919 } catch (IOException e) {
920 e.printStackTrace();
921 }
922 try {
923 json.put("type", "image");
924 json.put("path", filename);
925 if (bmp != null) {
926 json.put("width", bmp.getWidth());
927 json.put("height", bmp.getHeight());
928 }
929 m_drawableCache.put(filename, new DrawableCache(json, drawable));
930 } catch (JSONException e) {
931 e.printStackTrace();
932 }
933 return json;
934 }
935
936 private TypedArray obtainStyledAttributes(int styleName, int[] attributes)
937 {
938 TypedValue typedValue = new TypedValue();
939 Context ctx = new ContextThemeWrapper(m_context, m_theme);
940 ctx.getTheme().resolveAttribute(styleName, typedValue, true);
941 return ctx.obtainStyledAttributes(typedValue.data, attributes);
942 }
943
944 private ArrayList<Integer> getArrayListFromIntArray(int[] attributes) {
945 ArrayList<Integer> sortedAttrs = new ArrayList<>();
946 for (int attr : attributes)
947 sortedAttrs.add(attr);
948 return sortedAttrs;
949 }
950
951 void extractViewInformation(int styleName, JSONObject json, String qtClassName) {
952 extractViewInformation(styleName, json, qtClassName, null);
953 }
954
955 void extractViewInformation(int styleName, JSONObject json, String qtClassName, AttributeSet attributeSet) {
956 try {
957 TypedValue typedValue = new TypedValue();
958 Context ctx = new ContextThemeWrapper(m_context, m_theme);
959 ctx.getTheme().resolveAttribute(styleName, typedValue, true);
960
961 int[] attributes = new int[]{
962 android.R.attr.digits,
963 android.R.attr.background,
964 android.R.attr.padding,
965 android.R.attr.paddingLeft,
966 android.R.attr.paddingTop,
967 android.R.attr.paddingRight,
968 android.R.attr.paddingBottom,
969 android.R.attr.scrollX,
970 android.R.attr.scrollY,
971 android.R.attr.id,
972 android.R.attr.tag,
973 android.R.attr.fitsSystemWindows,
974 android.R.attr.focusable,
975 android.R.attr.focusableInTouchMode,
976 android.R.attr.clickable,
977 android.R.attr.longClickable,
978 android.R.attr.saveEnabled,
979 android.R.attr.duplicateParentState,
980 android.R.attr.visibility,
981 android.R.attr.drawingCacheQuality,
982 android.R.attr.contentDescription,
983 android.R.attr.soundEffectsEnabled,
984 android.R.attr.hapticFeedbackEnabled,
985 android.R.attr.scrollbars,
986 android.R.attr.fadingEdge,
987 android.R.attr.scrollbarStyle,
988 android.R.attr.scrollbarFadeDuration,
989 android.R.attr.scrollbarDefaultDelayBeforeFade,
990 android.R.attr.scrollbarSize,
991 android.R.attr.scrollbarThumbHorizontal,
992 android.R.attr.scrollbarThumbVertical,
993 android.R.attr.scrollbarTrackHorizontal,
994 android.R.attr.scrollbarTrackVertical,
995 android.R.attr.isScrollContainer,
996 android.R.attr.keepScreenOn,
997 android.R.attr.filterTouchesWhenObscured,
998 android.R.attr.nextFocusLeft,
999 android.R.attr.nextFocusRight,
1000 android.R.attr.nextFocusUp,
1001 android.R.attr.nextFocusDown,
1002 android.R.attr.minWidth,
1003 android.R.attr.minHeight,
1004 android.R.attr.onClick,
1005 android.R.attr.overScrollMode,
1006 android.R.attr.paddingStart,
1007 android.R.attr.paddingEnd,
1008 };
1009
1010 // The array must be sorted in ascending order, otherwise obtainStyledAttributes()
1011 // might fail to find some attributes
1012 Arrays.sort(attributes);
1013 TypedArray array;
1014 if (attributeSet != null)
1015 array = m_theme.obtainStyledAttributes(attributeSet, attributes, styleName, 0);
1016 else
1017 array = obtainStyledAttributes(styleName, attributes);
1018 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1019
1020 if (null != qtClassName)
1021 json.put("qtClass", qtClassName);
1022
1023 json.put("defaultBackgroundColor", defaultBackgroundColor);
1024 json.put("defaultTextColorPrimary", defaultTextColor);
1025 json.put("TextView_digits", array.getText(sortedAttrs.indexOf(android.R.attr.digits)));
1026 json.put("View_background", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.background)), styleName + "_View_background", null));
1027 json.put("View_padding", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.padding), -1));
1028 json.put("View_paddingLeft", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.paddingLeft), -1));
1029 json.put("View_paddingTop", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.paddingTop), -1));
1030 json.put("View_paddingRight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.paddingRight), -1));
1031 json.put("View_paddingBottom", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.paddingBottom), -1));
1032 json.put("View_paddingBottom", array.getDimensionPixelOffset(sortedAttrs.indexOf(android.R.attr.scrollX), 0));
1033 json.put("View_scrollY", array.getDimensionPixelOffset(sortedAttrs.indexOf(android.R.attr.scrollY), 0));
1034 json.put("View_id", array.getResourceId(sortedAttrs.indexOf(android.R.attr.id), -1));
1035 json.put("View_tag", array.getText(sortedAttrs.indexOf(android.R.attr.tag)));
1036 json.put("View_fitsSystemWindows", array.getBoolean(sortedAttrs.indexOf(android.R.attr.fitsSystemWindows), false));
1037 json.put("View_focusable", array.getBoolean(sortedAttrs.indexOf(android.R.attr.focusable), false));
1038 json.put("View_focusableInTouchMode", array.getBoolean(sortedAttrs.indexOf(android.R.attr.focusableInTouchMode), false));
1039 json.put("View_clickable", array.getBoolean(sortedAttrs.indexOf(android.R.attr.clickable), false));
1040 json.put("View_longClickable", array.getBoolean(sortedAttrs.indexOf(android.R.attr.longClickable), false));
1041 json.put("View_saveEnabled", array.getBoolean(sortedAttrs.indexOf(android.R.attr.saveEnabled), true));
1042 json.put("View_duplicateParentState", array.getBoolean(sortedAttrs.indexOf(android.R.attr.duplicateParentState), false));
1043 json.put("View_visibility", array.getInt(sortedAttrs.indexOf(android.R.attr.visibility), 0));
1044 json.put("View_drawingCacheQuality", array.getInt(sortedAttrs.indexOf(android.R.attr.drawingCacheQuality), 0));
1045 json.put("View_contentDescription", array.getString(sortedAttrs.indexOf(android.R.attr.contentDescription)));
1046 json.put("View_soundEffectsEnabled", array.getBoolean(sortedAttrs.indexOf(android.R.attr.soundEffectsEnabled), true));
1047 json.put("View_hapticFeedbackEnabled", array.getBoolean(sortedAttrs.indexOf(android.R.attr.hapticFeedbackEnabled), true));
1048 json.put("View_scrollbars", array.getInt(sortedAttrs.indexOf(android.R.attr.scrollbars), 0));
1049 json.put("View_fadingEdge", array.getInt(sortedAttrs.indexOf(android.R.attr.fadingEdge), 0));
1050 json.put("View_scrollbarStyle", array.getInt(sortedAttrs.indexOf(android.R.attr.scrollbarStyle), 0));
1051 json.put("View_scrollbarFadeDuration", array.getInt(sortedAttrs.indexOf(android.R.attr.scrollbarFadeDuration), 0));
1052 json.put("View_scrollbarDefaultDelayBeforeFade", array.getInt(sortedAttrs.indexOf(android.R.attr.scrollbarDefaultDelayBeforeFade), 0));
1053 json.put("View_scrollbarSize", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.scrollbarSize), -1));
1054 json.put("View_scrollbarThumbHorizontal", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.scrollbarThumbHorizontal)), styleName + "_View_scrollbarThumbHorizontal", null));
1055 json.put("View_scrollbarThumbVertical", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.scrollbarThumbVertical)), styleName + "_View_scrollbarThumbVertical", null));
1056 json.put("View_scrollbarTrackHorizontal", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.scrollbarTrackHorizontal)), styleName + "_View_scrollbarTrackHorizontal", null));
1057 json.put("View_scrollbarTrackVertical", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.scrollbarTrackVertical)), styleName + "_View_scrollbarTrackVertical", null));
1058 json.put("View_isScrollContainer", array.getBoolean(sortedAttrs.indexOf(android.R.attr.isScrollContainer), false));
1059 json.put("View_keepScreenOn", array.getBoolean(sortedAttrs.indexOf(android.R.attr.keepScreenOn), false));
1060 json.put("View_filterTouchesWhenObscured", array.getBoolean(sortedAttrs.indexOf(android.R.attr.filterTouchesWhenObscured), false));
1061 json.put("View_nextFocusLeft", array.getResourceId(sortedAttrs.indexOf(android.R.attr.nextFocusLeft), -1));
1062 json.put("View_nextFocusRight", array.getResourceId(sortedAttrs.indexOf(android.R.attr.nextFocusRight), -1));
1063 json.put("View_nextFocusUp", array.getResourceId(sortedAttrs.indexOf(android.R.attr.nextFocusUp), -1));
1064 json.put("View_nextFocusDown", array.getResourceId(sortedAttrs.indexOf(android.R.attr.nextFocusDown), -1));
1065 json.put("View_minWidth", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.minWidth), 0));
1066 json.put("View_minHeight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.minHeight), 0));
1067 json.put("View_onClick", array.getString(sortedAttrs.indexOf(android.R.attr.onClick)));
1068 json.put("View_overScrollMode", array.getInt(sortedAttrs.indexOf(android.R.attr.overScrollMode), 1));
1069 json.put("View_paddingStart", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.paddingStart), 0));
1070 json.put("View_paddingEnd", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.paddingEnd), 0));
1071 array.recycle();
1072 } catch (Exception e) {
1073 e.printStackTrace();
1074 }
1075 }
1076
1077 JSONObject extractTextAppearance(int styleName)
1078 {
1079 return extractTextAppearance(styleName, false);
1080 }
1081
1082 @SuppressLint("ResourceType")
1083 JSONObject extractTextAppearance(int styleName, boolean subStyle)
1084 {
1085 final int[] attributes = new int[]{
1086 android.R.attr.textSize,
1087 android.R.attr.textStyle,
1088 android.R.attr.textColor,
1089 android.R.attr.typeface,
1090 android.R.attr.textAllCaps,
1091 android.R.attr.textColorHint,
1092 android.R.attr.textColorLink,
1093 android.R.attr.textColorHighlight
1094 };
1095 Arrays.sort(attributes);
1096 TypedArray array;
1097 if (subStyle)
1098 array = m_theme.obtainStyledAttributes(styleName, attributes);
1099 else
1100 array = obtainStyledAttributes(styleName, attributes);
1101 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1102 JSONObject json = new JSONObject();
1103 try {
1104 int attr = sortedAttrs.indexOf(android.R.attr.textSize);
1105 if (array.hasValue(attr))
1106 json.put("TextAppearance_textSize", array.getDimensionPixelSize(attr, 15));
1107 attr = sortedAttrs.indexOf(android.R.attr.textStyle);
1108 if (array.hasValue(attr))
1109 json.put("TextAppearance_textStyle", array.getInt(attr, -1));
1110 ColorStateList color = array.getColorStateList(sortedAttrs.indexOf(android.R.attr.textColor));
1111 if (color != null)
1112 json.put("TextAppearance_textColor", getColorStateList(color));
1113 attr = sortedAttrs.indexOf(android.R.attr.typeface);
1114 if (array.hasValue(attr))
1115 json.put("TextAppearance_typeface", array.getInt(attr, -1));
1116 attr = sortedAttrs.indexOf(android.R.attr.textAllCaps);
1117 if (array.hasValue(attr))
1118 json.put("TextAppearance_textAllCaps", array.getBoolean(attr, false));
1119 color = array.getColorStateList(sortedAttrs.indexOf(android.R.attr.textColorHint));
1120 if (color != null)
1121 json.put("TextAppearance_textColorHint", getColorStateList(color));
1122 color = array.getColorStateList(sortedAttrs.indexOf(android.R.attr.textColorLink));
1123 if (color != null)
1124 json.put("TextAppearance_textColorLink", getColorStateList(color));
1125 attr = sortedAttrs.indexOf(android.R.attr.textColorHighlight);
1126 if (array.hasValue(attr))
1127 json.put("TextAppearance_textColorHighlight", array.getColor(attr, 0));
1128 array.recycle();
1129 } catch (Exception e) {
1130 e.printStackTrace();
1131 }
1132 return json;
1133 }
1134
1135 JSONObject extractTextAppearanceInformation(int styleName, String qtClass) {
1136 return extractTextAppearanceInformation(styleName, qtClass, android.R.attr.textAppearance, null);
1137 }
1138
1139 JSONObject extractTextAppearanceInformation(int styleName, String qtClass, int textAppearance, AttributeSet attributeSet) {
1140 JSONObject json = new JSONObject();
1141 extractViewInformation(styleName, json, qtClass, attributeSet);
1142
1143 if (textAppearance == -1)
1144 textAppearance = android.R.attr.textAppearance;
1145
1146 try {
1147 TypedValue typedValue = new TypedValue();
1148 Context ctx = new ContextThemeWrapper(m_context, m_theme);
1149 ctx.getTheme().resolveAttribute(styleName, typedValue, true);
1150
1151 // Get textAppearance values
1152 int[] textAppearanceAttr = new int[]{textAppearance};
1153 TypedArray textAppearanceArray = ctx.obtainStyledAttributes(typedValue.data, textAppearanceAttr);
1154 int textAppearanceId = textAppearanceArray.getResourceId(0, -1);
1155 textAppearanceArray.recycle();
1156
1157 int textSize = 15;
1158 int styleIndex = -1;
1159 int typefaceIndex = -1;
1160 int textColorHighlight = 0;
1161 boolean allCaps = false;
1162
1163 if (textAppearanceId != -1) {
1164 int[] attributes = new int[]{
1165 android.R.attr.textSize,
1166 android.R.attr.textStyle,
1167 android.R.attr.typeface,
1168 android.R.attr.textAllCaps,
1169 android.R.attr.textColorHighlight
1170 };
1171 Arrays.sort(attributes);
1172 TypedArray array = m_theme.obtainStyledAttributes(textAppearanceId, attributes);
1173 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1174
1175 textSize = array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.textSize), 15);
1176 styleIndex = array.getInt(sortedAttrs.indexOf(android.R.attr.textStyle), -1);
1177 typefaceIndex = array.getInt(sortedAttrs.indexOf(android.R.attr.typeface), -1);
1178 textColorHighlight = array.getColor(sortedAttrs.indexOf(android.R.attr.textColorHighlight), 0);
1179 allCaps = array.getBoolean(sortedAttrs.indexOf(android.R.attr.textAllCaps), false);
1180 array.recycle();
1181 }
1182 // Get TextView values
1183 int[] attributes = new int[]{
1184 android.R.attr.editable,
1185 android.R.attr.inputMethod,
1186 android.R.attr.numeric,
1187 android.R.attr.digits,
1188 android.R.attr.phoneNumber,
1189 android.R.attr.autoText,
1190 android.R.attr.capitalize,
1191 android.R.attr.bufferType,
1192 android.R.attr.selectAllOnFocus,
1193 android.R.attr.autoLink,
1194 android.R.attr.linksClickable,
1195 android.R.attr.drawableLeft,
1196 android.R.attr.drawableTop,
1197 android.R.attr.drawableRight,
1198 android.R.attr.drawableBottom,
1199 android.R.attr.drawableStart,
1200 android.R.attr.drawableEnd,
1201 android.R.attr.maxLines,
1202 android.R.attr.drawablePadding,
1203 android.R.attr.textCursorDrawable,
1204 android.R.attr.maxHeight,
1205 android.R.attr.lines,
1206 android.R.attr.height,
1207 android.R.attr.minLines,
1208 android.R.attr.minHeight,
1209 android.R.attr.maxEms,
1210 android.R.attr.maxWidth,
1211 android.R.attr.ems,
1212 android.R.attr.width,
1213 android.R.attr.minEms,
1214 android.R.attr.minWidth,
1215 android.R.attr.gravity,
1216 android.R.attr.hint,
1217 android.R.attr.text,
1218 android.R.attr.scrollHorizontally,
1219 android.R.attr.singleLine,
1220 android.R.attr.ellipsize,
1221 android.R.attr.marqueeRepeatLimit,
1222 android.R.attr.includeFontPadding,
1223 android.R.attr.cursorVisible,
1224 android.R.attr.maxLength,
1225 android.R.attr.textScaleX,
1226 android.R.attr.freezesText,
1227 android.R.attr.shadowColor,
1228 android.R.attr.shadowDx,
1229 android.R.attr.shadowDy,
1230 android.R.attr.shadowRadius,
1231 android.R.attr.enabled,
1232 android.R.attr.textColorHighlight,
1233 android.R.attr.textColor,
1234 android.R.attr.textColorHint,
1235 android.R.attr.textColorLink,
1236 android.R.attr.textSize,
1237 android.R.attr.typeface,
1238 android.R.attr.textStyle,
1239 android.R.attr.password,
1240 android.R.attr.lineSpacingExtra,
1241 android.R.attr.lineSpacingMultiplier,
1242 android.R.attr.inputType,
1243 android.R.attr.imeOptions,
1244 android.R.attr.imeActionLabel,
1245 android.R.attr.imeActionId,
1246 android.R.attr.privateImeOptions,
1247 android.R.attr.textSelectHandleLeft,
1248 android.R.attr.textSelectHandleRight,
1249 android.R.attr.textSelectHandle,
1250 android.R.attr.textIsSelectable,
1251 android.R.attr.textAllCaps
1252 };
1253
1254 // The array must be sorted in ascending order, otherwise obtainStyledAttributes()
1255 // might fail to find some attributes
1256 Arrays.sort(attributes);
1257 TypedArray array = ctx.obtainStyledAttributes(typedValue.data, attributes);
1258 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1259
1260 textSize = array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.textSize), textSize);
1261 styleIndex = array.getInt(sortedAttrs.indexOf(android.R.attr.textStyle), styleIndex);
1262 typefaceIndex = array.getInt(sortedAttrs.indexOf(android.R.attr.typeface), typefaceIndex);
1263 textColorHighlight = array.getColor(sortedAttrs.indexOf(android.R.attr.textColorHighlight), textColorHighlight);
1264 allCaps = array.getBoolean(sortedAttrs.indexOf(android.R.attr.textAllCaps), allCaps);
1265
1266 ColorStateList textColor = array.getColorStateList(sortedAttrs.indexOf(android.R.attr.textColor));
1267 ColorStateList textColorHint = array.getColorStateList(sortedAttrs.indexOf(android.R.attr.textColorHint));
1268 ColorStateList textColorLink = array.getColorStateList(sortedAttrs.indexOf(android.R.attr.textColorLink));
1269
1270 json.put("TextAppearance_textSize", textSize);
1271 json.put("TextAppearance_textStyle", styleIndex);
1272 json.put("TextAppearance_typeface", typefaceIndex);
1273 json.put("TextAppearance_textColorHighlight", textColorHighlight);
1274 json.put("TextAppearance_textAllCaps", allCaps);
1275 if (textColor != null)
1276 json.put("TextAppearance_textColor", getColorStateList(textColor));
1277 if (textColorHint != null)
1278 json.put("TextAppearance_textColorHint", getColorStateList(textColorHint));
1279 if (textColorLink != null)
1280 json.put("TextAppearance_textColorLink", getColorStateList(textColorLink));
1281
1282 json.put("TextView_editable", array.getBoolean(sortedAttrs.indexOf(android.R.attr.editable), false));
1283 json.put("TextView_inputMethod", array.getText(sortedAttrs.indexOf(android.R.attr.inputMethod)));
1284 json.put("TextView_numeric", array.getInt(sortedAttrs.indexOf(android.R.attr.numeric), 0));
1285 json.put("TextView_digits", array.getText(sortedAttrs.indexOf(android.R.attr.digits)));
1286 json.put("TextView_phoneNumber", array.getBoolean(sortedAttrs.indexOf(android.R.attr.phoneNumber), false));
1287 json.put("TextView_autoText", array.getBoolean(sortedAttrs.indexOf(android.R.attr.autoText), false));
1288 json.put("TextView_capitalize", array.getInt(sortedAttrs.indexOf(android.R.attr.capitalize), -1));
1289 json.put("TextView_bufferType", array.getInt(sortedAttrs.indexOf(android.R.attr.bufferType), 0));
1290 json.put("TextView_selectAllOnFocus", array.getBoolean(sortedAttrs.indexOf(android.R.attr.selectAllOnFocus), false));
1291 json.put("TextView_autoLink", array.getInt(sortedAttrs.indexOf(android.R.attr.autoLink), 0));
1292 json.put("TextView_linksClickable", array.getBoolean(sortedAttrs.indexOf(android.R.attr.linksClickable), true));
1293 json.put("TextView_drawableLeft", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.drawableLeft)), styleName + "_TextView_drawableLeft", null));
1294 json.put("TextView_drawableTop", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.drawableTop)), styleName + "_TextView_drawableTop", null));
1295 json.put("TextView_drawableRight", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.drawableRight)), styleName + "_TextView_drawableRight", null));
1296 json.put("TextView_drawableBottom", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.drawableBottom)), styleName + "_TextView_drawableBottom", null));
1297 json.put("TextView_drawableStart", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.drawableStart)), styleName + "_TextView_drawableStart", null));
1298 json.put("TextView_drawableEnd", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.drawableEnd)), styleName + "_TextView_drawableEnd", null));
1299 json.put("TextView_maxLines", array.getInt(sortedAttrs.indexOf(android.R.attr.maxLines), -1));
1300 json.put("TextView_drawablePadding", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.drawablePadding), 0));
1301
1302 try {
1303 json.put("TextView_textCursorDrawable", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.textCursorDrawable)), styleName + "_TextView_textCursorDrawable", null));
1304 } catch (Exception e_) {
1305 json.put("TextView_textCursorDrawable", getDrawable(m_context.getResources().getDrawable(array.getResourceId(sortedAttrs.indexOf(android.R.attr.textCursorDrawable), 0), m_theme), styleName + "_TextView_textCursorDrawable", null));
1306 }
1307
1308 json.put("TextView_maxLines", array.getInt(sortedAttrs.indexOf(android.R.attr.maxLines), -1));
1309 json.put("TextView_maxHeight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.maxHeight), -1));
1310 json.put("TextView_lines", array.getInt(sortedAttrs.indexOf(android.R.attr.lines), -1));
1311 json.put("TextView_height", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.height), -1));
1312 json.put("TextView_minLines", array.getInt(sortedAttrs.indexOf(android.R.attr.minLines), -1));
1313 json.put("TextView_minHeight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.minHeight), -1));
1314 json.put("TextView_maxEms", array.getInt(sortedAttrs.indexOf(android.R.attr.maxEms), -1));
1315 json.put("TextView_maxWidth", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.maxWidth), -1));
1316 json.put("TextView_ems", array.getInt(sortedAttrs.indexOf(android.R.attr.ems), -1));
1317 json.put("TextView_width", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.width), -1));
1318 json.put("TextView_minEms", array.getInt(sortedAttrs.indexOf(android.R.attr.minEms), -1));
1319 json.put("TextView_minWidth", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.minWidth), -1));
1320 json.put("TextView_gravity", array.getInt(sortedAttrs.indexOf(android.R.attr.gravity), -1));
1321 json.put("TextView_hint", array.getText(sortedAttrs.indexOf(android.R.attr.hint)));
1322 json.put("TextView_text", array.getText(sortedAttrs.indexOf(android.R.attr.text)));
1323 json.put("TextView_scrollHorizontally", array.getBoolean(sortedAttrs.indexOf(android.R.attr.scrollHorizontally), false));
1324 json.put("TextView_singleLine", array.getBoolean(sortedAttrs.indexOf(android.R.attr.singleLine), false));
1325 json.put("TextView_ellipsize", array.getInt(sortedAttrs.indexOf(android.R.attr.ellipsize), -1));
1326 json.put("TextView_marqueeRepeatLimit", array.getInt(sortedAttrs.indexOf(android.R.attr.marqueeRepeatLimit), 3));
1327 json.put("TextView_includeFontPadding", array.getBoolean(sortedAttrs.indexOf(android.R.attr.includeFontPadding), true));
1328 json.put("TextView_cursorVisible", array.getBoolean(sortedAttrs.indexOf(android.R.attr.maxLength), true));
1329 json.put("TextView_maxLength", array.getInt(sortedAttrs.indexOf(android.R.attr.maxLength), -1));
1330 json.put("TextView_textScaleX", array.getFloat(sortedAttrs.indexOf(android.R.attr.textScaleX), 1.0f));
1331 json.put("TextView_freezesText", array.getBoolean(sortedAttrs.indexOf(android.R.attr.freezesText), false));
1332 json.put("TextView_shadowColor", array.getInt(sortedAttrs.indexOf(android.R.attr.shadowColor), 0));
1333 json.put("TextView_shadowDx", array.getFloat(sortedAttrs.indexOf(android.R.attr.shadowDx), 0));
1334 json.put("TextView_shadowDy", array.getFloat(sortedAttrs.indexOf(android.R.attr.shadowDy), 0));
1335 json.put("TextView_shadowRadius", array.getFloat(sortedAttrs.indexOf(android.R.attr.shadowRadius), 0));
1336 json.put("TextView_enabled", array.getBoolean(sortedAttrs.indexOf(android.R.attr.enabled), true));
1337 json.put("TextView_password", array.getBoolean(sortedAttrs.indexOf(android.R.attr.password), false));
1338 json.put("TextView_lineSpacingExtra", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.lineSpacingExtra), 0));
1339 json.put("TextView_lineSpacingMultiplier", array.getFloat(sortedAttrs.indexOf(android.R.attr.lineSpacingMultiplier), 1.0f));
1340 json.put("TextView_inputType", array.getInt(sortedAttrs.indexOf(android.R.attr.inputType), EditorInfo.TYPE_NULL));
1341 json.put("TextView_imeOptions", array.getInt(sortedAttrs.indexOf(android.R.attr.imeOptions), EditorInfo.IME_NULL));
1342 json.put("TextView_imeActionLabel", array.getText(sortedAttrs.indexOf(android.R.attr.imeActionLabel)));
1343 json.put("TextView_imeActionId", array.getInt(sortedAttrs.indexOf(android.R.attr.imeActionId), 0));
1344 json.put("TextView_privateImeOptions", array.getString(sortedAttrs.indexOf(android.R.attr.privateImeOptions)));
1345
1346 try {
1347 json.put("TextView_textSelectHandleLeft", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.textSelectHandleLeft)), styleName + "_TextView_textSelectHandleLeft", null));
1348 } catch (Exception _e) {
1349 json.put("TextView_textSelectHandleLeft", getDrawable(m_context.getResources().getDrawable(array.getResourceId(sortedAttrs.indexOf(android.R.attr.textSelectHandleLeft), 0), m_theme), styleName + "_TextView_textSelectHandleLeft", null));
1350 }
1351
1352 try {
1353 json.put("TextView_textSelectHandleRight", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.textSelectHandleRight)), styleName + "_TextView_textSelectHandleRight", null));
1354 } catch (Exception _e) {
1355 json.put("TextView_textSelectHandleRight", getDrawable(m_context.getResources().getDrawable(array.getResourceId(sortedAttrs.indexOf(android.R.attr.textSelectHandleRight), 0), m_theme), styleName + "_TextView_textSelectHandleRight", null));
1356 }
1357
1358 try {
1359 json.put("TextView_textSelectHandle", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.textSelectHandle)), styleName + "_TextView_textSelectHandle", null));
1360 } catch (Exception _e) {
1361 json.put("TextView_textSelectHandle", getDrawable(m_context.getResources().getDrawable(array.getResourceId(sortedAttrs.indexOf(android.R.attr.textSelectHandle), 0), m_theme), styleName + "_TextView_textSelectHandle", null));
1362 }
1363 json.put("TextView_textIsSelectable", array.getBoolean(sortedAttrs.indexOf(android.R.attr.textIsSelectable), false));
1364 array.recycle();
1365 } catch (Exception e) {
1366 e.printStackTrace();
1367 }
1368 return json;
1369 }
1370
1371 JSONObject extractImageViewInformation(int styleName, String qtClassName) {
1372 JSONObject json = new JSONObject();
1373 try {
1374 extractViewInformation(styleName, json, qtClassName);
1375
1376 int[] attributes = new int[]{
1377 android.R.attr.src,
1378 android.R.attr.baselineAlignBottom,
1379 android.R.attr.adjustViewBounds,
1380 android.R.attr.maxWidth,
1381 android.R.attr.maxHeight,
1382 android.R.attr.scaleType,
1383 android.R.attr.cropToPadding,
1384 android.R.attr.tint
1385
1386 };
1387 Arrays.sort(attributes);
1388 TypedArray array = obtainStyledAttributes(styleName, attributes);
1389 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1390
1391 Drawable drawable = array.getDrawable(sortedAttrs.indexOf(android.R.attr.src));
1392 if (drawable != null)
1393 json.put("ImageView_src", getDrawable(drawable, styleName + "_ImageView_src", null));
1394
1395 json.put("ImageView_baselineAlignBottom", array.getBoolean(sortedAttrs.indexOf(android.R.attr.baselineAlignBottom), false));
1396 json.put("ImageView_adjustViewBounds", array.getBoolean(sortedAttrs.indexOf(android.R.attr.baselineAlignBottom), false));
1397 json.put("ImageView_maxWidth", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.maxWidth), Integer.MAX_VALUE));
1398 json.put("ImageView_maxHeight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.maxHeight), Integer.MAX_VALUE));
1399 int index = array.getInt(sortedAttrs.indexOf(android.R.attr.scaleType), -1);
1400 if (index >= 0)
1401 json.put("ImageView_scaleType", sScaleTypeArray[index]);
1402
1403 int tint = array.getInt(sortedAttrs.indexOf(android.R.attr.tint), 0);
1404 if (tint != 0)
1405 json.put("ImageView_tint", tint);
1406
1407 json.put("ImageView_cropToPadding", array.getBoolean(sortedAttrs.indexOf(android.R.attr.cropToPadding), false));
1408 array.recycle();
1409 } catch (Exception e) {
1410 e.printStackTrace();
1411 }
1412 return json;
1413 }
1414
1415 void extractCompoundButton(SimpleJsonWriter jsonWriter, int styleName, String className, String qtClass) {
1416 JSONObject json = extractTextAppearanceInformation(styleName, qtClass);
1417
1418 TypedValue typedValue = new TypedValue();
1419 Context ctx = new ContextThemeWrapper(m_context, m_theme);
1420 ctx.getTheme().resolveAttribute(styleName, typedValue, true);
1421 final int[] attributes = new int[]{android.R.attr.button};
1422 TypedArray array = ctx.obtainStyledAttributes(typedValue.data, attributes);
1423 Drawable drawable = array.getDrawable(0);
1424 array.recycle();
1425
1426 try {
1427 if (drawable != null)
1428 json.put("CompoundButton_button", getDrawable(drawable, styleName + "_CompoundButton_button", null));
1429 jsonWriter.name(className).value(json);
1430 } catch (Exception e) {
1431 e.printStackTrace();
1432 }
1433 }
1434
1435 void extractProgressBarInfo(JSONObject json, int styleName) {
1436 try {
1437 final int[] attributes = new int[]{
1438 android.R.attr.minWidth,
1439 android.R.attr.maxWidth,
1440 android.R.attr.minHeight,
1441 android.R.attr.maxHeight,
1442 android.R.attr.indeterminateDuration,
1443 android.R.attr.progressDrawable,
1444 android.R.attr.indeterminateDrawable
1445 };
1446
1447 // The array must be sorted in ascending order, otherwise obtainStyledAttributes()
1448 // might fail to find some attributes
1449 Arrays.sort(attributes);
1450 TypedArray array = obtainStyledAttributes(styleName, attributes);
1451 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1452
1453 json.put("ProgressBar_indeterminateDuration", array.getInt(sortedAttrs.indexOf(android.R.attr.indeterminateDuration), 4000));
1454 json.put("ProgressBar_minWidth", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.minWidth), 24));
1455 json.put("ProgressBar_maxWidth", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.maxWidth), 48));
1456 json.put("ProgressBar_minHeight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.minHeight), 24));
1457 json.put("ProgressBar_maxHeight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.maxHeight), 28));
1458 json.put("ProgressBar_progress_id", android.R.id.progress);
1459 json.put("ProgressBar_secondaryProgress_id", android.R.id.secondaryProgress);
1460
1461 Drawable drawable = array.getDrawable(sortedAttrs.indexOf(android.R.attr.progressDrawable));
1462 if (drawable != null)
1463 json.put("ProgressBar_progressDrawable", getDrawable(drawable,
1464 styleName + "_ProgressBar_progressDrawable", null));
1465
1466 drawable = array.getDrawable(sortedAttrs.indexOf(android.R.attr.indeterminateDrawable));
1467 if (drawable != null)
1468 json.put("ProgressBar_indeterminateDrawable", getDrawable(drawable,
1469 styleName + "_ProgressBar_indeterminateDrawable", null));
1470
1471 array.recycle();
1472 } catch (Exception e) {
1473 e.printStackTrace();
1474 }
1475 }
1476
1477 void extractProgressBar(SimpleJsonWriter writer, int styleName, String className, String qtClass) {
1478 JSONObject json = extractTextAppearanceInformation(android.R.attr.progressBarStyle, qtClass);
1479 try {
1480 extractProgressBarInfo(json, styleName);
1481 writer.name(className).value(json);
1482 } catch (Exception e) {
1483 e.printStackTrace();
1484 }
1485 }
1486
1487 void extractAbsSeekBar(SimpleJsonWriter jsonWriter) {
1488 JSONObject json = extractTextAppearanceInformation(android.R.attr.seekBarStyle, "QSlider");
1489 extractProgressBarInfo(json, android.R.attr.seekBarStyle);
1490 try {
1491 int[] attributes = new int[]{
1492 android.R.attr.thumb,
1493 android.R.attr.thumbOffset
1494 };
1495 Arrays.sort(attributes);
1496 TypedArray array = obtainStyledAttributes(android.R.attr.seekBarStyle, attributes);
1497 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1498
1499 Drawable d = array.getDrawable(sortedAttrs.indexOf(android.R.attr.thumb));
1500 if (d != null)
1501 json.put("SeekBar_thumb", getDrawable(d, android.R.attr.seekBarStyle + "_SeekBar_thumb", null));
1502 json.put("SeekBar_thumbOffset", array.getDimensionPixelOffset(sortedAttrs.indexOf(android.R.attr.thumbOffset), -1));
1503 array.recycle();
1504 jsonWriter.name("seekBarStyle").value(json);
1505 } catch (Exception e) {
1506 e.printStackTrace();
1507 }
1508 }
1509
1510 void extractSwitch(SimpleJsonWriter jsonWriter) {
1511 JSONObject json = new JSONObject();
1512 try {
1513 int[] attributes = new int[]{
1514 android.R.attr.thumb,
1515 android.R.attr.track,
1516 android.R.attr.switchTextAppearance,
1517 android.R.attr.textOn,
1518 android.R.attr.textOff,
1519 android.R.attr.switchMinWidth,
1520 android.R.attr.switchPadding,
1521 android.R.attr.thumbTextPadding,
1522 android.R.attr.showText,
1523 android.R.attr.splitTrack
1524 };
1525 Arrays.sort(attributes);
1526 TypedArray array = obtainStyledAttributes(android.R.attr.switchStyle, attributes);
1527 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1528
1529 Drawable thumb = array.getDrawable(sortedAttrs.indexOf(android.R.attr.thumb));
1530 if (thumb != null)
1531 json.put("Switch_thumb", getDrawable(thumb, android.R.attr.switchStyle + "_Switch_thumb", null));
1532
1533 Drawable track = array.getDrawable(sortedAttrs.indexOf(android.R.attr.track));
1534 if (track != null)
1535 json.put("Switch_track", getDrawable(track, android.R.attr.switchStyle + "_Switch_track", null));
1536
1537 json.put("Switch_textOn", array.getText(sortedAttrs.indexOf(android.R.attr.textOn)));
1538 json.put("Switch_textOff", array.getText(sortedAttrs.indexOf(android.R.attr.textOff)));
1539 json.put("Switch_switchMinWidth", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.switchMinWidth), 0));
1540 json.put("Switch_switchPadding", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.switchPadding), 0));
1541 json.put("Switch_thumbTextPadding", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.thumbTextPadding), 0));
1542 json.put("Switch_showText", array.getBoolean(sortedAttrs.indexOf(android.R.attr.showText), true));
1543 json.put("Switch_splitTrack", array.getBoolean(sortedAttrs.indexOf(android.R.attr.splitTrack), false));
1544
1545 // Get textAppearance values
1546 final int textAppearanceId = array.getResourceId(sortedAttrs.indexOf(android.R.attr.switchTextAppearance), -1);
1547 json.put("Switch_switchTextAppearance", extractTextAppearance(textAppearanceId, true));
1548
1549 array.recycle();
1550 jsonWriter.name("switchStyle").value(json);
1551 } catch (Exception e) {
1552 e.printStackTrace();
1553 }
1554 }
1555
1556 JSONObject extractCheckedTextView(String itemName) {
1557 JSONObject json = extractTextAppearanceInformation(android.R.attr.checkedTextViewStyle, itemName);
1558 try {
1559 int[] attributes = new int[]{
1560 android.R.attr.checkMark,
1561 };
1562
1563 Arrays.sort(attributes);
1564 TypedArray array = obtainStyledAttributes(android.R.attr.switchStyle, attributes);
1565 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1566
1567 Drawable drawable = array.getDrawable(sortedAttrs.indexOf(android.R.attr.checkMark));
1568 if (drawable != null)
1569 json.put("CheckedTextView_checkMark", getDrawable(drawable, itemName + "_CheckedTextView_checkMark", null));
1570 array.recycle();
1571 } catch (Exception e) {
1572 e.printStackTrace();
1573 }
1574 return json;
1575 }
1576
1577 private JSONObject extractItemStyle(int resourceId, String itemName)
1578 {
1579 try {
1580 XmlResourceParser parser = m_context.getResources().getLayout(resourceId);
1581 int type = parser.next();
1582 while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT)
1583 type = parser.next();
1584
1585 if (type != XmlPullParser.START_TAG)
1586 return null;
1587
1588 AttributeSet attributes = Xml.asAttributeSet(parser);
1589 String name = parser.getName();
1590 if (name.equals("TextView"))
1591 return extractTextAppearanceInformation(android.R.attr.textViewStyle, itemName, android.R.attr.textAppearanceListItem, attributes);
1592 else if (name.equals("CheckedTextView"))
1593 return extractCheckedTextView(itemName);
1594 } catch (Exception e) {
1595 e.printStackTrace();
1596 }
1597 return null;
1598 }
1599
1600 private void extractItemsStyle(SimpleJsonWriter jsonWriter) {
1601 try {
1602 JSONObject itemStyle = extractItemStyle(android.R.layout.simple_list_item_1, "simple_list_item");
1603 if (itemStyle != null)
1604 jsonWriter.name("simple_list_item").value(itemStyle);
1605 itemStyle = extractItemStyle(android.R.layout.simple_list_item_checked, "simple_list_item_checked");
1606 if (itemStyle != null)
1607 jsonWriter.name("simple_list_item_checked").value(itemStyle);
1608 itemStyle = extractItemStyle(android.R.layout.simple_list_item_multiple_choice, "simple_list_item_multiple_choice");
1609 if (itemStyle != null)
1610 jsonWriter.name("simple_list_item_multiple_choice").value(itemStyle);
1611 itemStyle = extractItemStyle(android.R.layout.simple_list_item_single_choice, "simple_list_item_single_choice");
1612 if (itemStyle != null)
1613 jsonWriter.name("simple_list_item_single_choice").value(itemStyle);
1614 itemStyle = extractItemStyle(android.R.layout.simple_spinner_item, "simple_spinner_item");
1615 if (itemStyle != null)
1616 jsonWriter.name("simple_spinner_item").value(itemStyle);
1617 itemStyle = extractItemStyle(android.R.layout.simple_spinner_dropdown_item, "simple_spinner_dropdown_item");
1618 if (itemStyle != null)
1619 jsonWriter.name("simple_spinner_dropdown_item").value(itemStyle);
1620 itemStyle = extractItemStyle(android.R.layout.simple_dropdown_item_1line, "simple_dropdown_item_1line");
1621 if (itemStyle != null)
1622 jsonWriter.name("simple_dropdown_item_1line").value(itemStyle);
1623 itemStyle = extractItemStyle(android.R.layout.simple_selectable_list_item, "simple_selectable_list_item");
1624 if (itemStyle != null)
1625 jsonWriter.name("simple_selectable_list_item").value(itemStyle);
1626 } catch (Exception e) {
1627 e.printStackTrace();
1628 }
1629 }
1630
1631 void extractListView(SimpleJsonWriter writer) {
1632 JSONObject json = extractTextAppearanceInformation(android.R.attr.listViewStyle, "QListView");
1633 try {
1634 int[] attributes = new int[]{
1635 android.R.attr.divider,
1636 android.R.attr.dividerHeight
1637 };
1638 Arrays.sort(attributes);
1639 TypedArray array = obtainStyledAttributes(android.R.attr.listViewStyle, attributes);
1640 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1641
1642 Drawable divider = array.getDrawable(sortedAttrs.indexOf(android.R.attr.divider));
1643 if (divider != null)
1644 json.put("ListView_divider", getDrawable(divider, android.R.attr.listViewStyle + "_ListView_divider", null));
1645
1646 json.put("ListView_dividerHeight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.dividerHeight), 0));
1647
1648 array.recycle();
1649 writer.name("listViewStyle").value(json);
1650 } catch (Exception e) {
1651 e.printStackTrace();
1652 }
1653 }
1654
1655 void extractCalendar(SimpleJsonWriter writer) {
1656 JSONObject json = extractTextAppearanceInformation(android.R.attr.calendarViewStyle, "QCalendarWidget");
1657 try {
1658 int[] attributes = new int[]{
1659 android.R.attr.firstDayOfWeek,
1660 android.R.attr.focusedMonthDateColor,
1661 android.R.attr.selectedWeekBackgroundColor,
1662 android.R.attr.showWeekNumber,
1663 android.R.attr.shownWeekCount,
1664 android.R.attr.unfocusedMonthDateColor,
1665 android.R.attr.weekNumberColor,
1666 android.R.attr.weekSeparatorLineColor,
1667 android.R.attr.selectedDateVerticalBar,
1668 android.R.attr.dateTextAppearance,
1669 android.R.attr.weekDayTextAppearance
1670 };
1671 Arrays.sort(attributes);
1672 TypedArray array = obtainStyledAttributes(android.R.attr.calendarViewStyle, attributes);
1673 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1674
1675 Drawable d = array.getDrawable(sortedAttrs.indexOf(android.R.attr.selectedDateVerticalBar));
1676 if (d != null)
1677 json.put("CalendarView_selectedDateVerticalBar", getDrawable(d, android.R.attr.calendarViewStyle + "_CalendarView_selectedDateVerticalBar", null));
1678
1679 int textAppearanceId = array.getResourceId(sortedAttrs.indexOf(android.R.attr.dateTextAppearance), -1);
1680 json.put("CalendarView_dateTextAppearance", extractTextAppearance(textAppearanceId, true));
1681 textAppearanceId = array.getResourceId(sortedAttrs.indexOf(android.R.attr.weekDayTextAppearance), -1);
1682 json.put("CalendarView_weekDayTextAppearance", extractTextAppearance(textAppearanceId, true));
1683
1684
1685 json.put("CalendarView_firstDayOfWeek", array.getInt(sortedAttrs.indexOf(android.R.attr.firstDayOfWeek), 0));
1686 json.put("CalendarView_focusedMonthDateColor", array.getColor(sortedAttrs.indexOf(android.R.attr.focusedMonthDateColor), 0));
1687 json.put("CalendarView_selectedWeekBackgroundColor", array.getColor(sortedAttrs.indexOf(android.R.attr.selectedWeekBackgroundColor), 0));
1688 json.put("CalendarView_showWeekNumber", array.getBoolean(sortedAttrs.indexOf(android.R.attr.showWeekNumber), true));
1689 json.put("CalendarView_shownWeekCount", array.getInt(sortedAttrs.indexOf(android.R.attr.shownWeekCount), 6));
1690 json.put("CalendarView_unfocusedMonthDateColor", array.getColor(sortedAttrs.indexOf(android.R.attr.unfocusedMonthDateColor), 0));
1691 json.put("CalendarView_weekNumberColor", array.getColor(sortedAttrs.indexOf(android.R.attr.weekNumberColor), 0));
1692 json.put("CalendarView_weekSeparatorLineColor", array.getColor(sortedAttrs.indexOf(android.R.attr.weekSeparatorLineColor), 0));
1693 array.recycle();
1694 writer.name("calendarViewStyle").value(json);
1695 } catch (Exception e) {
1696 e.printStackTrace();
1697 }
1698 }
1699
1700 void extractToolBar(SimpleJsonWriter writer) {
1701 JSONObject json = extractTextAppearanceInformation(android.R.attr.toolbarStyle, "QToolBar");
1702 try {
1703 int[] attributes = new int[]{
1704 android.R.attr.background,
1705 android.R.attr.backgroundStacked,
1706 android.R.attr.backgroundSplit,
1707 android.R.attr.divider,
1708 android.R.attr.itemPadding
1709 };
1710 Arrays.sort(attributes);
1711 TypedArray array = obtainStyledAttributes(android.R.attr.toolbarStyle, attributes);
1712 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1713
1714 Drawable d = array.getDrawable(sortedAttrs.indexOf(android.R.attr.background));
1715 if (d != null)
1716 json.put("ActionBar_background", getDrawable(d, android.R.attr.toolbarStyle + "_ActionBar_background", null));
1717
1718 d = array.getDrawable(sortedAttrs.indexOf(android.R.attr.backgroundStacked));
1719 if (d != null)
1720 json.put("ActionBar_backgroundStacked", getDrawable(d, android.R.attr.toolbarStyle + "_ActionBar_backgroundStacked", null));
1721
1722 d = array.getDrawable(sortedAttrs.indexOf(android.R.attr.backgroundSplit));
1723 if (d != null)
1724 json.put("ActionBar_backgroundSplit", getDrawable(d, android.R.attr.toolbarStyle + "_ActionBar_backgroundSplit", null));
1725
1726 d = array.getDrawable(sortedAttrs.indexOf(android.R.attr.divider));
1727 if (d != null)
1728 json.put("ActionBar_divider", getDrawable(d, android.R.attr.toolbarStyle + "_ActionBar_divider", null));
1729
1730 json.put("ActionBar_itemPadding", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.itemPadding), 0));
1731
1732 array.recycle();
1733 writer.name("actionBarStyle").value(json);
1734 } catch (Exception e) {
1735 e.printStackTrace();
1736 }
1737 }
1738
1739 void extractTabBar(SimpleJsonWriter writer) {
1740 JSONObject json = extractTextAppearanceInformation(android.R.attr.actionBarTabBarStyle, "QTabBar");
1741 try {
1742 int[] attributes = new int[]{
1743 android.R.attr.showDividers,
1744 android.R.attr.dividerPadding,
1745 android.R.attr.divider
1746 };
1747 Arrays.sort(attributes);
1748 TypedArray array = obtainStyledAttributes(android.R.attr.actionBarTabStyle, attributes);
1749 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1750
1751 Drawable d = array.getDrawable(sortedAttrs.indexOf(android.R.attr.divider));
1752 if (d != null)
1753 json.put("LinearLayout_divider", getDrawable(d, android.R.attr.actionBarTabStyle + "_LinearLayout_divider", null));
1754 json.put("LinearLayout_showDividers", array.getInt(sortedAttrs.indexOf(android.R.attr.showDividers), 0));
1755 json.put("LinearLayout_dividerPadding", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.dividerPadding), 0));
1756
1757 array.recycle();
1758 writer.name("actionBarTabBarStyle").value(json);
1759 } catch (Exception e) {
1760 e.printStackTrace();
1761 }
1762 }
1763
1764 private void extractWindow(SimpleJsonWriter writer) {
1765 JSONObject json = new JSONObject();
1766 try {
1767 int[] attributes = new int[]{
1768 android.R.attr.windowBackground,
1769 android.R.attr.windowFrame
1770 };
1771 Arrays.sort(attributes);
1772 TypedArray array = obtainStyledAttributes(android.R.attr.popupWindowStyle, attributes);
1773 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1774
1775 Drawable background = array.getDrawable(sortedAttrs.indexOf(android.R.attr.windowBackground));
1776 if (background != null)
1777 json.put("Window_windowBackground", getDrawable(background, android.R.attr.popupWindowStyle + "_Window_windowBackground", null));
1778
1779 Drawable frame = array.getDrawable(sortedAttrs.indexOf(android.R.attr.windowFrame));
1780 if (frame != null)
1781 json.put("Window_windowFrame", getDrawable(frame, android.R.attr.popupWindowStyle + "_Window_windowFrame", null));
1782 array.recycle();
1783 writer.name("windowStyle").value(json);
1784 } catch (Exception e) {
1785 e.printStackTrace();
1786 }
1787 }
1788
1789 private JSONObject extractDefaultPalette() {
1790 JSONObject json = extractTextAppearance(android.R.attr.textAppearance);
1791 try {
1792 json.put("defaultBackgroundColor", defaultBackgroundColor);
1793 json.put("defaultTextColorPrimary", defaultTextColor);
1794 } catch (Exception e) {
1795 e.printStackTrace();
1796 }
1797 return json;
1798 }
1799
1800 static class SimpleJsonWriter {
1801 private final OutputStreamWriter m_writer;
1802 private boolean m_addComma = false;
1803 private int m_indentLevel = 0;
1804
1805 SimpleJsonWriter(String filePath) throws IOException {
1806 m_writer = new OutputStreamWriter(Files.newOutputStream(Paths.get(filePath)));
1807 }
1808
1809 void close() throws IOException {
1810 m_writer.close();
1811 }
1812
1813 private void writeIndent() throws IOException {
1814 m_writer.write(" ", 0, m_indentLevel);
1815 }
1816
1817 void beginObject() throws IOException {
1818 writeIndent();
1819 m_writer.write("{\n");
1820 ++m_indentLevel;
1821 m_addComma = false;
1822 }
1823
1824 void endObject() throws IOException {
1825 m_writer.write("\n");
1826 writeIndent();
1827 m_writer.write("}\n");
1828 --m_indentLevel;
1829 m_addComma = false;
1830 }
1831
1832 SimpleJsonWriter name(String name) throws IOException {
1833 if (m_addComma) {
1834 m_writer.write(",\n");
1835 }
1836 writeIndent();
1837 m_writer.write(JSONObject.quote(name) + ": ");
1838 m_addComma = true;
1839 return this;
1840 }
1841
1842 void value(JSONObject value) throws IOException {
1843 m_writer.write(value.toString());
1844 }
1845 }
1846
1847 static class DrawableCache {
1848 JSONObject object;
1849 Object drawable;
1850 DrawableCache(JSONObject json, Object drawable) {
1851 object = json;
1852 this.drawable = drawable;
1853 }
1854 }
1855}
PeripheralState state
QPainter Context
static const QString context()
Definition java.cpp:398
QAudioFormat::AudioChannelPosition pos
Q_WIDGETS_EXPORT qreal dpi(const QStyleOption *option)
Orientation
Definition qnamespace.h:104
#define assert
EGLOutputLayerEXT EGLint EGLAttrib value
[3]
EGLConfig config
[3]
const EGLAttrib EGLOutputLayerEXT * layers
GLfloat GLfloat GLfloat w
[0]
GLuint object
[6]
GLboolean GLboolean GLboolean GLboolean a
GLenum type
GLenum GLenum GLsizei count
GLfloat GLfloat f
[26]
GLuint index
GLuint color
[setDefaultFactory]
GLboolean GLuint group
[16]
GLfloat n
GLfloat GLfloat GLfloat GLfloat h
GLenum GLsizei GLsizei GLint * values
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLuint GLfloat * val
GLhandleARB obj
[0]
GLsizei const GLchar *const * path
GLdouble GLdouble t
Definition qopenglext.h:243
GLenum array
GLenum GLsizei len
GLuint * states
EGLContext ctx
decltype(openFileForWriting({})) File
Definition main.cpp:76
static int getInt(QDataStream &stream)
EGLImageKHR EGLint * name
QList< std::pair< QString, QString > > Map
const char className[16]
Definition qwizard.cpp:100
QGraphicsRectItem rect
[3]
QFrame frame
[0]
static void writeIndent(QTextStream &ts, int indent)
Definition xliff.cpp:73