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 if (array == null || pos < 0)
560 return a;
561 final int l = Math.min(pos + len, array.length);
562 for (int i = pos; i < l; i++)
563 a.put(array[i]);
564 return a;
565 }
566
567 private JSONArray getJsonArray(float[] array) throws JSONException {
568 JSONArray a = new JSONArray();
569 if (array != null)
570 for (float val : array)
571 a.put(val);
572 return a;
573 }
574
575 private JSONObject getJsonChunkInfo(int[] chunkData) throws JSONException {
576 JSONObject jsonRect = new JSONObject();
577 if (chunkData == null || chunkData.length < 3)
578 return jsonRect;
579
580 jsonRect.put("xdivs", getJsonArray(chunkData, 3, chunkData[0]));
581 jsonRect.put("ydivs", getJsonArray(chunkData, 3 + chunkData[0], chunkData[1]));
582 jsonRect.put("colors", getJsonArray(chunkData, 3 + chunkData[0] + chunkData[1], chunkData[2]));
583 return jsonRect;
584 }
585
586 private JSONObject findPatchesMarings(Drawable d) throws JSONException, IllegalAccessException {
587 NinePatch np;
588 Field f = tryGetAccessibleField(NinePatchDrawable.class, "mNinePatch");
589 if (f != null) {
590 np = (NinePatch) f.get(d);
591 } else {
592 Object state = getAccessibleField(NinePatchDrawable.class, "mNinePatchState").get(d);
593 np = (NinePatch) getAccessibleField(Objects.requireNonNull(state).getClass(), "mNinePatch").get(state);
594 }
595 return getJsonChunkInfo(extractNativeChunkInfo20(getAccessibleField(Objects.requireNonNull(np).getClass(), "mNativeChunk").getLong(np)));
596 }
597
598 private JSONObject getRippleDrawable(Object drawable, String filename, Rect padding) {
599 JSONObject json = getLayerDrawable(drawable, filename);
600 JSONObject ripple = new JSONObject();
601 try {
602 Class<?> rippleDrawableClass = Class.forName("android.graphics.drawable.RippleDrawable");
603 final Object mState = getAccessibleField(rippleDrawableClass, "mState").get(drawable);
604 ripple.put("mask", getDrawable(getAccessibleField(rippleDrawableClass, "mMask").get(drawable), filename, padding));
605 if (mState != null) {
606 ripple.put("maxRadius", getAccessibleField(mState.getClass(), "mMaxRadius").getInt(mState));
607 ColorStateList color = (ColorStateList) getAccessibleField(mState.getClass(), "mColor").get(mState);
608 if (color != null)
609 ripple.put("color", getColorStateList(color));
610 }
611 json.put("ripple", ripple);
612 } catch (Exception e) {
613 e.printStackTrace();
614 }
615 return json;
616 }
617
618 private HashMap<Long, Long> getStateTransitions(Object sa) throws Exception {
619 HashMap<Long, Long> transitions = new HashMap<>();
620 final int sz = getAccessibleField(sa.getClass(), "mSize").getInt(sa);
621 long[] keys = (long[]) getAccessibleField(sa.getClass(), "mKeys").get(sa);
622 long[] values = (long[]) getAccessibleField(sa.getClass(), "mValues").get(sa);
623 for (int i = 0; i < sz; i++) {
624 if (keys != null && values != null)
625 transitions.put(keys[i], values[i]);
626 }
627 return transitions;
628 }
629
630 private HashMap<Integer, Integer> getStateIds(Object sa) throws Exception {
631 HashMap<Integer, Integer> states = new HashMap<>();
632 final int sz = getAccessibleField(sa.getClass(), "mSize").getInt(sa);
633 int[] keys = (int[]) getAccessibleField(sa.getClass(), "mKeys").get(sa);
634 int[] values = (int[]) getAccessibleField(sa.getClass(), "mValues").get(sa);
635 for (int i = 0; i < sz; i++) {
636 if (keys != null && values != null)
637 states.put(keys[i], values[i]);
638 }
639 return states;
640 }
641
642 private int findStateIndex(int id, HashMap<Integer, Integer> stateIds) {
643 for (Map.Entry<Integer, Integer> s : stateIds.entrySet()) {
644 if (id == s.getValue())
645 return s.getKey();
646 }
647 return -1;
648 }
649
650 private JSONObject getAnimatedStateListDrawable(Object drawable, String filename) {
651 JSONObject json = getStateListDrawable(drawable, filename);
652 try {
653 Class<?> animatedStateListDrawableClass = Class.forName("android.graphics.drawable.AnimatedStateListDrawable");
654 Object state = getAccessibleField(animatedStateListDrawableClass, "mState").get(drawable);
655
656 if (state != null) {
657 Class<?> stateClass = state.getClass();
658 HashMap<Integer, Integer> stateIds = getStateIds(Objects.requireNonNull(getAccessibleField(stateClass, "mStateIds").get(state)));
659 HashMap<Long, Long> transitions = getStateTransitions(Objects.requireNonNull(getAccessibleField(stateClass, "mTransitions").get(state)));
660
661 for (Map.Entry<Long, Long> t : transitions.entrySet()) {
662 final int toState = findStateIndex(t.getKey().intValue(), stateIds);
663 final int fromState = findStateIndex((int) (t.getKey() >> 32), stateIds);
664
665 JSONObject transition = new JSONObject();
666 transition.put("from", fromState);
667 transition.put("to", toState);
668 transition.put("reverse", (t.getValue() >> 32) != 0);
669
670 JSONArray stateslist = json.getJSONArray("stateslist");
671 JSONObject stateobj = stateslist.getJSONObject(t.getValue().intValue());
672 stateobj.put("transition", transition);
673 }
674 }
675 } catch (Exception e) {
676 e.printStackTrace();
677 }
678 return json;
679 }
680
681 private JSONObject getVPath(Object path) throws Exception {
682 JSONObject json = new JSONObject();
683 final Class<?> pathClass = path.getClass();
684 json.put("type", "path");
685 json.put("name", tryGetAccessibleField(pathClass, "mPathName").get(path));
686 Object[] mNodes = (Object[]) tryGetAccessibleField(pathClass, "mNodes").get(path);
687 JSONArray nodes = new JSONArray();
688 if (mNodes != null) {
689 for (Object n : mNodes) {
690 JSONObject node = new JSONObject();
691 node.put("type", String.valueOf(getAccessibleField(n.getClass(), "mType").getChar(n)));
692 node.put("params", getJsonArray((float[]) getAccessibleField(n.getClass(), "mParams").get(n)));
693 nodes.put(node);
694 }
695 json.put("nodes", nodes);
696 }
697 json.put("isClip", pathClass.getMethod("isClipPath").invoke(path));
698
699 if (tryGetAccessibleField(pathClass, "mStrokeColor") == null)
700 return json; // not VFullPath
701
702 json.put("strokeColor", getAccessibleField(pathClass, "mStrokeColor").getInt(path));
703 json.put("strokeWidth", getAccessibleField(pathClass, "mStrokeWidth").getFloat(path));
704 json.put("fillColor", getAccessibleField(pathClass, "mFillColor").getInt(path));
705 json.put("strokeAlpha", getAccessibleField(pathClass, "mStrokeAlpha").getFloat(path));
706 json.put("fillRule", getAccessibleField(pathClass, "mFillRule").getInt(path));
707 json.put("fillAlpha", getAccessibleField(pathClass, "mFillAlpha").getFloat(path));
708 json.put("trimPathStart", getAccessibleField(pathClass, "mTrimPathStart").getFloat(path));
709 json.put("trimPathEnd", getAccessibleField(pathClass, "mTrimPathEnd").getFloat(path));
710 json.put("trimPathOffset", getAccessibleField(pathClass, "mTrimPathOffset").getFloat(path));
711 json.put("strokeLineCap", getAccessibleField(pathClass, "mStrokeLineCap").get(path));
712 json.put("strokeLineJoin", getAccessibleField(pathClass, "mStrokeLineJoin").get(path));
713 json.put("strokeMiterlimit", getAccessibleField(pathClass, "mStrokeMiterlimit").getFloat(path));
714 return json;
715 }
716
717 @SuppressWarnings("unchecked")
718 private JSONObject getVGroup(Object group) throws Exception {
719 JSONObject json = new JSONObject();
720 json.put("type", "group");
721 final Class<?> groupClass = group.getClass();
722 json.put("name", getAccessibleField(groupClass, "mGroupName").get(group));
723 json.put("rotate", getAccessibleField(groupClass, "mRotate").getFloat(group));
724 json.put("pivotX", getAccessibleField(groupClass, "mPivotX").getFloat(group));
725 json.put("pivotY", getAccessibleField(groupClass, "mPivotY").getFloat(group));
726 json.put("scaleX", getAccessibleField(groupClass, "mScaleX").getFloat(group));
727 json.put("scaleY", getAccessibleField(groupClass, "mScaleY").getFloat(group));
728 json.put("translateX", getAccessibleField(groupClass, "mTranslateX").getFloat(group));
729 json.put("translateY", getAccessibleField(groupClass, "mTranslateY").getFloat(group));
730
731 ArrayList<Object> mChildren = (ArrayList<Object>) getAccessibleField(groupClass, "mChildren").get(group);
732 JSONArray children = new JSONArray();
733 if (mChildren != null) {
734 for (Object c : mChildren) {
735 if (groupClass.isInstance(c))
736 children.put(getVGroup(c));
737 else
738 children.put(getVPath(c));
739 }
740 json.put("children", children);
741 }
742 return json;
743 }
744
745 private JSONObject getVectorDrawable(Object drawable) {
746 JSONObject json = new JSONObject();
747 try {
748 json.put("type", "vector");
749 Class<?> vectorDrawableClass = Class.forName("android.graphics.drawable.VectorDrawable");
750 final Object state = getAccessibleField(vectorDrawableClass, "mVectorState").get(drawable);
751 final Class<?> stateClass = Objects.requireNonNull(state).getClass();
752 final ColorStateList mTint = (ColorStateList) getAccessibleField(stateClass, "mTint").get(state);
753 if (mTint != null) {
754 json.put("tintList", getColorStateList(mTint));
755 json.put("tintMode", getAccessibleField(stateClass, "mTintMode").get(state));
756 }
757 final Object mVPathRenderer = getAccessibleField(stateClass, "mVPathRenderer").get(state);
758 final Class<?> VPathRendererClass = Objects.requireNonNull(mVPathRenderer).getClass();
759 json.put("baseWidth", getAccessibleField(VPathRendererClass, "mBaseWidth").getFloat(mVPathRenderer));
760 json.put("baseHeight", getAccessibleField(VPathRendererClass, "mBaseHeight").getFloat(mVPathRenderer));
761 json.put("viewportWidth", getAccessibleField(VPathRendererClass, "mViewportWidth").getFloat(mVPathRenderer));
762 json.put("viewportHeight", getAccessibleField(VPathRendererClass, "mViewportHeight").getFloat(mVPathRenderer));
763 json.put("rootAlpha", getAccessibleField(VPathRendererClass, "mRootAlpha").getInt(mVPathRenderer));
764 json.put("rootName", getAccessibleField(VPathRendererClass, "mRootName").get(mVPathRenderer));
765 json.put("rootGroup", getVGroup(Objects.requireNonNull(getAccessibleField(VPathRendererClass, "mRootGroup").get(mVPathRenderer))));
766 } catch (Exception e) {
767 e.printStackTrace();
768 }
769 return json;
770 }
771
772 JSONObject getDrawable(Object drawable, String filename, Rect padding) {
773 if (drawable == null || m_minimal)
774 return null;
775
776 DrawableCache dc = m_drawableCache.get(filename);
777 if (dc != null) {
778 if (dc.drawable.equals(drawable))
779 return dc.object;
780 else
781 Log.e(QtNative.QtTAG, "Different drawable objects points to the same file name \"" + filename + "\"");
782 }
783 JSONObject json = new JSONObject();
784 Bitmap bmp = null;
785 if (drawable instanceof Bitmap)
786 bmp = (Bitmap) drawable;
787 else {
788 if (drawable instanceof BitmapDrawable) {
789 BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
790 bmp = bitmapDrawable.getBitmap();
791 try {
792 json.put("gravity", bitmapDrawable.getGravity());
793 json.put("tileModeX", bitmapDrawable.getTileModeX());
794 json.put("tileModeY", bitmapDrawable.getTileModeY());
795 json.put("antialias", BitmapDrawable.class.getMethod("hasAntiAlias").invoke(bitmapDrawable));
796 json.put("mipMap", BitmapDrawable.class.getMethod("hasMipMap").invoke(bitmapDrawable));
797 json.put("tintMode", BitmapDrawable.class.getMethod("getTintMode").invoke(bitmapDrawable));
798 ColorStateList tintList = (ColorStateList) BitmapDrawable.class.getMethod("getTint").invoke(bitmapDrawable);
799 if (tintList != null)
800 json.put("tintList", getColorStateList(tintList));
801 } catch (Exception e) {
802 e.printStackTrace();
803 }
804 } else {
805
806 if (drawable instanceof RippleDrawable)
807 return getRippleDrawable(drawable, filename, padding);
808
809 if (drawable instanceof AnimatedStateListDrawable)
810 return getAnimatedStateListDrawable(drawable, filename);
811
812 if (drawable instanceof VectorDrawable)
813 return getVectorDrawable(drawable);
814
815 if (drawable instanceof ScaleDrawable) {
816 return getDrawable(((ScaleDrawable) drawable).getDrawable(), filename, null);
817 }
818 if (drawable instanceof LayerDrawable) {
819 return getLayerDrawable(drawable, filename);
820 }
821 if (drawable instanceof StateListDrawable) {
822 return getStateListDrawable(drawable, filename);
823 }
824 if (drawable instanceof GradientDrawable) {
825 return getGradientDrawable((GradientDrawable) drawable);
826 }
827 if (drawable instanceof RotateDrawable) {
828 return getRotateDrawable((RotateDrawable) drawable, filename);
829 }
830 if (drawable instanceof AnimationDrawable) {
831 return getAnimationDrawable((AnimationDrawable) drawable, filename);
832 }
833 if (drawable instanceof ClipDrawable) {
834 try {
835 json.put("type", "clipDrawable");
836 Drawable.ConstantState dcs = ((ClipDrawable) drawable).getConstantState();
837 json.put("drawable", getDrawable(getAccessibleField(dcs.getClass(), "mDrawable").get(dcs), filename, null));
838 if (null != padding)
839 json.put("padding", getJsonRect(padding));
840 else {
841 Rect _padding = new Rect();
842 if (((Drawable) drawable).getPadding(_padding))
843 json.put("padding", getJsonRect(_padding));
844 }
845 } catch (Exception e) {
846 e.printStackTrace();
847 }
848 return json;
849 }
850 if (drawable instanceof ColorDrawable) {
851 bmp = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
852 Drawable d = (Drawable) drawable;
853 d.setBounds(0, 0, 1, 1);
854 d.draw(new Canvas(bmp));
855 try {
856 json.put("type", "color");
857 json.put("color", bmp.getPixel(0, 0));
858 if (null != padding)
859 json.put("padding", getJsonRect(padding));
860 else {
861 Rect _padding = new Rect();
862 if (d.getPadding(_padding))
863 json.put("padding", getJsonRect(_padding));
864 }
865 } catch (JSONException e) {
866 e.printStackTrace();
867 }
868 return json;
869 }
870 if (drawable instanceof InsetDrawable) {
871 try {
872 InsetDrawable d = (InsetDrawable) drawable;
873 Object mInsetStateObject = getAccessibleField(InsetDrawable.class, "mState").get(d);
874 Rect _padding = new Rect();
875 boolean hasPadding = d.getPadding(_padding);
876 return getDrawable(getAccessibleField(Objects.requireNonNull(mInsetStateObject).getClass(), "mDrawable").get(mInsetStateObject), filename, hasPadding ? _padding : null);
877 } catch (Exception e) {
878 e.printStackTrace();
879 }
880 } else {
881 Drawable d = (Drawable) drawable;
882 int w = d.getIntrinsicWidth();
883 int h = d.getIntrinsicHeight();
884 d.setLevel(10000);
885 if (w < 1 || h < 1) {
886 w = 100;
887 h = 100;
888 }
889 bmp = Bitmap.createBitmap(w, h, Config.ARGB_8888);
890 d.setBounds(0, 0, w, h);
891 d.draw(new Canvas(bmp));
892 if (drawable instanceof NinePatchDrawable) {
893 NinePatchDrawable npd = (NinePatchDrawable) drawable;
894 try {
895 json.put("type", "9patch");
896 json.put("drawable", getDrawable(bmp, filename, null));
897 if (padding != null)
898 json.put("padding", getJsonRect(padding));
899 else {
900 Rect _padding = new Rect();
901 if (npd.getPadding(_padding))
902 json.put("padding", getJsonRect(_padding));
903 }
904
905 json.put("chunkInfo", findPatchesMarings(d));
906 return json;
907 } catch (Exception e) {
908 e.printStackTrace();
909 }
910 }
911 }
912 }
913 }
914 FileOutputStream out;
915 try {
916 filename = m_extractPath + filename + ".png";
917 out = new FileOutputStream(filename);
918 if (bmp != null)
919 bmp.compress(Bitmap.CompressFormat.PNG, 100, out);
920 out.close();
921 } catch (IOException e) {
922 e.printStackTrace();
923 }
924 try {
925 json.put("type", "image");
926 json.put("path", filename);
927 if (bmp != null) {
928 json.put("width", bmp.getWidth());
929 json.put("height", bmp.getHeight());
930 }
931 m_drawableCache.put(filename, new DrawableCache(json, drawable));
932 } catch (JSONException e) {
933 e.printStackTrace();
934 }
935 return json;
936 }
937
938 private TypedArray obtainStyledAttributes(int styleName, int[] attributes)
939 {
940 TypedValue typedValue = new TypedValue();
941 Context ctx = new ContextThemeWrapper(m_context, m_theme);
942 ctx.getTheme().resolveAttribute(styleName, typedValue, true);
943 return ctx.obtainStyledAttributes(typedValue.data, attributes);
944 }
945
946 private ArrayList<Integer> getArrayListFromIntArray(int[] attributes) {
947 ArrayList<Integer> sortedAttrs = new ArrayList<>();
948 for (int attr : attributes)
949 sortedAttrs.add(attr);
950 return sortedAttrs;
951 }
952
953 void extractViewInformation(int styleName, JSONObject json, String qtClassName) {
954 extractViewInformation(styleName, json, qtClassName, null);
955 }
956
957 void extractViewInformation(int styleName, JSONObject json, String qtClassName, AttributeSet attributeSet) {
958 try {
959 TypedValue typedValue = new TypedValue();
960 Context ctx = new ContextThemeWrapper(m_context, m_theme);
961 ctx.getTheme().resolveAttribute(styleName, typedValue, true);
962
963 int[] attributes = new int[]{
964 android.R.attr.digits,
965 android.R.attr.background,
966 android.R.attr.padding,
967 android.R.attr.paddingLeft,
968 android.R.attr.paddingTop,
969 android.R.attr.paddingRight,
970 android.R.attr.paddingBottom,
971 android.R.attr.scrollX,
972 android.R.attr.scrollY,
973 android.R.attr.id,
974 android.R.attr.tag,
975 android.R.attr.fitsSystemWindows,
976 android.R.attr.focusable,
977 android.R.attr.focusableInTouchMode,
978 android.R.attr.clickable,
979 android.R.attr.longClickable,
980 android.R.attr.saveEnabled,
981 android.R.attr.duplicateParentState,
982 android.R.attr.visibility,
983 android.R.attr.drawingCacheQuality,
984 android.R.attr.contentDescription,
985 android.R.attr.soundEffectsEnabled,
986 android.R.attr.hapticFeedbackEnabled,
987 android.R.attr.scrollbars,
988 android.R.attr.fadingEdge,
989 android.R.attr.scrollbarStyle,
990 android.R.attr.scrollbarFadeDuration,
991 android.R.attr.scrollbarDefaultDelayBeforeFade,
992 android.R.attr.scrollbarSize,
993 android.R.attr.scrollbarThumbHorizontal,
994 android.R.attr.scrollbarThumbVertical,
995 android.R.attr.scrollbarTrackHorizontal,
996 android.R.attr.scrollbarTrackVertical,
997 android.R.attr.isScrollContainer,
998 android.R.attr.keepScreenOn,
999 android.R.attr.filterTouchesWhenObscured,
1000 android.R.attr.nextFocusLeft,
1001 android.R.attr.nextFocusRight,
1002 android.R.attr.nextFocusUp,
1003 android.R.attr.nextFocusDown,
1004 android.R.attr.minWidth,
1005 android.R.attr.minHeight,
1006 android.R.attr.onClick,
1007 android.R.attr.overScrollMode,
1008 android.R.attr.paddingStart,
1009 android.R.attr.paddingEnd,
1010 };
1011
1012 // The array must be sorted in ascending order, otherwise obtainStyledAttributes()
1013 // might fail to find some attributes
1014 Arrays.sort(attributes);
1016 if (attributeSet != null)
1017 array = m_theme.obtainStyledAttributes(attributeSet, attributes, styleName, 0);
1018 else
1019 array = obtainStyledAttributes(styleName, attributes);
1020 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1021
1022 if (null != qtClassName)
1023 json.put("qtClass", qtClassName);
1024
1025 json.put("defaultBackgroundColor", defaultBackgroundColor);
1026 json.put("defaultTextColorPrimary", defaultTextColor);
1027 json.put("TextView_digits", array.getText(sortedAttrs.indexOf(android.R.attr.digits)));
1028 json.put("View_background", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.background)), styleName + "_View_background", null));
1029 json.put("View_padding", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.padding), -1));
1030 json.put("View_paddingLeft", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.paddingLeft), -1));
1031 json.put("View_paddingTop", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.paddingTop), -1));
1032 json.put("View_paddingRight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.paddingRight), -1));
1033 json.put("View_paddingBottom", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.paddingBottom), -1));
1034 json.put("View_paddingBottom", array.getDimensionPixelOffset(sortedAttrs.indexOf(android.R.attr.scrollX), 0));
1035 json.put("View_scrollY", array.getDimensionPixelOffset(sortedAttrs.indexOf(android.R.attr.scrollY), 0));
1036 json.put("View_id", array.getResourceId(sortedAttrs.indexOf(android.R.attr.id), -1));
1037 json.put("View_tag", array.getText(sortedAttrs.indexOf(android.R.attr.tag)));
1038 json.put("View_fitsSystemWindows", array.getBoolean(sortedAttrs.indexOf(android.R.attr.fitsSystemWindows), false));
1039 json.put("View_focusable", array.getBoolean(sortedAttrs.indexOf(android.R.attr.focusable), false));
1040 json.put("View_focusableInTouchMode", array.getBoolean(sortedAttrs.indexOf(android.R.attr.focusableInTouchMode), false));
1041 json.put("View_clickable", array.getBoolean(sortedAttrs.indexOf(android.R.attr.clickable), false));
1042 json.put("View_longClickable", array.getBoolean(sortedAttrs.indexOf(android.R.attr.longClickable), false));
1043 json.put("View_saveEnabled", array.getBoolean(sortedAttrs.indexOf(android.R.attr.saveEnabled), true));
1044 json.put("View_duplicateParentState", array.getBoolean(sortedAttrs.indexOf(android.R.attr.duplicateParentState), false));
1045 json.put("View_visibility", array.getInt(sortedAttrs.indexOf(android.R.attr.visibility), 0));
1046 json.put("View_drawingCacheQuality", array.getInt(sortedAttrs.indexOf(android.R.attr.drawingCacheQuality), 0));
1047 json.put("View_contentDescription", array.getString(sortedAttrs.indexOf(android.R.attr.contentDescription)));
1048 json.put("View_soundEffectsEnabled", array.getBoolean(sortedAttrs.indexOf(android.R.attr.soundEffectsEnabled), true));
1049 json.put("View_hapticFeedbackEnabled", array.getBoolean(sortedAttrs.indexOf(android.R.attr.hapticFeedbackEnabled), true));
1050 json.put("View_scrollbars", array.getInt(sortedAttrs.indexOf(android.R.attr.scrollbars), 0));
1051 json.put("View_fadingEdge", array.getInt(sortedAttrs.indexOf(android.R.attr.fadingEdge), 0));
1052 json.put("View_scrollbarStyle", array.getInt(sortedAttrs.indexOf(android.R.attr.scrollbarStyle), 0));
1053 json.put("View_scrollbarFadeDuration", array.getInt(sortedAttrs.indexOf(android.R.attr.scrollbarFadeDuration), 0));
1054 json.put("View_scrollbarDefaultDelayBeforeFade", array.getInt(sortedAttrs.indexOf(android.R.attr.scrollbarDefaultDelayBeforeFade), 0));
1055 json.put("View_scrollbarSize", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.scrollbarSize), -1));
1056 json.put("View_scrollbarThumbHorizontal", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.scrollbarThumbHorizontal)), styleName + "_View_scrollbarThumbHorizontal", null));
1057 json.put("View_scrollbarThumbVertical", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.scrollbarThumbVertical)), styleName + "_View_scrollbarThumbVertical", null));
1058 json.put("View_scrollbarTrackHorizontal", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.scrollbarTrackHorizontal)), styleName + "_View_scrollbarTrackHorizontal", null));
1059 json.put("View_scrollbarTrackVertical", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.scrollbarTrackVertical)), styleName + "_View_scrollbarTrackVertical", null));
1060 json.put("View_isScrollContainer", array.getBoolean(sortedAttrs.indexOf(android.R.attr.isScrollContainer), false));
1061 json.put("View_keepScreenOn", array.getBoolean(sortedAttrs.indexOf(android.R.attr.keepScreenOn), false));
1062 json.put("View_filterTouchesWhenObscured", array.getBoolean(sortedAttrs.indexOf(android.R.attr.filterTouchesWhenObscured), false));
1063 json.put("View_nextFocusLeft", array.getResourceId(sortedAttrs.indexOf(android.R.attr.nextFocusLeft), -1));
1064 json.put("View_nextFocusRight", array.getResourceId(sortedAttrs.indexOf(android.R.attr.nextFocusRight), -1));
1065 json.put("View_nextFocusUp", array.getResourceId(sortedAttrs.indexOf(android.R.attr.nextFocusUp), -1));
1066 json.put("View_nextFocusDown", array.getResourceId(sortedAttrs.indexOf(android.R.attr.nextFocusDown), -1));
1067 json.put("View_minWidth", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.minWidth), 0));
1068 json.put("View_minHeight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.minHeight), 0));
1069 json.put("View_onClick", array.getString(sortedAttrs.indexOf(android.R.attr.onClick)));
1070 json.put("View_overScrollMode", array.getInt(sortedAttrs.indexOf(android.R.attr.overScrollMode), 1));
1071 json.put("View_paddingStart", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.paddingStart), 0));
1072 json.put("View_paddingEnd", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.paddingEnd), 0));
1073 array.recycle();
1074 } catch (Exception e) {
1075 e.printStackTrace();
1076 }
1077 }
1078
1079 JSONObject extractTextAppearance(int styleName)
1080 {
1081 return extractTextAppearance(styleName, false);
1082 }
1083
1084 @SuppressLint("ResourceType")
1085 JSONObject extractTextAppearance(int styleName, boolean subStyle)
1086 {
1087 final int[] attributes = new int[]{
1088 android.R.attr.textSize,
1089 android.R.attr.textStyle,
1090 android.R.attr.textColor,
1091 android.R.attr.typeface,
1092 android.R.attr.textAllCaps,
1093 android.R.attr.textColorHint,
1094 android.R.attr.textColorLink,
1095 android.R.attr.textColorHighlight
1096 };
1097 Arrays.sort(attributes);
1099 if (subStyle)
1100 array = m_theme.obtainStyledAttributes(styleName, attributes);
1101 else
1102 array = obtainStyledAttributes(styleName, attributes);
1103 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1104 JSONObject json = new JSONObject();
1105 try {
1106 int attr = sortedAttrs.indexOf(android.R.attr.textSize);
1107 if (array.hasValue(attr))
1108 json.put("TextAppearance_textSize", array.getDimensionPixelSize(attr, 15));
1109 attr = sortedAttrs.indexOf(android.R.attr.textStyle);
1110 if (array.hasValue(attr))
1111 json.put("TextAppearance_textStyle", array.getInt(attr, -1));
1112 ColorStateList color = array.getColorStateList(sortedAttrs.indexOf(android.R.attr.textColor));
1113 if (color != null)
1114 json.put("TextAppearance_textColor", getColorStateList(color));
1115 attr = sortedAttrs.indexOf(android.R.attr.typeface);
1116 if (array.hasValue(attr))
1117 json.put("TextAppearance_typeface", array.getInt(attr, -1));
1118 attr = sortedAttrs.indexOf(android.R.attr.textAllCaps);
1119 if (array.hasValue(attr))
1120 json.put("TextAppearance_textAllCaps", array.getBoolean(attr, false));
1121 color = array.getColorStateList(sortedAttrs.indexOf(android.R.attr.textColorHint));
1122 if (color != null)
1123 json.put("TextAppearance_textColorHint", getColorStateList(color));
1124 color = array.getColorStateList(sortedAttrs.indexOf(android.R.attr.textColorLink));
1125 if (color != null)
1126 json.put("TextAppearance_textColorLink", getColorStateList(color));
1127 attr = sortedAttrs.indexOf(android.R.attr.textColorHighlight);
1128 if (array.hasValue(attr))
1129 json.put("TextAppearance_textColorHighlight", array.getColor(attr, 0));
1130 array.recycle();
1131 } catch (Exception e) {
1132 e.printStackTrace();
1133 }
1134 return json;
1135 }
1136
1137 JSONObject extractTextAppearanceInformation(int styleName, String qtClass) {
1138 return extractTextAppearanceInformation(styleName, qtClass, android.R.attr.textAppearance, null);
1139 }
1140
1141 JSONObject extractTextAppearanceInformation(int styleName, String qtClass, int textAppearance, AttributeSet attributeSet) {
1142 JSONObject json = new JSONObject();
1143 extractViewInformation(styleName, json, qtClass, attributeSet);
1144
1145 if (textAppearance == -1)
1146 textAppearance = android.R.attr.textAppearance;
1147
1148 try {
1149 TypedValue typedValue = new TypedValue();
1150 Context ctx = new ContextThemeWrapper(m_context, m_theme);
1151 ctx.getTheme().resolveAttribute(styleName, typedValue, true);
1152
1153 // Get textAppearance values
1154 int[] textAppearanceAttr = new int[]{textAppearance};
1155 TypedArray textAppearanceArray = ctx.obtainStyledAttributes(typedValue.data, textAppearanceAttr);
1156 int textAppearanceId = textAppearanceArray.getResourceId(0, -1);
1157 textAppearanceArray.recycle();
1158
1159 int textSize = 15;
1160 int styleIndex = -1;
1161 int typefaceIndex = -1;
1162 int textColorHighlight = 0;
1163 boolean allCaps = false;
1164
1165 if (textAppearanceId != -1) {
1166 int[] attributes = new int[]{
1167 android.R.attr.textSize,
1168 android.R.attr.textStyle,
1169 android.R.attr.typeface,
1170 android.R.attr.textAllCaps,
1171 android.R.attr.textColorHighlight
1172 };
1173 Arrays.sort(attributes);
1174 TypedArray array = m_theme.obtainStyledAttributes(textAppearanceId, attributes);
1175 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1176
1177 textSize = array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.textSize), 15);
1178 styleIndex = array.getInt(sortedAttrs.indexOf(android.R.attr.textStyle), -1);
1179 typefaceIndex = array.getInt(sortedAttrs.indexOf(android.R.attr.typeface), -1);
1180 textColorHighlight = array.getColor(sortedAttrs.indexOf(android.R.attr.textColorHighlight), 0);
1181 allCaps = array.getBoolean(sortedAttrs.indexOf(android.R.attr.textAllCaps), false);
1182 array.recycle();
1183 }
1184 // Get TextView values
1185 int[] attributes = new int[]{
1186 android.R.attr.editable,
1187 android.R.attr.inputMethod,
1188 android.R.attr.numeric,
1189 android.R.attr.digits,
1190 android.R.attr.phoneNumber,
1191 android.R.attr.autoText,
1192 android.R.attr.capitalize,
1193 android.R.attr.bufferType,
1194 android.R.attr.selectAllOnFocus,
1195 android.R.attr.autoLink,
1196 android.R.attr.linksClickable,
1197 android.R.attr.drawableLeft,
1198 android.R.attr.drawableTop,
1199 android.R.attr.drawableRight,
1200 android.R.attr.drawableBottom,
1201 android.R.attr.drawableStart,
1202 android.R.attr.drawableEnd,
1203 android.R.attr.maxLines,
1204 android.R.attr.drawablePadding,
1205 android.R.attr.textCursorDrawable,
1206 android.R.attr.maxHeight,
1207 android.R.attr.lines,
1208 android.R.attr.height,
1209 android.R.attr.minLines,
1210 android.R.attr.minHeight,
1211 android.R.attr.maxEms,
1212 android.R.attr.maxWidth,
1213 android.R.attr.ems,
1214 android.R.attr.width,
1215 android.R.attr.minEms,
1216 android.R.attr.minWidth,
1217 android.R.attr.gravity,
1218 android.R.attr.hint,
1219 android.R.attr.text,
1220 android.R.attr.scrollHorizontally,
1221 android.R.attr.singleLine,
1222 android.R.attr.ellipsize,
1223 android.R.attr.marqueeRepeatLimit,
1224 android.R.attr.includeFontPadding,
1225 android.R.attr.cursorVisible,
1226 android.R.attr.maxLength,
1227 android.R.attr.textScaleX,
1228 android.R.attr.freezesText,
1229 android.R.attr.shadowColor,
1230 android.R.attr.shadowDx,
1231 android.R.attr.shadowDy,
1232 android.R.attr.shadowRadius,
1233 android.R.attr.enabled,
1234 android.R.attr.textColorHighlight,
1235 android.R.attr.textColor,
1236 android.R.attr.textColorHint,
1237 android.R.attr.textColorLink,
1238 android.R.attr.textSize,
1239 android.R.attr.typeface,
1240 android.R.attr.textStyle,
1241 android.R.attr.password,
1242 android.R.attr.lineSpacingExtra,
1243 android.R.attr.lineSpacingMultiplier,
1244 android.R.attr.inputType,
1245 android.R.attr.imeOptions,
1246 android.R.attr.imeActionLabel,
1247 android.R.attr.imeActionId,
1248 android.R.attr.privateImeOptions,
1249 android.R.attr.textSelectHandleLeft,
1250 android.R.attr.textSelectHandleRight,
1251 android.R.attr.textSelectHandle,
1252 android.R.attr.textIsSelectable,
1253 android.R.attr.textAllCaps
1254 };
1255
1256 // The array must be sorted in ascending order, otherwise obtainStyledAttributes()
1257 // might fail to find some attributes
1258 Arrays.sort(attributes);
1259 TypedArray array = ctx.obtainStyledAttributes(typedValue.data, attributes);
1260 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1261
1262 textSize = array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.textSize), textSize);
1263 styleIndex = array.getInt(sortedAttrs.indexOf(android.R.attr.textStyle), styleIndex);
1264 typefaceIndex = array.getInt(sortedAttrs.indexOf(android.R.attr.typeface), typefaceIndex);
1265 textColorHighlight = array.getColor(sortedAttrs.indexOf(android.R.attr.textColorHighlight), textColorHighlight);
1266 allCaps = array.getBoolean(sortedAttrs.indexOf(android.R.attr.textAllCaps), allCaps);
1267
1268 ColorStateList textColor = array.getColorStateList(sortedAttrs.indexOf(android.R.attr.textColor));
1269 ColorStateList textColorHint = array.getColorStateList(sortedAttrs.indexOf(android.R.attr.textColorHint));
1270 ColorStateList textColorLink = array.getColorStateList(sortedAttrs.indexOf(android.R.attr.textColorLink));
1271
1272 json.put("TextAppearance_textSize", textSize);
1273 json.put("TextAppearance_textStyle", styleIndex);
1274 json.put("TextAppearance_typeface", typefaceIndex);
1275 json.put("TextAppearance_textColorHighlight", textColorHighlight);
1276 json.put("TextAppearance_textAllCaps", allCaps);
1277 if (textColor != null)
1278 json.put("TextAppearance_textColor", getColorStateList(textColor));
1279 if (textColorHint != null)
1280 json.put("TextAppearance_textColorHint", getColorStateList(textColorHint));
1281 if (textColorLink != null)
1282 json.put("TextAppearance_textColorLink", getColorStateList(textColorLink));
1283
1284 json.put("TextView_editable", array.getBoolean(sortedAttrs.indexOf(android.R.attr.editable), false));
1285 json.put("TextView_inputMethod", array.getText(sortedAttrs.indexOf(android.R.attr.inputMethod)));
1286 json.put("TextView_numeric", array.getInt(sortedAttrs.indexOf(android.R.attr.numeric), 0));
1287 json.put("TextView_digits", array.getText(sortedAttrs.indexOf(android.R.attr.digits)));
1288 json.put("TextView_phoneNumber", array.getBoolean(sortedAttrs.indexOf(android.R.attr.phoneNumber), false));
1289 json.put("TextView_autoText", array.getBoolean(sortedAttrs.indexOf(android.R.attr.autoText), false));
1290 json.put("TextView_capitalize", array.getInt(sortedAttrs.indexOf(android.R.attr.capitalize), -1));
1291 json.put("TextView_bufferType", array.getInt(sortedAttrs.indexOf(android.R.attr.bufferType), 0));
1292 json.put("TextView_selectAllOnFocus", array.getBoolean(sortedAttrs.indexOf(android.R.attr.selectAllOnFocus), false));
1293 json.put("TextView_autoLink", array.getInt(sortedAttrs.indexOf(android.R.attr.autoLink), 0));
1294 json.put("TextView_linksClickable", array.getBoolean(sortedAttrs.indexOf(android.R.attr.linksClickable), true));
1295 json.put("TextView_drawableLeft", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.drawableLeft)), styleName + "_TextView_drawableLeft", null));
1296 json.put("TextView_drawableTop", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.drawableTop)), styleName + "_TextView_drawableTop", null));
1297 json.put("TextView_drawableRight", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.drawableRight)), styleName + "_TextView_drawableRight", null));
1298 json.put("TextView_drawableBottom", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.drawableBottom)), styleName + "_TextView_drawableBottom", null));
1299 json.put("TextView_drawableStart", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.drawableStart)), styleName + "_TextView_drawableStart", null));
1300 json.put("TextView_drawableEnd", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.drawableEnd)), styleName + "_TextView_drawableEnd", null));
1301 json.put("TextView_maxLines", array.getInt(sortedAttrs.indexOf(android.R.attr.maxLines), -1));
1302 json.put("TextView_drawablePadding", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.drawablePadding), 0));
1303
1304 try {
1305 json.put("TextView_textCursorDrawable", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.textCursorDrawable)), styleName + "_TextView_textCursorDrawable", null));
1306 } catch (Exception e_) {
1307 json.put("TextView_textCursorDrawable", getDrawable(m_context.getResources().getDrawable(array.getResourceId(sortedAttrs.indexOf(android.R.attr.textCursorDrawable), 0), m_theme), styleName + "_TextView_textCursorDrawable", null));
1308 }
1309
1310 json.put("TextView_maxLines", array.getInt(sortedAttrs.indexOf(android.R.attr.maxLines), -1));
1311 json.put("TextView_maxHeight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.maxHeight), -1));
1312 json.put("TextView_lines", array.getInt(sortedAttrs.indexOf(android.R.attr.lines), -1));
1313 json.put("TextView_height", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.height), -1));
1314 json.put("TextView_minLines", array.getInt(sortedAttrs.indexOf(android.R.attr.minLines), -1));
1315 json.put("TextView_minHeight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.minHeight), -1));
1316 json.put("TextView_maxEms", array.getInt(sortedAttrs.indexOf(android.R.attr.maxEms), -1));
1317 json.put("TextView_maxWidth", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.maxWidth), -1));
1318 json.put("TextView_ems", array.getInt(sortedAttrs.indexOf(android.R.attr.ems), -1));
1319 json.put("TextView_width", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.width), -1));
1320 json.put("TextView_minEms", array.getInt(sortedAttrs.indexOf(android.R.attr.minEms), -1));
1321 json.put("TextView_minWidth", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.minWidth), -1));
1322 json.put("TextView_gravity", array.getInt(sortedAttrs.indexOf(android.R.attr.gravity), -1));
1323 json.put("TextView_hint", array.getText(sortedAttrs.indexOf(android.R.attr.hint)));
1324 json.put("TextView_text", array.getText(sortedAttrs.indexOf(android.R.attr.text)));
1325 json.put("TextView_scrollHorizontally", array.getBoolean(sortedAttrs.indexOf(android.R.attr.scrollHorizontally), false));
1326 json.put("TextView_singleLine", array.getBoolean(sortedAttrs.indexOf(android.R.attr.singleLine), false));
1327 json.put("TextView_ellipsize", array.getInt(sortedAttrs.indexOf(android.R.attr.ellipsize), -1));
1328 json.put("TextView_marqueeRepeatLimit", array.getInt(sortedAttrs.indexOf(android.R.attr.marqueeRepeatLimit), 3));
1329 json.put("TextView_includeFontPadding", array.getBoolean(sortedAttrs.indexOf(android.R.attr.includeFontPadding), true));
1330 json.put("TextView_cursorVisible", array.getBoolean(sortedAttrs.indexOf(android.R.attr.maxLength), true));
1331 json.put("TextView_maxLength", array.getInt(sortedAttrs.indexOf(android.R.attr.maxLength), -1));
1332 json.put("TextView_textScaleX", array.getFloat(sortedAttrs.indexOf(android.R.attr.textScaleX), 1.0f));
1333 json.put("TextView_freezesText", array.getBoolean(sortedAttrs.indexOf(android.R.attr.freezesText), false));
1334 json.put("TextView_shadowColor", array.getInt(sortedAttrs.indexOf(android.R.attr.shadowColor), 0));
1335 json.put("TextView_shadowDx", array.getFloat(sortedAttrs.indexOf(android.R.attr.shadowDx), 0));
1336 json.put("TextView_shadowDy", array.getFloat(sortedAttrs.indexOf(android.R.attr.shadowDy), 0));
1337 json.put("TextView_shadowRadius", array.getFloat(sortedAttrs.indexOf(android.R.attr.shadowRadius), 0));
1338 json.put("TextView_enabled", array.getBoolean(sortedAttrs.indexOf(android.R.attr.enabled), true));
1339 json.put("TextView_password", array.getBoolean(sortedAttrs.indexOf(android.R.attr.password), false));
1340 json.put("TextView_lineSpacingExtra", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.lineSpacingExtra), 0));
1341 json.put("TextView_lineSpacingMultiplier", array.getFloat(sortedAttrs.indexOf(android.R.attr.lineSpacingMultiplier), 1.0f));
1342 json.put("TextView_inputType", array.getInt(sortedAttrs.indexOf(android.R.attr.inputType), EditorInfo.TYPE_NULL));
1343 json.put("TextView_imeOptions", array.getInt(sortedAttrs.indexOf(android.R.attr.imeOptions), EditorInfo.IME_NULL));
1344 json.put("TextView_imeActionLabel", array.getText(sortedAttrs.indexOf(android.R.attr.imeActionLabel)));
1345 json.put("TextView_imeActionId", array.getInt(sortedAttrs.indexOf(android.R.attr.imeActionId), 0));
1346 json.put("TextView_privateImeOptions", array.getString(sortedAttrs.indexOf(android.R.attr.privateImeOptions)));
1347
1348 try {
1349 json.put("TextView_textSelectHandleLeft", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.textSelectHandleLeft)), styleName + "_TextView_textSelectHandleLeft", null));
1350 } catch (Exception _e) {
1351 json.put("TextView_textSelectHandleLeft", getDrawable(m_context.getResources().getDrawable(array.getResourceId(sortedAttrs.indexOf(android.R.attr.textSelectHandleLeft), 0), m_theme), styleName + "_TextView_textSelectHandleLeft", null));
1352 }
1353
1354 try {
1355 json.put("TextView_textSelectHandleRight", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.textSelectHandleRight)), styleName + "_TextView_textSelectHandleRight", null));
1356 } catch (Exception _e) {
1357 json.put("TextView_textSelectHandleRight", getDrawable(m_context.getResources().getDrawable(array.getResourceId(sortedAttrs.indexOf(android.R.attr.textSelectHandleRight), 0), m_theme), styleName + "_TextView_textSelectHandleRight", null));
1358 }
1359
1360 try {
1361 json.put("TextView_textSelectHandle", getDrawable(array.getDrawable(sortedAttrs.indexOf(android.R.attr.textSelectHandle)), styleName + "_TextView_textSelectHandle", null));
1362 } catch (Exception _e) {
1363 json.put("TextView_textSelectHandle", getDrawable(m_context.getResources().getDrawable(array.getResourceId(sortedAttrs.indexOf(android.R.attr.textSelectHandle), 0), m_theme), styleName + "_TextView_textSelectHandle", null));
1364 }
1365 json.put("TextView_textIsSelectable", array.getBoolean(sortedAttrs.indexOf(android.R.attr.textIsSelectable), false));
1366 array.recycle();
1367 } catch (Exception e) {
1368 e.printStackTrace();
1369 }
1370 return json;
1371 }
1372
1373 JSONObject extractImageViewInformation(int styleName, String qtClassName) {
1374 JSONObject json = new JSONObject();
1375 try {
1376 extractViewInformation(styleName, json, qtClassName);
1377
1378 int[] attributes = new int[]{
1379 android.R.attr.src,
1380 android.R.attr.baselineAlignBottom,
1381 android.R.attr.adjustViewBounds,
1382 android.R.attr.maxWidth,
1383 android.R.attr.maxHeight,
1384 android.R.attr.scaleType,
1385 android.R.attr.cropToPadding,
1386 android.R.attr.tint
1387
1388 };
1389 Arrays.sort(attributes);
1390 TypedArray array = obtainStyledAttributes(styleName, attributes);
1391 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1392
1393 Drawable drawable = array.getDrawable(sortedAttrs.indexOf(android.R.attr.src));
1394 if (drawable != null)
1395 json.put("ImageView_src", getDrawable(drawable, styleName + "_ImageView_src", null));
1396
1397 json.put("ImageView_baselineAlignBottom", array.getBoolean(sortedAttrs.indexOf(android.R.attr.baselineAlignBottom), false));
1398 json.put("ImageView_adjustViewBounds", array.getBoolean(sortedAttrs.indexOf(android.R.attr.baselineAlignBottom), false));
1399 json.put("ImageView_maxWidth", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.maxWidth), Integer.MAX_VALUE));
1400 json.put("ImageView_maxHeight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.maxHeight), Integer.MAX_VALUE));
1401 int index = array.getInt(sortedAttrs.indexOf(android.R.attr.scaleType), -1);
1402 if (index >= 0)
1403 json.put("ImageView_scaleType", sScaleTypeArray[index]);
1404
1405 int tint = array.getInt(sortedAttrs.indexOf(android.R.attr.tint), 0);
1406 if (tint != 0)
1407 json.put("ImageView_tint", tint);
1408
1409 json.put("ImageView_cropToPadding", array.getBoolean(sortedAttrs.indexOf(android.R.attr.cropToPadding), false));
1410 array.recycle();
1411 } catch (Exception e) {
1412 e.printStackTrace();
1413 }
1414 return json;
1415 }
1416
1417 void extractCompoundButton(SimpleJsonWriter jsonWriter, int styleName, String className, String qtClass) {
1418 JSONObject json = extractTextAppearanceInformation(styleName, qtClass);
1419
1420 TypedValue typedValue = new TypedValue();
1421 Context ctx = new ContextThemeWrapper(m_context, m_theme);
1422 ctx.getTheme().resolveAttribute(styleName, typedValue, true);
1423 final int[] attributes = new int[]{android.R.attr.button};
1424 TypedArray array = ctx.obtainStyledAttributes(typedValue.data, attributes);
1425 Drawable drawable = array.getDrawable(0);
1426 array.recycle();
1427
1428 try {
1429 if (drawable != null)
1430 json.put("CompoundButton_button", getDrawable(drawable, styleName + "_CompoundButton_button", null));
1431 jsonWriter.name(className).value(json);
1432 } catch (Exception e) {
1433 e.printStackTrace();
1434 }
1435 }
1436
1437 void extractProgressBarInfo(JSONObject json, int styleName) {
1438 try {
1439 final int[] attributes = new int[]{
1440 android.R.attr.minWidth,
1441 android.R.attr.maxWidth,
1442 android.R.attr.minHeight,
1443 android.R.attr.maxHeight,
1444 android.R.attr.indeterminateDuration,
1445 android.R.attr.progressDrawable,
1446 android.R.attr.indeterminateDrawable
1447 };
1448
1449 // The array must be sorted in ascending order, otherwise obtainStyledAttributes()
1450 // might fail to find some attributes
1451 Arrays.sort(attributes);
1452 TypedArray array = obtainStyledAttributes(styleName, attributes);
1453 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1454
1455 json.put("ProgressBar_indeterminateDuration", array.getInt(sortedAttrs.indexOf(android.R.attr.indeterminateDuration), 4000));
1456 json.put("ProgressBar_minWidth", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.minWidth), 24));
1457 json.put("ProgressBar_maxWidth", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.maxWidth), 48));
1458 json.put("ProgressBar_minHeight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.minHeight), 24));
1459 json.put("ProgressBar_maxHeight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.maxHeight), 28));
1460 json.put("ProgressBar_progress_id", android.R.id.progress);
1461 json.put("ProgressBar_secondaryProgress_id", android.R.id.secondaryProgress);
1462
1463 Drawable drawable = array.getDrawable(sortedAttrs.indexOf(android.R.attr.progressDrawable));
1464 if (drawable != null)
1465 json.put("ProgressBar_progressDrawable", getDrawable(drawable,
1466 styleName + "_ProgressBar_progressDrawable", null));
1467
1468 drawable = array.getDrawable(sortedAttrs.indexOf(android.R.attr.indeterminateDrawable));
1469 if (drawable != null)
1470 json.put("ProgressBar_indeterminateDrawable", getDrawable(drawable,
1471 styleName + "_ProgressBar_indeterminateDrawable", null));
1472
1473 array.recycle();
1474 } catch (Exception e) {
1475 e.printStackTrace();
1476 }
1477 }
1478
1479 void extractProgressBar(SimpleJsonWriter writer, int styleName, String className, String qtClass) {
1480 JSONObject json = extractTextAppearanceInformation(android.R.attr.progressBarStyle, qtClass);
1481 try {
1482 extractProgressBarInfo(json, styleName);
1483 writer.name(className).value(json);
1484 } catch (Exception e) {
1485 e.printStackTrace();
1486 }
1487 }
1488
1489 void extractAbsSeekBar(SimpleJsonWriter jsonWriter) {
1490 JSONObject json = extractTextAppearanceInformation(android.R.attr.seekBarStyle, "QSlider");
1491 extractProgressBarInfo(json, android.R.attr.seekBarStyle);
1492 try {
1493 int[] attributes = new int[]{
1494 android.R.attr.thumb,
1495 android.R.attr.thumbOffset
1496 };
1497 Arrays.sort(attributes);
1498 TypedArray array = obtainStyledAttributes(android.R.attr.seekBarStyle, attributes);
1499 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1500
1501 Drawable d = array.getDrawable(sortedAttrs.indexOf(android.R.attr.thumb));
1502 if (d != null)
1503 json.put("SeekBar_thumb", getDrawable(d, android.R.attr.seekBarStyle + "_SeekBar_thumb", null));
1504 json.put("SeekBar_thumbOffset", array.getDimensionPixelOffset(sortedAttrs.indexOf(android.R.attr.thumbOffset), -1));
1505 array.recycle();
1506 jsonWriter.name("seekBarStyle").value(json);
1507 } catch (Exception e) {
1508 e.printStackTrace();
1509 }
1510 }
1511
1512 void extractSwitch(SimpleJsonWriter jsonWriter) {
1513 JSONObject json = new JSONObject();
1514 try {
1515 int[] attributes = new int[]{
1516 android.R.attr.thumb,
1517 android.R.attr.track,
1518 android.R.attr.switchTextAppearance,
1519 android.R.attr.textOn,
1520 android.R.attr.textOff,
1521 android.R.attr.switchMinWidth,
1522 android.R.attr.switchPadding,
1523 android.R.attr.thumbTextPadding,
1524 android.R.attr.showText,
1525 android.R.attr.splitTrack
1526 };
1527 Arrays.sort(attributes);
1528 TypedArray array = obtainStyledAttributes(android.R.attr.switchStyle, attributes);
1529 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1530
1531 Drawable thumb = array.getDrawable(sortedAttrs.indexOf(android.R.attr.thumb));
1532 if (thumb != null)
1533 json.put("Switch_thumb", getDrawable(thumb, android.R.attr.switchStyle + "_Switch_thumb", null));
1534
1535 Drawable track = array.getDrawable(sortedAttrs.indexOf(android.R.attr.track));
1536 if (track != null)
1537 json.put("Switch_track", getDrawable(track, android.R.attr.switchStyle + "_Switch_track", null));
1538
1539 json.put("Switch_textOn", array.getText(sortedAttrs.indexOf(android.R.attr.textOn)));
1540 json.put("Switch_textOff", array.getText(sortedAttrs.indexOf(android.R.attr.textOff)));
1541 json.put("Switch_switchMinWidth", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.switchMinWidth), 0));
1542 json.put("Switch_switchPadding", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.switchPadding), 0));
1543 json.put("Switch_thumbTextPadding", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.thumbTextPadding), 0));
1544 json.put("Switch_showText", array.getBoolean(sortedAttrs.indexOf(android.R.attr.showText), true));
1545 json.put("Switch_splitTrack", array.getBoolean(sortedAttrs.indexOf(android.R.attr.splitTrack), false));
1546
1547 // Get textAppearance values
1548 final int textAppearanceId = array.getResourceId(sortedAttrs.indexOf(android.R.attr.switchTextAppearance), -1);
1549 json.put("Switch_switchTextAppearance", extractTextAppearance(textAppearanceId, true));
1550
1551 array.recycle();
1552 jsonWriter.name("switchStyle").value(json);
1553 } catch (Exception e) {
1554 e.printStackTrace();
1555 }
1556 }
1557
1558 JSONObject extractCheckedTextView(String itemName) {
1559 JSONObject json = extractTextAppearanceInformation(android.R.attr.checkedTextViewStyle, itemName);
1560 try {
1561 int[] attributes = new int[]{
1562 android.R.attr.checkMark,
1563 };
1564
1565 Arrays.sort(attributes);
1566 TypedArray array = obtainStyledAttributes(android.R.attr.switchStyle, attributes);
1567 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1568
1569 Drawable drawable = array.getDrawable(sortedAttrs.indexOf(android.R.attr.checkMark));
1570 if (drawable != null)
1571 json.put("CheckedTextView_checkMark", getDrawable(drawable, itemName + "_CheckedTextView_checkMark", null));
1572 array.recycle();
1573 } catch (Exception e) {
1574 e.printStackTrace();
1575 }
1576 return json;
1577 }
1578
1579 private JSONObject extractItemStyle(int resourceId, String itemName)
1580 {
1581 try {
1582 XmlResourceParser parser = m_context.getResources().getLayout(resourceId);
1583 int type = parser.next();
1584 while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT)
1585 type = parser.next();
1586
1587 if (type != XmlPullParser.START_TAG)
1588 return null;
1589
1590 AttributeSet attributes = Xml.asAttributeSet(parser);
1591 String name = parser.getName();
1592 if (name.equals("TextView"))
1593 return extractTextAppearanceInformation(android.R.attr.textViewStyle, itemName, android.R.attr.textAppearanceListItem, attributes);
1594 else if (name.equals("CheckedTextView"))
1595 return extractCheckedTextView(itemName);
1596 } catch (Exception e) {
1597 e.printStackTrace();
1598 }
1599 return null;
1600 }
1601
1602 private void extractItemsStyle(SimpleJsonWriter jsonWriter) {
1603 try {
1604 JSONObject itemStyle = extractItemStyle(android.R.layout.simple_list_item_1, "simple_list_item");
1605 if (itemStyle != null)
1606 jsonWriter.name("simple_list_item").value(itemStyle);
1607 itemStyle = extractItemStyle(android.R.layout.simple_list_item_checked, "simple_list_item_checked");
1608 if (itemStyle != null)
1609 jsonWriter.name("simple_list_item_checked").value(itemStyle);
1610 itemStyle = extractItemStyle(android.R.layout.simple_list_item_multiple_choice, "simple_list_item_multiple_choice");
1611 if (itemStyle != null)
1612 jsonWriter.name("simple_list_item_multiple_choice").value(itemStyle);
1613 itemStyle = extractItemStyle(android.R.layout.simple_list_item_single_choice, "simple_list_item_single_choice");
1614 if (itemStyle != null)
1615 jsonWriter.name("simple_list_item_single_choice").value(itemStyle);
1616 itemStyle = extractItemStyle(android.R.layout.simple_spinner_item, "simple_spinner_item");
1617 if (itemStyle != null)
1618 jsonWriter.name("simple_spinner_item").value(itemStyle);
1619 itemStyle = extractItemStyle(android.R.layout.simple_spinner_dropdown_item, "simple_spinner_dropdown_item");
1620 if (itemStyle != null)
1621 jsonWriter.name("simple_spinner_dropdown_item").value(itemStyle);
1622 itemStyle = extractItemStyle(android.R.layout.simple_dropdown_item_1line, "simple_dropdown_item_1line");
1623 if (itemStyle != null)
1624 jsonWriter.name("simple_dropdown_item_1line").value(itemStyle);
1625 itemStyle = extractItemStyle(android.R.layout.simple_selectable_list_item, "simple_selectable_list_item");
1626 if (itemStyle != null)
1627 jsonWriter.name("simple_selectable_list_item").value(itemStyle);
1628 } catch (Exception e) {
1629 e.printStackTrace();
1630 }
1631 }
1632
1633 void extractListView(SimpleJsonWriter writer) {
1634 JSONObject json = extractTextAppearanceInformation(android.R.attr.listViewStyle, "QListView");
1635 try {
1636 int[] attributes = new int[]{
1637 android.R.attr.divider,
1638 android.R.attr.dividerHeight
1639 };
1640 Arrays.sort(attributes);
1641 TypedArray array = obtainStyledAttributes(android.R.attr.listViewStyle, attributes);
1642 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1643
1644 Drawable divider = array.getDrawable(sortedAttrs.indexOf(android.R.attr.divider));
1645 if (divider != null)
1646 json.put("ListView_divider", getDrawable(divider, android.R.attr.listViewStyle + "_ListView_divider", null));
1647
1648 json.put("ListView_dividerHeight", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.dividerHeight), 0));
1649
1650 array.recycle();
1651 writer.name("listViewStyle").value(json);
1652 } catch (Exception e) {
1653 e.printStackTrace();
1654 }
1655 }
1656
1657 void extractCalendar(SimpleJsonWriter writer) {
1658 JSONObject json = extractTextAppearanceInformation(android.R.attr.calendarViewStyle, "QCalendarWidget");
1659 try {
1660 int[] attributes = new int[]{
1661 android.R.attr.firstDayOfWeek,
1662 android.R.attr.focusedMonthDateColor,
1663 android.R.attr.selectedWeekBackgroundColor,
1664 android.R.attr.showWeekNumber,
1665 android.R.attr.shownWeekCount,
1666 android.R.attr.unfocusedMonthDateColor,
1667 android.R.attr.weekNumberColor,
1668 android.R.attr.weekSeparatorLineColor,
1669 android.R.attr.selectedDateVerticalBar,
1670 android.R.attr.dateTextAppearance,
1671 android.R.attr.weekDayTextAppearance
1672 };
1673 Arrays.sort(attributes);
1674 TypedArray array = obtainStyledAttributes(android.R.attr.calendarViewStyle, attributes);
1675 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1676
1677 Drawable d = array.getDrawable(sortedAttrs.indexOf(android.R.attr.selectedDateVerticalBar));
1678 if (d != null)
1679 json.put("CalendarView_selectedDateVerticalBar", getDrawable(d, android.R.attr.calendarViewStyle + "_CalendarView_selectedDateVerticalBar", null));
1680
1681 int textAppearanceId = array.getResourceId(sortedAttrs.indexOf(android.R.attr.dateTextAppearance), -1);
1682 json.put("CalendarView_dateTextAppearance", extractTextAppearance(textAppearanceId, true));
1683 textAppearanceId = array.getResourceId(sortedAttrs.indexOf(android.R.attr.weekDayTextAppearance), -1);
1684 json.put("CalendarView_weekDayTextAppearance", extractTextAppearance(textAppearanceId, true));
1685
1686
1687 json.put("CalendarView_firstDayOfWeek", array.getInt(sortedAttrs.indexOf(android.R.attr.firstDayOfWeek), 0));
1688 json.put("CalendarView_focusedMonthDateColor", array.getColor(sortedAttrs.indexOf(android.R.attr.focusedMonthDateColor), 0));
1689 json.put("CalendarView_selectedWeekBackgroundColor", array.getColor(sortedAttrs.indexOf(android.R.attr.selectedWeekBackgroundColor), 0));
1690 json.put("CalendarView_showWeekNumber", array.getBoolean(sortedAttrs.indexOf(android.R.attr.showWeekNumber), true));
1691 json.put("CalendarView_shownWeekCount", array.getInt(sortedAttrs.indexOf(android.R.attr.shownWeekCount), 6));
1692 json.put("CalendarView_unfocusedMonthDateColor", array.getColor(sortedAttrs.indexOf(android.R.attr.unfocusedMonthDateColor), 0));
1693 json.put("CalendarView_weekNumberColor", array.getColor(sortedAttrs.indexOf(android.R.attr.weekNumberColor), 0));
1694 json.put("CalendarView_weekSeparatorLineColor", array.getColor(sortedAttrs.indexOf(android.R.attr.weekSeparatorLineColor), 0));
1695 array.recycle();
1696 writer.name("calendarViewStyle").value(json);
1697 } catch (Exception e) {
1698 e.printStackTrace();
1699 }
1700 }
1701
1702 void extractToolBar(SimpleJsonWriter writer) {
1703 JSONObject json = extractTextAppearanceInformation(android.R.attr.toolbarStyle, "QToolBar");
1704 try {
1705 int[] attributes = new int[]{
1706 android.R.attr.background,
1707 android.R.attr.backgroundStacked,
1708 android.R.attr.backgroundSplit,
1709 android.R.attr.divider,
1710 android.R.attr.itemPadding
1711 };
1712 Arrays.sort(attributes);
1713 TypedArray array = obtainStyledAttributes(android.R.attr.toolbarStyle, attributes);
1714 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1715
1716 Drawable d = array.getDrawable(sortedAttrs.indexOf(android.R.attr.background));
1717 if (d != null)
1718 json.put("ActionBar_background", getDrawable(d, android.R.attr.toolbarStyle + "_ActionBar_background", null));
1719
1720 d = array.getDrawable(sortedAttrs.indexOf(android.R.attr.backgroundStacked));
1721 if (d != null)
1722 json.put("ActionBar_backgroundStacked", getDrawable(d, android.R.attr.toolbarStyle + "_ActionBar_backgroundStacked", null));
1723
1724 d = array.getDrawable(sortedAttrs.indexOf(android.R.attr.backgroundSplit));
1725 if (d != null)
1726 json.put("ActionBar_backgroundSplit", getDrawable(d, android.R.attr.toolbarStyle + "_ActionBar_backgroundSplit", null));
1727
1728 d = array.getDrawable(sortedAttrs.indexOf(android.R.attr.divider));
1729 if (d != null)
1730 json.put("ActionBar_divider", getDrawable(d, android.R.attr.toolbarStyle + "_ActionBar_divider", null));
1731
1732 json.put("ActionBar_itemPadding", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.itemPadding), 0));
1733
1734 array.recycle();
1735 writer.name("actionBarStyle").value(json);
1736 } catch (Exception e) {
1737 e.printStackTrace();
1738 }
1739 }
1740
1741 void extractTabBar(SimpleJsonWriter writer) {
1742 JSONObject json = extractTextAppearanceInformation(android.R.attr.actionBarTabBarStyle, "QTabBar");
1743 try {
1744 int[] attributes = new int[]{
1745 android.R.attr.showDividers,
1746 android.R.attr.dividerPadding,
1747 android.R.attr.divider
1748 };
1749 Arrays.sort(attributes);
1750 TypedArray array = obtainStyledAttributes(android.R.attr.actionBarTabStyle, attributes);
1751 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1752
1753 Drawable d = array.getDrawable(sortedAttrs.indexOf(android.R.attr.divider));
1754 if (d != null)
1755 json.put("LinearLayout_divider", getDrawable(d, android.R.attr.actionBarTabStyle + "_LinearLayout_divider", null));
1756 json.put("LinearLayout_showDividers", array.getInt(sortedAttrs.indexOf(android.R.attr.showDividers), 0));
1757 json.put("LinearLayout_dividerPadding", array.getDimensionPixelSize(sortedAttrs.indexOf(android.R.attr.dividerPadding), 0));
1758
1759 array.recycle();
1760 writer.name("actionBarTabBarStyle").value(json);
1761 } catch (Exception e) {
1762 e.printStackTrace();
1763 }
1764 }
1765
1766 private void extractWindow(SimpleJsonWriter writer) {
1767 JSONObject json = new JSONObject();
1768 try {
1769 int[] attributes = new int[]{
1770 android.R.attr.windowBackground,
1771 android.R.attr.windowFrame
1772 };
1773 Arrays.sort(attributes);
1774 TypedArray array = obtainStyledAttributes(android.R.attr.popupWindowStyle, attributes);
1775 ArrayList<Integer> sortedAttrs = getArrayListFromIntArray(attributes);
1776
1777 Drawable background = array.getDrawable(sortedAttrs.indexOf(android.R.attr.windowBackground));
1778 if (background != null)
1779 json.put("Window_windowBackground", getDrawable(background, android.R.attr.popupWindowStyle + "_Window_windowBackground", null));
1780
1781 Drawable frame = array.getDrawable(sortedAttrs.indexOf(android.R.attr.windowFrame));
1782 if (frame != null)
1783 json.put("Window_windowFrame", getDrawable(frame, android.R.attr.popupWindowStyle + "_Window_windowFrame", null));
1784 array.recycle();
1785 writer.name("windowStyle").value(json);
1786 } catch (Exception e) {
1787 e.printStackTrace();
1788 }
1789 }
1790
1791 private JSONObject extractDefaultPalette() {
1792 JSONObject json = extractTextAppearance(android.R.attr.textAppearance);
1793 try {
1794 json.put("defaultBackgroundColor", defaultBackgroundColor);
1795 json.put("defaultTextColorPrimary", defaultTextColor);
1796 } catch (Exception e) {
1797 e.printStackTrace();
1798 }
1799 return json;
1800 }
1801
1802 static class SimpleJsonWriter {
1803 private final OutputStreamWriter m_writer;
1804 private boolean m_addComma = false;
1805 private int m_indentLevel = 0;
1806
1807 SimpleJsonWriter(String filePath) throws IOException {
1808 m_writer = new OutputStreamWriter(Files.newOutputStream(Paths.get(filePath)));
1809 }
1810
1811 void close() throws IOException {
1812 m_writer.close();
1813 }
1814
1815 private void writeIndent() throws IOException {
1816 m_writer.write(" ", 0, m_indentLevel);
1817 }
1818
1819 void beginObject() throws IOException {
1820 writeIndent();
1821 m_writer.write("{\n");
1822 ++m_indentLevel;
1823 m_addComma = false;
1824 }
1825
1826 void endObject() throws IOException {
1827 m_writer.write("\n");
1828 writeIndent();
1829 m_writer.write("}\n");
1830 --m_indentLevel;
1831 m_addComma = false;
1832 }
1833
1834 SimpleJsonWriter name(String name) throws IOException {
1835 if (m_addComma) {
1836 m_writer.write(",\n");
1837 }
1838 writeIndent();
1839 m_writer.write(JSONObject.quote(name) + ": ");
1840 m_addComma = true;
1841 return this;
1842 }
1843
1844 void value(JSONObject value) throws IOException {
1845 m_writer.write(value.toString());
1846 }
1847 }
1848
1849 static class DrawableCache {
1850 JSONObject object;
1851 Object drawable;
1852 DrawableCache(JSONObject json, Object drawable) {
1853 object = json;
1854 this.drawable = drawable;
1855 }
1856 }
1857}
PeripheralState state
constexpr qreal left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:523
constexpr qreal bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:526
constexpr qreal right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:525
constexpr qreal top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:524
QPainter Context
static const QString context()
Definition java.cpp:396
Napi::TypedArray TypedArray
Definition qnapi_p.h:76
Q_WIDGETS_EXPORT qreal dpi(const QStyleOption *option)
constexpr impl::keys_tag keys
Orientation
Definition qnamespace.h:110
#define assert
EGLOutputLayerEXT EGLint EGLAttrib value
[3]
EGLConfig config
[3]
const EGLAttrib EGLOutputLayerEXT * layers
GLenum type
GLenum GLenum GLsizei count
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
GLfloat GLfloat f
[26]
GLuint index
GLuint color
[setDefaultFactory]
GLboolean GLuint group
GLfloat n
GLfloat GLfloat GLfloat GLfloat h
GLuint object
[6]
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
QFrame frame
[0]
static void writeIndent(QTextStream &ts, int indent)
Definition xliff.cpp:73