diff options
-rw-r--r-- | src/3rdparty/android/extract.h | 117 | ||||
-rw-r--r-- | src/android/jar/jar.pri | 3 | ||||
-rw-r--r-- | src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java | 1344 | ||||
-rw-r--r-- | src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java | 6 | ||||
-rw-r--r-- | src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java | 17 | ||||
-rw-r--r-- | src/plugins/platforms/android/android.pro | 7 | ||||
-rw-r--r-- | src/plugins/platforms/android/extract.cpp | 135 |
7 files changed, 1625 insertions, 4 deletions
diff --git a/src/3rdparty/android/extract.h b/src/3rdparty/android/extract.h new file mode 100644 index 0000000000..f7928e20a8 --- /dev/null +++ b/src/3rdparty/android/extract.h @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2005 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef EXTRACT_H +#define EXTRACT_H + +#include <cstdint> +#include <cstring> +// shamelessly stolen from ResourceTypes.h Android's sources +/** + * This chunk specifies how to split an image into segments for + * scaling. + * + * There are J horizontal and K vertical segments. These segments divide + * the image into J*K regions as follows (where J=4 and K=3): + * + * F0 S0 F1 S1 + * +-----+----+------+-------+ + * S2| 0 | 1 | 2 | 3 | + * +-----+----+------+-------+ + * | | | | | + * | | | | | + * F2| 4 | 5 | 6 | 7 | + * | | | | | + * | | | | | + * +-----+----+------+-------+ + * S3| 8 | 9 | 10 | 11 | + * +-----+----+------+-------+ + * + * Each horizontal and vertical segment is considered to by either + * stretchable (marked by the Sx labels) or fixed (marked by the Fy + * labels), in the horizontal or vertical axis, respectively. In the + * above example, the first is horizontal segment (F0) is fixed, the + * next is stretchable and then they continue to alternate. Note that + * the segment list for each axis can begin or end with a stretchable + * or fixed segment. + * + * The relative sizes of the stretchy segments indicates the relative + * amount of stretchiness of the regions bordered by the segments. For + * example, regions 3, 7 and 11 above will take up more horizontal space + * than regions 1, 5 and 9 since the horizontal segment associated with + * the first set of regions is larger than the other set of regions. The + * ratios of the amount of horizontal (or vertical) space taken by any + * two stretchable slices is exactly the ratio of their corresponding + * segment lengths. + * + * xDivs and yDivs point to arrays of horizontal and vertical pixel + * indices. The first pair of Divs (in either array) indicate the + * starting and ending points of the first stretchable segment in that + * axis. The next pair specifies the next stretchable segment, etc. So + * in the above example xDiv[0] and xDiv[1] specify the horizontal + * coordinates for the regions labeled 1, 5 and 9. xDiv[2] and + * xDiv[3] specify the coordinates for regions 3, 7 and 11. Note that + * the leftmost slices always start at x=0 and the rightmost slices + * always end at the end of the image. So, for example, the regions 0, + * 4 and 8 (which are fixed along the X axis) start at x value 0 and + * go to xDiv[0] and slices 2, 6 and 10 start at xDiv[1] and end at + * xDiv[2]. + * + * The array pointed to by the colors field lists contains hints for + * each of the regions. They are ordered according left-to-right and + * top-to-bottom as indicated above. For each segment that is a solid + * color the array entry will contain that color value; otherwise it + * will contain NO_COLOR. Segments that are completely transparent + * will always have the value TRANSPARENT_COLOR. + * + * The PNG chunk type is "npTc". + */ +struct Res_png_9patch +{ + Res_png_9patch() : wasDeserialized(false), xDivs(NULL), + yDivs(NULL), colors(NULL) { } + + int8_t wasDeserialized; + int8_t numXDivs; + int8_t numYDivs; + int8_t numColors; + + // These tell where the next section of a patch starts. + // For example, the first patch includes the pixels from + // 0 to xDivs[0]-1 and the second patch includes the pixels + // from xDivs[0] to xDivs[1]-1. + // Note: allocation/free of these pointers is left to the caller. + int32_t* xDivs; + int32_t* yDivs; + + int32_t paddingLeft, paddingRight; + int32_t paddingTop, paddingBottom; + + enum { + // The 9 patch segment is not a solid color. + NO_COLOR = 0x00000001, + + // The 9 patch segment is completely transparent. + TRANSPARENT_COLOR = 0x00000000 + }; + // Note: allocation/free of this pointer is left to the caller. + uint32_t* colors; + + // Deserialize/Unmarshall the patch data + static Res_png_9patch* deserialize(const void* data); +}; + +#endif diff --git a/src/android/jar/jar.pri b/src/android/jar/jar.pri index 5906231c73..66feda1d56 100644 --- a/src/android/jar/jar.pri +++ b/src/android/jar/jar.pri @@ -12,7 +12,8 @@ JAVASOURCES += \ $$PATHPREFIX/QtMessageDialogHelper.java \ $$PATHPREFIX/QtNative.java \ $$PATHPREFIX/QtNativeLibrariesDir.java \ - $$PATHPREFIX/QtSurface.java + $$PATHPREFIX/QtSurface.java \ + $$PATHPREFIX/ExtractStyle.java # install target.path = $$[QT_INSTALL_PREFIX]/jar diff --git a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java new file mode 100644 index 0000000000..4544eebd33 --- /dev/null +++ b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java @@ -0,0 +1,1344 @@ +/**************************************************************************** +** +** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Android port of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +package org.qtproject.qt5.android; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.lang.reflect.Field; +import java.util.ArrayList; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.xmlpull.v1.XmlPullParser; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.Canvas; +import android.graphics.NinePatch; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ClipDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.GradientDrawable.Orientation; +import android.graphics.drawable.LayerDrawable; +import android.graphics.drawable.NinePatchDrawable; +import android.graphics.drawable.ScaleDrawable; +import android.graphics.drawable.StateListDrawable; +import android.os.Build; +import android.util.AttributeSet; +import android.util.Log; +import android.util.Xml; +import android.view.inputmethod.EditorInfo; + + +public class ExtractStyle { + + native static int[] extractChunkInfo(byte[] chunkData); + native static int[] extractNativeChunkInfo(int nativeChunk); + + Class<?> styleableClass = getStylableClass(); + final int[] EMPTY_STATE_SET = {}; + final int[] ENABLED_STATE_SET = {android.R.attr.state_enabled}; + final int[] FOCUSED_STATE_SET = {android.R.attr.state_focused}; + final int[] SELECTED_STATE_SET = {android.R.attr.state_selected}; + final int[] PRESSED_STATE_SET = {android.R.attr.state_pressed}; + final int[] WINDOW_FOCUSED_STATE_SET = {android.R.attr.state_window_focused}; + final int[] ENABLED_FOCUSED_STATE_SET = stateSetUnion(ENABLED_STATE_SET, FOCUSED_STATE_SET); + final int[] ENABLED_SELECTED_STATE_SET = stateSetUnion(ENABLED_STATE_SET, SELECTED_STATE_SET); + final int[] ENABLED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET); + final int[] FOCUSED_SELECTED_STATE_SET = stateSetUnion(FOCUSED_STATE_SET, SELECTED_STATE_SET); + final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET); + final int[] SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); + final int[] ENABLED_FOCUSED_SELECTED_STATE_SET = stateSetUnion(ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET); + final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET); + final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); + final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); + final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(ENABLED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); + final int[] PRESSED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_STATE_SET, WINDOW_FOCUSED_STATE_SET); + final int[] PRESSED_SELECTED_STATE_SET = stateSetUnion(PRESSED_STATE_SET, SELECTED_STATE_SET); + final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); + final int[] PRESSED_FOCUSED_STATE_SET = stateSetUnion(PRESSED_STATE_SET, FOCUSED_STATE_SET); + final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET); + final int[] PRESSED_FOCUSED_SELECTED_STATE_SET = stateSetUnion(PRESSED_FOCUSED_STATE_SET, SELECTED_STATE_SET); + final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); + final int[] PRESSED_ENABLED_STATE_SET = stateSetUnion(PRESSED_STATE_SET, ENABLED_STATE_SET); + final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET); + final int[] PRESSED_ENABLED_SELECTED_STATE_SET = stateSetUnion(PRESSED_ENABLED_STATE_SET, SELECTED_STATE_SET); + final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); + final int[] PRESSED_ENABLED_FOCUSED_STATE_SET = stateSetUnion(PRESSED_ENABLED_STATE_SET, FOCUSED_STATE_SET); + final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET); + final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET); + final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = stateSetUnion(PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET); + + + final int View_background = getField(styleableClass,"View_background"); + final int View_padding = getField(styleableClass,"View_padding"); + final int View_paddingLeft = getField(styleableClass,"View_paddingLeft"); + final int View_paddingTop = getField(styleableClass,"View_paddingTop"); + final int View_paddingRight = getField(styleableClass,"View_paddingRight"); + final int View_paddingBottom = getField(styleableClass,"View_paddingBottom"); + final int View_scrollX = getField(styleableClass,"View_scrollX"); + final int View_scrollY = getField(styleableClass,"View_scrollY"); + final int View_id = getField(styleableClass,"View_id"); + final int View_tag = getField(styleableClass,"View_tag"); + final int View_fitsSystemWindows = getField(styleableClass,"View_fitsSystemWindows"); + final int View_focusable = getField(styleableClass,"View_focusable"); + final int View_focusableInTouchMode = getField(styleableClass,"View_focusableInTouchMode"); + final int View_clickable = getField(styleableClass,"View_clickable"); + final int View_longClickable = getField(styleableClass,"View_longClickable"); + final int View_saveEnabled = getField(styleableClass,"View_saveEnabled"); + final int View_duplicateParentState = getField(styleableClass,"View_duplicateParentState"); + final int View_visibility = getField(styleableClass,"View_visibility"); + final int View_drawingCacheQuality = getField(styleableClass,"View_drawingCacheQuality"); + final int View_contentDescription = getField(styleableClass,"View_contentDescription"); + final int View_soundEffectsEnabled = getField(styleableClass,"View_soundEffectsEnabled"); + final int View_hapticFeedbackEnabled = getField(styleableClass,"View_hapticFeedbackEnabled"); + final int View_scrollbars = getField(styleableClass,"View_scrollbars"); + final int View_fadingEdge = getField(styleableClass,"View_fadingEdge"); + final int View_scrollbarStyle = getField(styleableClass,"View_scrollbarStyle"); + final int View_isScrollContainer = getField(styleableClass,"View_isScrollContainer"); + final int View_keepScreenOn = getField(styleableClass,"View_keepScreenOn"); + final int View_filterTouchesWhenObscured = getField(styleableClass,"View_filterTouchesWhenObscured"); + final int View_nextFocusLeft = getField(styleableClass,"View_nextFocusLeft"); + final int View_nextFocusRight = getField(styleableClass,"View_nextFocusRight"); + final int View_nextFocusUp = getField(styleableClass,"View_nextFocusUp"); + final int View_nextFocusDown = getField(styleableClass,"View_nextFocusDown"); + final int View_minWidth = getField(styleableClass,"View_minWidth"); + final int View_minHeight = getField(styleableClass,"View_minHeight"); + final int View_onClick = getField(styleableClass,"View_onClick"); + final int View_overScrollMode = getField(styleableClass,"View_overScrollMode"); + + final int TextAppearance_textColorHighlight = getField(styleableClass,"TextAppearance_textColorHighlight"); + final int TextAppearance_textColor = getField(styleableClass,"TextAppearance_textColor"); + final int TextAppearance_textColorHint = getField(styleableClass,"TextAppearance_textColorHint"); + final int TextAppearance_textColorLink = getField(styleableClass,"TextAppearance_textColorLink"); + final int TextAppearance_textSize = getField(styleableClass,"TextAppearance_textSize"); + final int TextAppearance_typeface = getField(styleableClass,"TextAppearance_typeface"); + final int TextAppearance_textStyle = getField(styleableClass,"TextAppearance_textStyle"); + final int TextAppearance_textAllCaps = getField(styleableClass,"TextAppearance_textAllCaps"); + final int TextView_editable = getField(styleableClass,"TextView_editable"); + final int TextView_inputMethod = getField(styleableClass,"TextView_inputMethod"); + final int TextView_numeric = getField(styleableClass,"TextView_numeric"); + final int TextView_digits = getField(styleableClass,"TextView_digits"); + final int TextView_phoneNumber = getField(styleableClass,"TextView_phoneNumber"); + final int TextView_autoText = getField(styleableClass,"TextView_autoText"); + final int TextView_capitalize = getField(styleableClass,"TextView_capitalize"); + final int TextView_bufferType = getField(styleableClass,"TextView_bufferType"); + final int TextView_selectAllOnFocus = getField(styleableClass,"TextView_selectAllOnFocus"); + final int TextView_autoLink = getField(styleableClass,"TextView_autoLink"); + final int TextView_linksClickable = getField(styleableClass,"TextView_linksClickable"); + final int TextView_drawableLeft = getField(styleableClass,"TextView_drawableLeft"); + final int TextView_drawableTop = getField(styleableClass,"TextView_drawableTop"); + final int TextView_drawableRight = getField(styleableClass,"TextView_drawableRight"); + final int TextView_drawableBottom = getField(styleableClass,"TextView_drawableBottom"); + final int TextView_drawableStart = getField(styleableClass,"TextView_drawableStart"); + final int TextView_drawableEnd = getField(styleableClass,"TextView_drawableEnd"); + final int TextView_drawablePadding = getField(styleableClass,"TextView_drawablePadding"); + final int TextView_textCursorDrawable = getField(styleableClass,"TextView_textCursorDrawable"); + final int TextView_maxLines = getField(styleableClass,"TextView_maxLines"); + final int TextView_maxHeight = getField(styleableClass,"TextView_maxHeight"); + final int TextView_lines = getField(styleableClass,"TextView_lines"); + final int TextView_height = getField(styleableClass,"TextView_height"); + final int TextView_minLines = getField(styleableClass,"TextView_minLines"); + final int TextView_minHeight = getField(styleableClass,"TextView_minHeight"); + final int TextView_maxEms = getField(styleableClass,"TextView_maxEms"); + final int TextView_maxWidth = getField(styleableClass,"TextView_maxWidth"); + final int TextView_ems = getField(styleableClass,"TextView_ems"); + final int TextView_width = getField(styleableClass,"TextView_width"); + final int TextView_minEms = getField(styleableClass,"TextView_minEms"); + final int TextView_minWidth = getField(styleableClass,"TextView_minWidth"); + final int TextView_gravity = getField(styleableClass,"TextView_gravity"); + final int TextView_hint = getField(styleableClass,"TextView_hint"); + final int TextView_text = getField(styleableClass,"TextView_text"); + final int TextView_scrollHorizontally = getField(styleableClass,"TextView_scrollHorizontally"); + final int TextView_singleLine = getField(styleableClass,"TextView_singleLine"); + final int TextView_ellipsize = getField(styleableClass,"TextView_ellipsize"); + final int TextView_marqueeRepeatLimit = getField(styleableClass,"TextView_marqueeRepeatLimit"); + final int TextView_includeFontPadding = getField(styleableClass,"TextView_includeFontPadding"); + final int TextView_cursorVisible = getField(styleableClass,"TextView_cursorVisible"); + final int TextView_maxLength = getField(styleableClass,"TextView_maxLength"); + final int TextView_textScaleX = getField(styleableClass,"TextView_textScaleX"); + final int TextView_freezesText = getField(styleableClass,"TextView_freezesText"); + final int TextView_shadowColor = getField(styleableClass,"TextView_shadowColor"); + final int TextView_shadowDx = getField(styleableClass,"TextView_shadowDx"); + final int TextView_shadowDy = getField(styleableClass,"TextView_shadowDy"); + final int TextView_shadowRadius = getField(styleableClass,"TextView_shadowRadius"); + final int TextView_enabled = getField(styleableClass,"TextView_enabled"); + final int TextView_textColorHighlight = getField(styleableClass,"TextView_textColorHighlight"); + final int TextView_textColor = getField(styleableClass,"TextView_textColor"); + final int TextView_textColorHint = getField(styleableClass,"TextView_textColorHint"); + final int TextView_textColorLink = getField(styleableClass,"TextView_textColorLink"); + final int TextView_textSize = getField(styleableClass,"TextView_textSize"); + final int TextView_typeface = getField(styleableClass,"TextView_typeface"); + final int TextView_textStyle = getField(styleableClass,"TextView_textStyle"); + final int TextView_password = getField(styleableClass,"TextView_password"); + final int TextView_lineSpacingExtra = getField(styleableClass,"TextView_lineSpacingExtra"); + final int TextView_lineSpacingMultiplier = getField(styleableClass,"TextView_lineSpacingMultiplier"); + final int TextView_inputType = getField(styleableClass,"TextView_inputType"); + final int TextView_imeOptions = getField(styleableClass,"TextView_imeOptions"); + final int TextView_imeActionLabel = getField(styleableClass,"TextView_imeActionLabel"); + final int TextView_imeActionId = getField(styleableClass,"TextView_imeActionId"); + final int TextView_privateImeOptions = getField(styleableClass,"TextView_privateImeOptions"); + final int TextView_textSelectHandleLeft = getField(styleableClass,"TextView_textSelectHandleLeft"); + final int TextView_textSelectHandleRight = getField(styleableClass,"TextView_textSelectHandleRight"); + final int TextView_textSelectHandle = getField(styleableClass,"TextView_textSelectHandle"); + final int TextView_textIsSelectable = getField(styleableClass,"TextView_textIsSelectable"); + final int TextView_textAllCaps = getField(styleableClass,"TextView_textAllCaps"); + + final int ImageView_src = getField(styleableClass,"ImageView_src"); + final int ImageView_baselineAlignBottom = getField(styleableClass,"ImageView_baselineAlignBottom"); + final int ImageView_adjustViewBounds = getField(styleableClass,"ImageView_adjustViewBounds"); + final int ImageView_maxWidth = getField(styleableClass,"ImageView_maxWidth"); + final int ImageView_maxHeight = getField(styleableClass,"ImageView_maxHeight"); + final int ImageView_scaleType = getField(styleableClass,"ImageView_scaleType"); + final int ImageView_tint = getField(styleableClass,"ImageView_tint"); + final int ImageView_cropToPadding = getField(styleableClass,"ImageView_cropToPadding"); + + final Resources.Theme m_theme; + final String m_extractPath; + Context m_context; + final int defaultBackgroundColor; + final int defaultTextColor; + + class FakeCanvas extends Canvas { + int[] chunkData = null; + class Size { + public int s,e; + Size(int start, int end) + { + s=start; + e=end; + } + } + + public boolean isHardwareAccelerated() { + return true; + } + + public void drawPatch(Bitmap bmp, byte[] chunks, RectF dst, Paint paint) { + chunkData = extractChunkInfo(chunks); + } + } + + + + private int[] stateSetUnion(final int[] stateSet1, final int[] stateSet2) + { + try + { + final int stateSet1Length = stateSet1.length; + final int stateSet2Length = stateSet2.length; + final int[] newSet = new int[stateSet1Length + stateSet2Length]; + int k = 0; + int i = 0; + int j = 0; + // This is a merge of the two input state sets and assumes that the + // input sets are sorted by the order imposed by ViewDrawableStates. + int[] viewDrawableStatesState=(int[]) styleableClass.getDeclaredField("ViewDrawableStates").get(null); + for (int viewState : viewDrawableStatesState) + { + if (i < stateSet1Length && stateSet1[i] == viewState) + { + newSet[k++] = viewState; + i++; + } else if (j < stateSet2Length && stateSet2[j] == viewState) { + newSet[k++] = viewState; + j++; + } + if (k > 1) { + assert(newSet[k - 1] > newSet[k - 2]); + } + } + return newSet; + } + catch(Exception e) + { + e.printStackTrace(); + } + return null; + } + + private Class<?> getStylableClass() { + try { + return Class.forName("android.R$styleable"); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + return null; + } + + int getField(Class<?> clazz, String fieldName) + { + try { + return clazz.getDeclaredField(fieldName).getInt(null); + } catch (Exception e) { + e.printStackTrace(); + } + return -1; + } + + JSONObject getColorStateList(ColorStateList colorList) + { + JSONObject json = new JSONObject(); + try + { + json.put("EMPTY_STATE_SET", colorList.getColorForState(EMPTY_STATE_SET, 0)); + json.put("WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(WINDOW_FOCUSED_STATE_SET, 0)); + json.put("SELECTED_STATE_SET", colorList.getColorForState(SELECTED_STATE_SET, 0)); + json.put("SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(SELECTED_WINDOW_FOCUSED_STATE_SET, 0)); + json.put("FOCUSED_STATE_SET", colorList.getColorForState(FOCUSED_STATE_SET, 0)); + json.put("FOCUSED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(FOCUSED_WINDOW_FOCUSED_STATE_SET, 0)); + json.put("FOCUSED_SELECTED_STATE_SET", colorList.getColorForState(FOCUSED_SELECTED_STATE_SET, 0)); + json.put("FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0)); + json.put("ENABLED_STATE_SET", colorList.getColorForState(ENABLED_STATE_SET, 0)); + json.put("ENABLED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(ENABLED_WINDOW_FOCUSED_STATE_SET, 0)); + json.put("ENABLED_SELECTED_STATE_SET", colorList.getColorForState(ENABLED_SELECTED_STATE_SET, 0)); + json.put("ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0)); + json.put("ENABLED_FOCUSED_STATE_SET", colorList.getColorForState(ENABLED_FOCUSED_STATE_SET, 0)); + json.put("ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET, 0)); + json.put("ENABLED_FOCUSED_SELECTED_STATE_SET", colorList.getColorForState(ENABLED_FOCUSED_SELECTED_STATE_SET, 0)); + json.put("ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0)); + json.put("PRESSED_STATE_SET", colorList.getColorForState(PRESSED_STATE_SET, 0)); + json.put("PRESSED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_WINDOW_FOCUSED_STATE_SET, 0)); + json.put("PRESSED_SELECTED_STATE_SET", colorList.getColorForState(PRESSED_SELECTED_STATE_SET, 0)); + json.put("PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0)); + json.put("PRESSED_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_FOCUSED_STATE_SET, 0)); + json.put("PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET, 0)); + json.put("PRESSED_FOCUSED_SELECTED_STATE_SET", colorList.getColorForState(PRESSED_FOCUSED_SELECTED_STATE_SET, 0)); + json.put("PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0)); + json.put("PRESSED_ENABLED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_STATE_SET, 0)); + json.put("PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET, 0)); + json.put("PRESSED_ENABLED_SELECTED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_SELECTED_STATE_SET, 0)); + json.put("PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0)); + json.put("PRESSED_ENABLED_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_FOCUSED_STATE_SET, 0)); + json.put("PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET, 0)); + json.put("PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, 0)); + json.put("PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET", colorList.getColorForState(PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, 0)); + } catch (JSONException e) { + e.printStackTrace(); + } + + return json; + } + + final int [] DrawableStates ={android.R.attr.state_active, android.R.attr.state_checked + , android.R.attr.state_enabled, android.R.attr.state_focused + , android.R.attr.state_pressed, android.R.attr.state_selected + , android.R.attr.state_window_focused, 16908288, 16843597, 16843518}; + final String[] DrawableStatesLabels = {"active", "checked", "enabled", "focused", "pressed", "selected", "window_focused", "background", "multiline", "activated"}; + final String[] DisableDrawableStatesLabels = {"inactive", "unchecked", "disabled", "not_focused", "no_pressed", "unselected", "window_not_focused", "background", "multiline", "activated"}; + + String getFileName(String file, String[] states) + { + for (String state: states) + file+="__"+state; + return file; + } + + String getStatesName(String[] states) + { + String statesName=""; + for (String state: states) + { + if (statesName.length()>0) + statesName+="__"; + statesName += state; + } + return statesName; + } + + void addDrawableItemIfNotExists(JSONObject json, ArrayList<Integer> list, Drawable item, String[] states, String filename) + { + for (Integer it : list) + { + if (it.equals(item.hashCode())) + return; + } + list.add(item.hashCode()); + try { + json.put(getStatesName(states), getDrawable(item, getFileName(filename, states))); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + void addSolution(String filename, JSONObject json, int c, Drawable drawable, ArrayList<Integer> drawableList, int u) + { + int pos=0; + int states[] = new int[c]; + String [] statesText = new String[c]; + + for (int n= 0;u > 0;++n, u>>= 1) + if ((u & 1) > 0) + { + statesText[pos]=DrawableStatesLabels[n]; + states[pos++]=DrawableStates[n]; + } + drawable.setState(states); + addDrawableItemIfNotExists(json, drawableList, drawable.getCurrent(), statesText, filename); + } + + int bitCount(int u) + { + int n; + for (n= 0;u > 0;++n, u&= (u - 1)); + return n; + } + + Object getStateListDrawable_old(Drawable drawable, String filename) + { + JSONObject json = new JSONObject(); + ArrayList<Integer> drawableList= new ArrayList<Integer>(); + drawable.setState(EMPTY_STATE_SET); + try { + json.put("empty", getDrawable(drawable.getCurrent(), filename)); + drawableList.add(drawable.getCurrent().hashCode()); + } catch (JSONException e) { + e.printStackTrace(); + } + for (int c = 1;c<=DrawableStates.length;c++) + for (int u= 0;u < 1 << DrawableStates.length;u++) + if (bitCount(u) == c) + addSolution(filename, json, c, drawable, drawableList, u); + return json; + } + + JSONObject getStatesList(int [] states) throws JSONException + { + JSONObject json = new JSONObject(); + for (int s : states) + { + boolean found=false; + for (int d = 0;d<DrawableStates.length;d++) + { + if (s==DrawableStates[d]) + { + json.put(DrawableStatesLabels[d], true); + found=true; + break; + } + else if (s==-DrawableStates[d]) + { + json.put(DrawableStatesLabels[d], false); + + found=true; + break; + } + } + if (!found) + { + json.put("unhandled_state_"+s,s>0); + } + } + return json; + } + + String getStatesName(int [] states) + { + String statesName=""; + for (int s : states) + { + boolean found=false; + for (int d = 0;d<DrawableStates.length;d++) + { + if (s==DrawableStates[d]) + { + if (statesName.length()>0) + statesName+="__"; + statesName+=DrawableStatesLabels[d]; + found=true; + break; + } + else if (s==-DrawableStates[d]) + { + if (statesName.length()>0) + statesName+="__"; + statesName+=DisableDrawableStatesLabels[d]; + found=true; + break; + } + } + if (!found) + { + if (statesName.length()>0) + statesName+=";"; + statesName+=s; + } + } + if (statesName.length()>0) + return statesName; + return "empty"; + } + + private JSONObject getLayerDrawable(Object drawable, String filename) + { + JSONObject json = new JSONObject(); + LayerDrawable layers = (LayerDrawable) drawable; + final int nr=layers.getNumberOfLayers(); + try { + JSONArray array =new JSONArray(); + for (int i = 0; i < nr; i++) + { + JSONObject layerJsonObject=getDrawable(layers.getDrawable(i), filename+"__"+layers.getId(i)); + layerJsonObject.put("id", layers.getId(i)); + array.put(layerJsonObject); + } + json.put("type", "layer"); + Rect padding = new Rect(); + if (layers.getPadding(padding)) + json.put("padding", getJsonRect(padding)); + json.put("layers", array); + } catch (JSONException e) { + e.printStackTrace(); + } + return json; + } + + private JSONObject getStateListDrawable(Object drawable, String filename) + { + JSONObject json = new JSONObject(); + try { + StateListDrawable stateList = (StateListDrawable) drawable; + final int numStates = (Integer) StateListDrawable.class.getMethod("getStateCount").invoke(stateList); + JSONArray array =new JSONArray(); + for (int i = 0; i < numStates; i++) + { + JSONObject stateJson = new JSONObject(); + final Drawable d = (Drawable) StateListDrawable.class.getMethod("getStateDrawable", Integer.TYPE).invoke(stateList, i); + final int [] states = (int[]) StateListDrawable.class.getMethod("getStateSet", Integer.TYPE).invoke(stateList, i); + stateJson.put("states", getStatesList(states)); + stateJson.put("drawable", getDrawable(d, filename+"__"+getStatesName(states))); + array.put(stateJson); + } + json.put("type", "stateslist"); + Rect padding = new Rect(); + if (stateList.getPadding(padding)) + json.put("padding", getJsonRect(padding)); + json.put("stateslist", array); + } catch (Exception e) { + e.printStackTrace(); + } + return json; + } + + private JSONObject getGradientDrawable(GradientDrawable drawable) { + JSONObject json = new JSONObject(); + try { + json.put("type", "gradient"); + Object obj=drawable.getConstantState(); + Class<?> gradientStateClass=obj.getClass(); + json.put("shape",gradientStateClass.getField("mShape").getInt(obj)); + json.put("gradient",gradientStateClass.getField("mGradient").getInt(obj)); + GradientDrawable.Orientation orientation=(Orientation) gradientStateClass.getField("mOrientation").get(obj); + json.put("orientation",orientation.name()); + int [] intArray=(int[]) gradientStateClass.getField("mColors").get(obj); + json.put("colors",getJsonArray(intArray, 0, intArray.length)); + json.put("positions",getJsonArray((float[]) gradientStateClass.getField("mPositions").get(obj))); + json.put("solidColor",gradientStateClass.getField("mSolidColor").getInt(obj)); + json.put("strokeWidth",gradientStateClass.getField("mStrokeWidth").getInt(obj)); + json.put("strokeColor",gradientStateClass.getField("mStrokeColor").getInt(obj)); + json.put("strokeDashWidth",gradientStateClass.getField("mStrokeDashWidth").getFloat(obj)); + json.put("strokeDashGap",gradientStateClass.getField("mStrokeDashGap").getFloat(obj)); + json.put("radius",gradientStateClass.getField("mRadius").getFloat(obj)); + float [] floatArray=(float[]) gradientStateClass.getField("mRadiusArray").get(obj); + if (floatArray!=null) + json.put("radiusArray",getJsonArray(floatArray)); + Rect rc= (Rect) gradientStateClass.getField("mPadding").get(obj); + if (rc!=null) + json.put("padding",getJsonRect(rc)); + json.put("width",gradientStateClass.getField("mWidth").getInt(obj)); + json.put("height",gradientStateClass.getField("mHeight").getInt(obj)); + json.put("innerRadiusRatio",gradientStateClass.getField("mInnerRadiusRatio").getFloat(obj)); + json.put("thicknessRatio",gradientStateClass.getField("mThicknessRatio").getFloat(obj)); + json.put("innerRadius",gradientStateClass.getField("mInnerRadius").getInt(obj)); + json.put("thickness",gradientStateClass.getField("mThickness").getInt(obj)); + } catch (Exception e) { + e.printStackTrace(); + } + return json; + } + + private JSONObject getJsonRect(Rect rect) throws JSONException + { + JSONObject jsonRect = new JSONObject(); + jsonRect.put("left", rect.left); + jsonRect.put("top", rect.top); + jsonRect.put("right", rect.right); + jsonRect.put("bottom", rect.bottom); + return jsonRect; + + } + + private JSONArray getJsonArray(int[] array, int pos, int len) + { + JSONArray a = new JSONArray(); + final int l = pos+len; + for (int i=pos; i<l;i++) + a.put(array[i]); + return a; + } + + private JSONArray getJsonArray(float[] array) throws JSONException + { + JSONArray a = new JSONArray(); + if (array != null) + for (float val: array) + a.put(val); + return a; + } + + private JSONObject getJsonChunkInfo(int[] chunkData) throws JSONException + { + JSONObject jsonRect = new JSONObject(); + jsonRect.put("xdivs", getJsonArray(chunkData, 3, chunkData[0])); + jsonRect.put("ydivs", getJsonArray(chunkData, 3 + chunkData[0], chunkData[1])); + jsonRect.put("colors", getJsonArray(chunkData, 3 + chunkData[0] + chunkData[1], chunkData[2])); + return jsonRect; + } + + private JSONObject findPatchesMarings(Drawable d) throws JSONException, NoSuchFieldException, IllegalAccessException + { + Field mNinePatch = ((NinePatchDrawable)d).getClass().getDeclaredField("mNinePatch"); + mNinePatch.setAccessible(true); + NinePatch np = (NinePatch) mNinePatch.get(d); + if (Build.VERSION.SDK_INT < 19) + { + Field mChunk = np.getClass().getDeclaredField("mChunk"); + mChunk.setAccessible(true); + return getJsonChunkInfo(extractChunkInfo((byte[]) mChunk.get(np))); + } + else + { + Field mNativeChunk = np.getClass().getDeclaredField("mNativeChunk"); + mNativeChunk.setAccessible(true); + return getJsonChunkInfo(extractNativeChunkInfo(mNativeChunk.getInt(np))); + } + } + + public JSONObject getDrawable(Object drawable, String filename) + { + JSONObject json = new JSONObject(); + Bitmap bmp; + if (drawable instanceof Bitmap) + bmp = (Bitmap) drawable; + else + { + if (drawable instanceof BitmapDrawable) + bmp = ((BitmapDrawable)drawable).getBitmap(); + else + { + if (drawable instanceof ScaleDrawable) + { + return getDrawable(((ScaleDrawable)drawable).getDrawable(), filename); + } + if (drawable instanceof LayerDrawable) + { + return getLayerDrawable(drawable, filename); + } + if (drawable instanceof StateListDrawable) + { + return getStateListDrawable(drawable, filename); + } + if (drawable instanceof GradientDrawable) + { + return getGradientDrawable((GradientDrawable) drawable); + } + if (drawable instanceof ClipDrawable) + { + try { + json.put("type", "clipDrawable"); + Drawable.ConstantState dcs = ((ClipDrawable)drawable).getConstantState(); + Field f = dcs.getClass().getDeclaredField("mDrawable"); + f.setAccessible(true); + json.put("drawable", getDrawable(f.get(dcs), filename)); + Rect padding = new Rect(); + if (((Drawable) drawable).getPadding(padding)) + json.put("padding", getJsonRect(padding)); + } catch (Exception e) { + e.printStackTrace(); + } + return json; + } + if (drawable instanceof ColorDrawable) + { + bmp = Bitmap.createBitmap(1, 1, Config.ARGB_8888); + Drawable d = (Drawable) drawable; + d.setBounds(0, 0, 1, 1); + d.draw(new Canvas(bmp)); + Rect padding = new Rect(); + try { + json.put("type", "color"); + json.put("color", bmp.getPixel(0, 0)); + if (d.getPadding(padding)) + json.put("padding", getJsonRect(padding)); + } catch (JSONException e) { + e.printStackTrace(); + } + return json; + } + else + { + Drawable d = (Drawable) drawable; + int w=d.getIntrinsicWidth(); + int h=d.getIntrinsicHeight(); + d.setLevel(10000); + if (w<1 || h< 1) + { + w=100; + h=100; + } + bmp = Bitmap.createBitmap(w, h, Config.ARGB_8888); + d.setBounds(0, 0, w, h); + d.draw(new Canvas(bmp)); + if (drawable instanceof NinePatchDrawable) + { + NinePatchDrawable npd = (NinePatchDrawable) drawable; + try { + json.put("type", "9patch"); + json.put("drawable", getDrawable(bmp, filename)); + Rect padding = new Rect(); + if (npd.getPadding(padding)) + json.put("padding", getJsonRect(padding)); + json.put("chunkInfo", findPatchesMarings(d)); + return json; + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + } + FileOutputStream out; + try { + filename = m_extractPath+filename+".png"; + out = new FileOutputStream(filename); + bmp.compress(Bitmap.CompressFormat.PNG, 100, out); + out.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + try { + json.put("type", "image"); + json.put("path", filename); + json.put("width", bmp.getWidth()); + json.put("height", bmp.getHeight()); +// MinistroActivity.nativeChmode(filename, 0644); + } catch (JSONException e) { + e.printStackTrace(); + } + return json; + } + + public void extractViewInformations(String styleName, int styleId, JSONObject json, String qtClassName, AttributeSet attribSet) + { + try { + int[] viewAttrs; + viewAttrs = (int[]) styleableClass.getDeclaredField("View").get(null); + TypedArray a =m_theme.obtainStyledAttributes(attribSet, viewAttrs, styleId, 0); + + if (null != qtClassName) + json.put("qtClass", qtClassName); + json.put("defaultBackgroundColor", defaultBackgroundColor); + json.put("defaultTextColorPrimary", defaultTextColor); + final int N = a.getIndexCount(); + for (int i = 0; i < N; i++) { + int attr = a.getIndex(i); + if (attr == View_background) + json.put("View_background", getDrawable(a.getDrawable(attr), styleName + "_View_background")); + else if (attr == View_padding) + json.put("View_padding", a.getDimensionPixelSize(attr, -1)); + else if (attr == View_paddingLeft) + json.put("View_paddingLeft", a.getDimensionPixelSize(attr, -1)); + else if (attr == View_paddingTop) + json.put("View_paddingTop", a.getDimensionPixelSize(attr, -1)); + else if (attr == View_paddingRight) + json.put("View_paddingRight", a.getDimensionPixelSize(attr, -1)); + else if (attr == View_paddingBottom) + json.put("View_paddingBottom", a.getDimensionPixelSize(attr, -1)); + else if (attr == View_scrollX) + json.put("View_paddingBottom", a.getDimensionPixelOffset(attr, 0)); + else if (attr == View_scrollY) + json.put("View_scrollY", a.getDimensionPixelOffset(attr, 0)); + else if (attr == View_id) + json.put("View_id", a.getResourceId(attr, -1)); + else if (attr == View_tag) + json.put("View_tag", a.getText(attr)); + else if (attr == View_fitsSystemWindows) + json.put("View_fitsSystemWindows", a.getBoolean(attr, false)); + else if (attr == View_focusable) + json.put("View_focusable", a.getBoolean(attr, false)); + else if (attr == View_focusableInTouchMode) + json.put("View_focusableInTouchMode", a.getBoolean(attr, false)); + else if (attr == View_clickable) + json.put("View_clickable", a.getBoolean(attr, false)); + else if (attr == View_longClickable) + json.put("View_longClickable", a.getBoolean(attr, false)); + else if (attr == View_saveEnabled) + json.put("View_saveEnabled", a.getBoolean(attr, true)); + else if (attr == View_duplicateParentState) + json.put("View_duplicateParentState", a.getBoolean(attr, false)); + else if (attr == View_visibility) + json.put("View_visibility", a.getInt(attr, 0)); + else if (attr == View_drawingCacheQuality) + json.put("View_drawingCacheQuality", a.getInt(attr, 0)); + else if (attr == View_drawingCacheQuality) + json.put("View_contentDescription", a.getString(attr)); + else if (attr == View_soundEffectsEnabled) + json.put("View_soundEffectsEnabled", a.getBoolean(attr, true)); + else if (attr == View_hapticFeedbackEnabled) + json.put("View_hapticFeedbackEnabled", a.getBoolean(attr, true)); + else if (attr == View_scrollbars) + json.put("View_scrollbars", a.getInt(attr, 0)); + else if (attr == View_fadingEdge) + json.put("View_fadingEdge", a.getInt(attr, 0)); + else if (attr == View_scrollbarStyle) + json.put("View_scrollbarStyle", a.getInt(attr, 0)); + else if (attr == View_isScrollContainer) + json.put("View_isScrollContainer", a.getBoolean(attr, false)); + else if (attr == View_keepScreenOn) + json.put("View_keepScreenOn", a.getBoolean(attr, false)); + else if (attr == View_filterTouchesWhenObscured) + json.put("View_filterTouchesWhenObscured", a.getBoolean(attr, false)); + else if (attr == View_nextFocusLeft) + json.put("View_nextFocusLeft", a.getResourceId(attr, -1)); + else if (attr == View_nextFocusRight) + json.put("View_nextFocusRight", a.getResourceId(attr, -1)); + else if (attr == View_nextFocusUp) + json.put("View_nextFocusUp", a.getResourceId(attr, -1)); + else if (attr == View_nextFocusDown) + json.put("View_nextFocusDown", a.getResourceId(attr, -1)); + else if (attr == View_minWidth) + json.put("View_minWidth", a.getDimensionPixelSize(attr, 0)); + else if (attr == View_minHeight) + json.put("View_minHeight", a.getDimensionPixelSize(attr, 0)); + else if (attr == View_onClick) + json.put("View_onClick", a.getString(attr)); + else if (attr == View_overScrollMode) + json.put("View_overScrollMode", a.getInt(attr, 1)); + } + a.recycle(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public JSONObject extractTextAppearanceInformations(String styleName, String qtClass, AttributeSet attribSet, int textAppearance ) + { + JSONObject json = new JSONObject(); + try + { + int textColorHighlight = 0; // + ColorStateList textColor = null; // + ColorStateList textColorHint = null; // + ColorStateList textColorLink = null; // + int textSize = 15; // + int typefaceIndex = -1; // + int styleIndex = -1; + boolean allCaps = false; + + Class<?> attrClass= Class.forName("android.R$attr"); + int styleId = attrClass.getDeclaredField(styleName).getInt(null); + + extractViewInformations(styleName, styleId, json, qtClass, attribSet); + + int[] textViewAttrs=(int[]) styleableClass.getDeclaredField("TextView").get(null); + TypedArray a =m_theme.obtainStyledAttributes(null, textViewAttrs, styleId, 0); + + TypedArray appearance = null; + if (-1==textAppearance) + textAppearance = a.getResourceId(styleableClass.getDeclaredField("TextView_textAppearance").getInt(null), -1); + + if (textAppearance != -1) + appearance = m_theme.obtainStyledAttributes(textAppearance, (int[]) styleableClass.getDeclaredField("TextAppearance").get(null)); + + if (appearance != null) + { + int n = appearance.getIndexCount(); + for (int i = 0; i < n; i++) + { + int attr = appearance.getIndex(i); + if (attr == TextAppearance_textColorHighlight) + textColorHighlight = appearance.getColor(attr, textColorHighlight); + else if (attr == TextAppearance_textColor) + textColor = appearance.getColorStateList(attr); + else if (attr == TextAppearance_textColorHint) + textColorHint = appearance.getColorStateList(attr); + else if (attr == TextAppearance_textColorLink) + textColorLink = appearance.getColorStateList(attr); + else if (attr == TextAppearance_textSize) + textSize = appearance.getDimensionPixelSize(attr, textSize); + else if (attr == TextAppearance_typeface) + typefaceIndex = appearance.getInt(attr, -1); + else if (attr == TextAppearance_textStyle) + styleIndex = appearance.getInt(attr, -1); + else if (attr == TextAppearance_textAllCaps) + allCaps = appearance.getBoolean(attr, false); + } + appearance.recycle(); + } + + int n = a.getIndexCount(); + + for (int i = 0; i < n; i++) { + int attr = a.getIndex(i); + + if (attr == TextView_editable) + json.put("TextView_editable", a.getBoolean(attr, false)); + else if (attr == TextView_inputMethod) + json.put("TextView_inputMethod", a.getText(attr)); + else if (attr == TextView_numeric) + json.put("TextView_numeric", a.getInt(attr, 0)); + else if (attr == TextView_digits) + json.put("TextView_digits", a.getText(attr)); + else if (attr == TextView_phoneNumber) + json.put("TextView_phoneNumber", a.getBoolean(attr, false)); + else if (attr == TextView_autoText) + json.put("TextView_autoText", a.getBoolean(attr, false)); + else if (attr == TextView_capitalize) + json.put("TextView_capitalize", a.getInt(attr, -1)); + else if (attr == TextView_bufferType) + json.put("TextView_bufferType", a.getInt(attr, 0)); + else if (attr == TextView_selectAllOnFocus) + json.put("TextView_selectAllOnFocus", a.getBoolean(attr, false)); + else if (attr == TextView_autoLink) + json.put("TextView_autoLink", a.getInt(attr, 0)); + else if (attr == TextView_linksClickable) + json.put("TextView_linksClickable", a.getBoolean(attr, true)); + else if (attr == TextView_linksClickable) + json.put("TextView_linksClickable", a.getBoolean(attr, true)); + else if (attr == TextView_drawableLeft) + json.put("TextView_drawableLeft", getDrawable(a.getDrawable(attr), styleName + "_TextView_drawableLeft")); + else if (attr == TextView_drawableTop) + json.put("TextView_drawableTop", getDrawable(a.getDrawable(attr), styleName + "_TextView_drawableTop")); + else if (attr == TextView_drawableRight) + json.put("TextView_drawableRight", getDrawable(a.getDrawable(attr), styleName + "_TextView_drawableRight")); + else if (attr == TextView_drawableBottom) + json.put("TextView_drawableBottom", getDrawable(a.getDrawable(attr), styleName + "_TextView_drawableBottom")); + else if (attr == TextView_drawableStart) + json.put("TextView_drawableStart", getDrawable(a.getDrawable(attr), styleName + "_TextView_drawableStart")); + else if (attr == TextView_drawableEnd) + json.put("TextView_drawableEnd", getDrawable(a.getDrawable(attr), styleName + "_TextView_drawableEnd")); + else if (attr == TextView_drawablePadding) + json.put("TextView_drawablePadding", a.getDimensionPixelSize(attr, 0)); + else if (attr == TextView_textCursorDrawable) + json.put("TextView_textCursorDrawable", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textCursorDrawable")); + else if (attr == TextView_maxLines) + json.put("TextView_maxLines", a.getInt(attr, -1)); + else if (attr == TextView_maxHeight) + json.put("TextView_maxHeight", a.getDimensionPixelSize(attr, -1)); + else if (attr == TextView_lines) + json.put("TextView_lines", a.getInt(attr, -1)); + else if (attr == TextView_height) + json.put("TextView_height", a.getDimensionPixelSize(attr, -1)); + else if (attr == TextView_minLines) + json.put("TextView_minLines", a.getInt(attr, -1)); + else if (attr == TextView_minHeight) + json.put("TextView_minHeight", a.getDimensionPixelSize(attr, -1)); + else if (attr == TextView_maxEms) + json.put("TextView_maxEms", a.getInt(attr, -1)); + else if (attr == TextView_maxWidth) + json.put("TextView_maxWidth", a.getDimensionPixelSize(attr, -1)); + else if (attr == TextView_ems) + json.put("TextView_ems", a.getInt(attr, -1)); + else if (attr == TextView_width) + json.put("TextView_width", a.getDimensionPixelSize(attr, -1)); + else if (attr == TextView_minEms) + json.put("TextView_minEms", a.getInt(attr, -1)); + else if (attr == TextView_minWidth) + json.put("TextView_minWidth", a.getDimensionPixelSize(attr, -1)); + else if (attr == TextView_gravity) + json.put("TextView_gravity", a.getInt(attr, -1)); + else if (attr == TextView_hint) + json.put("TextView_hint", a.getText(attr)); + else if (attr == TextView_text) + json.put("TextView_text", a.getText(attr)); + else if (attr == TextView_scrollHorizontally) + json.put("TextView_scrollHorizontally", a.getBoolean(attr, false)); + else if (attr == TextView_singleLine) + json.put("TextView_singleLine", a.getBoolean(attr, false)); + else if (attr == TextView_ellipsize) + json.put("TextView_ellipsize", a.getInt(attr, -1)); + else if (attr == TextView_marqueeRepeatLimit) + json.put("TextView_marqueeRepeatLimit", a.getInt(attr, 3)); + else if (attr == TextView_includeFontPadding) + json.put("TextView_includeFontPadding", a.getBoolean(attr, true)); + else if (attr == TextView_cursorVisible) + json.put("TextView_cursorVisible", a.getBoolean(attr, true)); + else if (attr == TextView_maxLength) + json.put("TextView_maxLength", a.getInt(attr, -1)); + else if (attr == TextView_textScaleX) + json.put("TextView_textScaleX", a.getFloat(attr, 1.0f)); + else if (attr == TextView_freezesText) + json.put("TextView_freezesText", a.getBoolean(attr, false)); + else if (attr == TextView_shadowColor) + json.put("TextView_shadowColor", a.getInt(attr, 0)); + else if (attr == TextView_shadowDx) + json.put("TextView_shadowDx", a.getFloat(attr, 0)); + else if (attr == TextView_shadowDy) + json.put("TextView_shadowDy", a.getFloat(attr, 0)); + else if (attr == TextView_shadowRadius) + json.put("TextView_shadowRadius", a.getFloat(attr, 0)); + else if (attr == TextView_enabled) + json.put("TextView_enabled", a.getBoolean(attr,true)); + else if (attr == TextView_textColorHighlight) + textColorHighlight = a.getColor(attr, textColorHighlight); + else if (attr == TextView_textColor) + textColor = a.getColorStateList(attr); + else if (attr == TextView_textColorHint) + textColorHint = a.getColorStateList(attr); + else if (attr == TextView_textColorLink) + textColorLink = a.getColorStateList(attr); + else if (attr == TextView_textSize) + textSize = a.getDimensionPixelSize(attr, textSize); + else if (attr == TextView_typeface) + typefaceIndex = a.getInt(attr, typefaceIndex); + else if (attr == TextView_textStyle) + styleIndex = a.getInt(attr, styleIndex); + else if (attr == TextView_password) + json.put("TextView_password", a.getBoolean(attr,false)); + else if (attr == TextView_lineSpacingExtra) + json.put("TextView_lineSpacingExtra", a.getDimensionPixelSize(attr, 0)); + else if (attr == TextView_lineSpacingMultiplier) + json.put("TextView_lineSpacingMultiplier", a.getFloat(attr, 1.0f)); + else if (attr == TextView_inputType) + json.put("TextView_inputType", a.getInt(attr, EditorInfo.TYPE_NULL)); + else if (attr == TextView_imeOptions) + json.put("TextView_imeOptions", a.getInt(attr, EditorInfo.IME_NULL)); + else if (attr == TextView_imeActionLabel) + json.put("TextView_imeActionLabel", a.getText(attr)); + else if (attr == TextView_imeActionId) + json.put("TextView_imeActionId", a.getInt(attr,0)); + else if (attr == TextView_privateImeOptions) + json.put("TextView_privateImeOptions", a.getString(attr)); + else if (attr == TextView_textSelectHandleLeft && styleName.equals("textViewStyle")) + json.put("TextView_textSelectHandleLeft", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textSelectHandleLeft")); + else if (attr == TextView_textSelectHandleRight && styleName.equals("textViewStyle")) + json.put("TextView_textSelectHandleRight", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textSelectHandleRight")); + else if (attr == TextView_textSelectHandle && styleName.equals("textViewStyle")) + json.put("TextView_textSelectHandle", getDrawable(m_context.getResources().getDrawable(a.getResourceId(attr, 0)), styleName + "_TextView_textSelectHandle")); + else if (attr == TextView_textIsSelectable) + json.put("TextView_textIsSelectable", a.getBoolean(attr, false)); + else if (attr == TextView_textAllCaps) + allCaps = a.getBoolean(attr, false); + } + a.recycle(); + + json.put("TextAppearance_textColorHighlight",textColorHighlight); + json.put("TextAppearance_textColor", getColorStateList(textColor)); + json.put("TextAppearance_textColorHint", getColorStateList(textColorHint)); + json.put("TextAppearance_textColorLink", getColorStateList(textColorLink)); + json.put("TextAppearance_textSize",textSize); + json.put("TextAppearance_typeface",typefaceIndex); + json.put("TextAppearance_textStyle",styleIndex); + json.put("TextAppearance_textAllCaps",allCaps); + } + catch(Exception e) + { + e.printStackTrace(); + } + return json; + } + + final String[] sScaleTypeArray = { + "MATRIX", + "FIT_XY", + "FIT_START", + "FIT_CENTER", + "FIT_END", + "CENTER", + "CENTER_CROP", + "CENTER_INSIDE" + }; + + public JSONObject extractImageViewInformations(String styleName, String qtClassName ) + { + JSONObject json = new JSONObject(); + try + { + Class<?> attrClass= Class.forName("android.R$attr"); + int styleId = attrClass.getDeclaredField(styleName).getInt(null); + + extractViewInformations(styleName, styleId, json, qtClassName, null); + + int[] imageViewAttrs=(int[]) styleableClass.getDeclaredField("ImageView").get(null); + TypedArray a =m_theme.obtainStyledAttributes(null, imageViewAttrs, styleId, 0); + Drawable d = a.getDrawable(ImageView_src); + if (d != null) + json.put("ImageView_src", getDrawable(d, styleName + "_ImageView_src")); + + json.put("ImageView_baselineAlignBottom", a.getBoolean(ImageView_baselineAlignBottom, false)); + json.put("ImageView_adjustViewBounds", a.getBoolean(ImageView_adjustViewBounds, false)); + json.put("ImageView_maxWidth", a.getDimensionPixelSize(ImageView_maxWidth, Integer.MAX_VALUE)); + json.put("ImageView_maxHeight", a.getDimensionPixelSize(ImageView_maxHeight, Integer.MAX_VALUE)); + int index = a.getInt(ImageView_scaleType, -1); + if (index >= 0) + json.put("ImageView_scaleType", sScaleTypeArray[index]); + + int tint = a.getInt(ImageView_tint, 0); + if (tint != 0) + json.put("ImageView_tint", tint); + + + json.put("ImageView_cropToPadding",a.getBoolean(ImageView_cropToPadding, false)); + a.recycle(); + } + catch(Exception e) + { + e.printStackTrace(); + } + return json; + + } + + void extractCompoundButton(JSONObject parentObject, String styleName, String qtClass) + { + JSONObject json = extractTextAppearanceInformations(styleName, qtClass, null, -1); + Class<?> attrClass; + try { + attrClass = Class.forName("android.R$attr"); + int styleId = attrClass.getDeclaredField(styleName).getInt(null); + int[] compoundButtonAttrs=(int[]) styleableClass.getDeclaredField("CompoundButton").get(null); + + TypedArray a = m_theme.obtainStyledAttributes( + null, compoundButtonAttrs, styleId, 0); + + Drawable d = a.getDrawable(getField(styleableClass,"CompoundButton_button")); + if (d != null) + json.put("CompoundButton_button", getDrawable(d, styleName + "_CompoundButton_button")); + + a.recycle(); + parentObject.put(styleName, json); + } catch (Exception e) { + e.printStackTrace(); + } + } + + void extractProgressBarInfo(JSONObject json, String styleName) + { + Class<?> attrClass; + try { + attrClass = Class.forName("android.R$attr"); + int styleId = attrClass.getDeclaredField(styleName).getInt(null); + int[] progressBarAttrs=(int[]) styleableClass.getDeclaredField("ProgressBar").get(null); + + TypedArray a = m_theme.obtainStyledAttributes(null, progressBarAttrs, styleId, 0); + int mMinWidth = 24; + int mMaxWidth = 48; + int mMinHeight = 24; + int mMaxHeight = 48; + mMinWidth = a.getDimensionPixelSize(getField(styleableClass, "ProgressBar_minWidth"), mMinWidth); + mMaxWidth = a.getDimensionPixelSize(getField(styleableClass, "ProgressBar_maxWidth"), mMaxWidth); + mMinHeight = a.getDimensionPixelSize(getField(styleableClass, "ProgressBar_minHeight"), mMinHeight); + mMaxHeight = a.getDimensionPixelSize(getField(styleableClass, "ProgressBar_maxHeight"), mMaxHeight); + + json.put("ProgressBar_indeterminateDuration", a.getInt(getField(styleableClass, "ProgressBar_indeterminateDuration"), 4000)); + json.put("ProgressBar_minWidth", mMinWidth); + json.put("ProgressBar_maxWidth", mMaxWidth); + json.put("ProgressBar_minHeight", mMinHeight); + json.put("ProgressBar_maxHeight", mMaxHeight); + json.put("ProgressBar_progress_id", android.R.id.progress); + json.put("ProgressBar_secondaryProgress_id", android.R.id.secondaryProgress); + + Drawable d = a.getDrawable(getField(styleableClass,"ProgressBar_progressDrawable")); + if (d != null) + json.put("ProgressBar_progressDrawable", getDrawable(d, styleName + "_ProgressBar_progressDrawable")); + + d = a.getDrawable(getField(styleableClass,"ProgressBar_indeterminateDrawable")); + if (d != null) + json.put("ProgressBar_indeterminateDrawable", getDrawable(d, styleName + "_ProgressBar_indeterminateDrawable")); + + a.recycle(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + void extractProgressBar(JSONObject parentObject, String styleName, String qtClass) + { + JSONObject json = extractTextAppearanceInformations(styleName, qtClass, null, -1); + try { + extractProgressBarInfo(json, styleName); + parentObject.put(styleName, json); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + void extractAbsSeekBar(JSONObject parentObject, String styleName, String qtClass) + { + JSONObject json = extractTextAppearanceInformations(styleName, qtClass, null, -1); + extractProgressBarInfo(json, styleName); + Class<?> attrClass; + try { + attrClass = Class.forName("android.R$attr"); + int styleId = attrClass.getDeclaredField(styleName).getInt(null); + int[] compoundButtonAttrs=(int[]) styleableClass.getDeclaredField("SeekBar").get(null); + + TypedArray a = m_theme.obtainStyledAttributes( + null, compoundButtonAttrs, styleId, 0); + + Drawable d = a.getDrawable(getField(styleableClass,"SeekBar_thumb")); + if (d != null) + json.put("SeekBar_thumb", getDrawable(d, styleName + "_SeekBar_thumb")); + + a.recycle(); + parentObject.put(styleName, json); + } catch (Exception e) { + e.printStackTrace(); + } + } + + JSONObject extractCheckedTextView(AttributeSet attribSet, String itemName) + { + JSONObject json = extractTextAppearanceInformations("textViewStyle", itemName, attribSet, -1); + try { + Class<?> attrClass= Class.forName("android.R$attr"); + int styleId = attrClass.getDeclaredField("textViewStyle").getInt(null); + int[] compoundButtonAttrs=(int[]) styleableClass.getDeclaredField("CheckedTextView").get(null); + + TypedArray a = m_theme.obtainStyledAttributes(attribSet, compoundButtonAttrs, styleId, 0); + + Drawable d = a.getDrawable(getField(styleableClass,"CheckedTextView_checkMark")); + if (d != null) + json.put("CheckedTextView_checkMark", getDrawable(d, itemName+"_CheckedTextView_checkMark")); + + a.recycle(); + } catch (Exception e) { + e.printStackTrace(); + } + return json; + } + + private JSONObject extractItemStyle(int resourceId, String itemName, int textAppearance) { + try + { + XmlResourceParser parser = m_context.getResources().getLayout(resourceId); + int type; + while ((type = parser.next()) != XmlPullParser.START_TAG && + type != XmlPullParser.END_DOCUMENT) { + // Empty + } + + if (type != XmlPullParser.START_TAG) { + return null; + } + + AttributeSet attributes = Xml.asAttributeSet(parser); + String name = parser.getName(); + if (name.equals("TextView")) + return extractTextAppearanceInformations("textViewStyle", itemName, attributes, textAppearance); + if (name.equals("CheckedTextView")) + return extractCheckedTextView(attributes, itemName); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private void extractItemsStyle(JSONObject json) { + try + { + json.put("simple_list_item",extractItemStyle(android.R.layout.simple_list_item_1, "simple_list_item", android.R.style.TextAppearance_Large)); + json.put("simple_list_item_checked",extractItemStyle(android.R.layout.simple_list_item_checked, "simple_list_item_checked", android.R.style.TextAppearance_Large)); + json.put("simple_list_item_multiple_choice",extractItemStyle(android.R.layout.simple_list_item_multiple_choice, "simple_list_item_multiple_choice", android.R.style.TextAppearance_Large)); + json.put("simple_list_item_single_choice",extractItemStyle(android.R.layout.simple_list_item_single_choice, "simple_list_item_single_choice", android.R.style.TextAppearance_Large)); + json.put("simple_spinner_item",extractItemStyle(android.R.layout.simple_spinner_item, "simple_spinner_item", -1)); + json.put("simple_spinner_dropdown_item",extractItemStyle(android.R.layout.simple_spinner_dropdown_item, "simple_spinner_dropdown_item",android.R.style.TextAppearance_Large)); + json.put("simple_dropdown_item_1line",extractItemStyle(android.R.layout.simple_dropdown_item_1line, "simple_dropdown_item_1line",android.R.style.TextAppearance_Large)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public ExtractStyle(Context context, String extractPath) + { +// Log.i(MinistroService.TAG, "Extract " + extractPath); + m_extractPath = extractPath + "/"; + new File(m_extractPath).mkdirs(); +// MinistroActivity.nativeChmode(m_extractPath, 0755); + m_context = context; + m_theme = context.getTheme(); + TypedArray array = m_theme.obtainStyledAttributes(new int[]{ + android.R.attr.colorBackground, + android.R.attr.textColorPrimary, + }); + defaultBackgroundColor = array.getColor(0, 0); + defaultTextColor = array.getColor(1, 0xFFFFFF); + array.recycle(); + + JSONObject json = new JSONObject(); + try { + json.put("buttonStyle", extractTextAppearanceInformations("buttonStyle", "QPushButton", null, -1)); + json.put("spinnerStyle", extractTextAppearanceInformations("spinnerStyle", "QComboBox", null, -1)); + extractProgressBar(json, "progressBarStyleHorizontal", "QProgressBar"); + extractAbsSeekBar(json, "seekBarStyle", "QSlider"); + extractCompoundButton(json, "checkboxStyle", "QCheckBox"); + json.put("editTextStyle", extractTextAppearanceInformations("editTextStyle", "QLineEdit", null, -1)); + extractCompoundButton(json, "radioButtonStyle", "QRadioButton"); + json.put("textViewStyle", extractTextAppearanceInformations("textViewStyle", "QWidget", null, -1)); + extractItemsStyle(json); + extractCompoundButton(json, "buttonStyleToggle", null); + OutputStreamWriter jsonWriter; + jsonWriter = new OutputStreamWriter(new FileOutputStream(m_extractPath+"style.json")); + jsonWriter.write(json.toString(1)); + jsonWriter.close(); +// MinistroActivity.nativeChmode(m_extractPath+"style.json", 0644); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index 554c54d4a0..7e7312cde8 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -99,6 +99,7 @@ public class QtActivityDelegate private static final String APPLICATION_PARAMETERS_KEY = "application.parameters"; private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes"; private static final String NECESSITAS_API_LEVEL_KEY = "necessitas.api.level"; + private static final String EXTRACT_STYLE_KEY = "extract.android.style"; private static String m_environmentVariables = null; private static String m_applicationParameters = null; @@ -426,6 +427,11 @@ public class QtActivityDelegate if (null == m_mainLib && libraries.size() > 0) m_mainLib = libraries.get(libraries.size() - 1); + if (loaderParams.containsKey(EXTRACT_STYLE_KEY)) { + String path = loaderParams.getString(EXTRACT_STYLE_KEY); + new ExtractStyle(m_activity, path); + } + try { m_super_dispatchKeyEvent = m_activity.getClass().getMethod("super_dispatchKeyEvent", KeyEvent.class); m_super_onRestoreInstanceState = m_activity.getClass().getMethod("super_onRestoreInstanceState", Bundle.class); diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java index f99bb84077..43b04d17f0 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java @@ -116,6 +116,7 @@ public class QtActivity extends Activity private static final String MAIN_LIBRARY_KEY = "main.library"; private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes"; private static final String NECESSITAS_API_LEVEL_KEY = "necessitas.api.level"; + private static final String EXTRACT_STYLE_KEY = "extract.android.style"; /// Ministro server parameter keys private static final String REQUIRED_MODULES_KEY = "required.modules"; @@ -177,6 +178,7 @@ public class QtActivity extends Activity // * unstable - unstable repository, DO NOT use this repository in production, // this repository is used to push Qt snapshots. private String[] m_qtLibs = null; // required qt libs + private int m_displayDensity = -1; public QtActivity() { @@ -629,6 +631,17 @@ public class QtActivity extends Activity m_activityInfo.metaData.getString("android.app.static_init_classes").split(":")); } loaderParams.putStringArrayList(NATIVE_LIBRARIES_KEY, libraryList); + + + if (bundlingQtLibs) { + String themePath = pluginsPrefix + "android-style/"; + String stylePath = themePath + m_displayDensity + "/"; + if (!(new File(stylePath)).exists()) + loaderParams.putString(EXTRACT_STYLE_KEY, stylePath); + ENVIRONMENT_VARIABLES += "\tMINISTRO_ANDROID_STYLE_PATH=" + stylePath + + "\tQT_ANDROID_THEMES_ROOT_PATH=" + themePath; + } + loaderParams.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES + "\tQML2_IMPORT_PATH=" + pluginsPrefix + "/qml" + "\tQML_IMPORT_PATH=" + pluginsPrefix + "/imports" @@ -867,8 +880,10 @@ public class QtActivity extends Activity return; } + m_displayDensity = getResources().getDisplayMetrics().densityDpi; + ENVIRONMENT_VARIABLES += "\tQT_ANDROID_THEME=" + QT_ANDROID_DEFAULT_THEME - + "/\tQT_ANDROID_THEME_DISPLAY_DPI=" + getResources().getDisplayMetrics().densityDpi + "\t"; + + "/\tQT_ANDROID_THEME_DISPLAY_DPI=" + m_displayDensity + "\t"; if (null == getLastNonConfigurationInstance()) { // if splash screen is defined, then show it diff --git a/src/plugins/platforms/android/android.pro b/src/plugins/platforms/android/android.pro index 243eea071a..32c37ab17a 100644 --- a/src/plugins/platforms/android/android.pro +++ b/src/plugins/platforms/android/android.pro @@ -21,7 +21,9 @@ CONFIG += qpa/genericunixfontdatabase OTHER_FILES += $$PWD/android.json -INCLUDEPATH += $$PWD +INCLUDEPATH += \ + $$PWD \ + $$QT_SOURCE_TREE/src/3rdparty/android SOURCES += $$PWD/androidplatformplugin.cpp \ $$PWD/androidjnimain.cpp \ @@ -48,7 +50,8 @@ SOURCES += $$PWD/androidplatformplugin.cpp \ $$PWD/qandroidplatformrasterwindow.cpp \ $$PWD/qandroidplatformbackingstore.cpp \ $$PWD/qandroidplatformopenglcontext.cpp \ - $$PWD/qandroidplatformforeignwindow.cpp + $$PWD/qandroidplatformforeignwindow.cpp \ + $$PWD/extract.cpp HEADERS += $$PWD/qandroidplatformintegration.h \ $$PWD/androidjnimain.h \ diff --git a/src/plugins/platforms/android/extract.cpp b/src/plugins/platforms/android/extract.cpp new file mode 100644 index 0000000000..82687e61a7 --- /dev/null +++ b/src/plugins/platforms/android/extract.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2014 BogDan Vatra <bogdan@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + + +#include <jni.h> +#include <android/log.h> +#include <extract.h> +#include <alloca.h> + +#define LOG_TAG "extractSyleInfo" +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) +#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) +#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__) + +extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractNativeChunkInfo(JNIEnv * env, jobject, Res_png_9patch* chunk) +{ + Res_png_9patch::deserialize(chunk); + //printChunkInformation(chunk); + jintArray result; + size_t size = 3+chunk->numXDivs+chunk->numYDivs+chunk->numColors; + result = env->NewIntArray(size); + if (!result) + return 0; + + jint *data = (jint*)malloc(sizeof(jint)*size); + size_t pos = 0; + data[pos++]=chunk->numXDivs; + data[pos++]=chunk->numYDivs; + data[pos++]=chunk->numColors; + for (int x = 0; x <chunk->numXDivs; x ++) + data[pos++]=chunk->xDivs[x]; + for (int y = 0; y <chunk->numYDivs; y ++) + data[pos++]=chunk->yDivs[y]; + for (int c = 0; c <chunk->numColors; c ++) + data[pos++]=chunk->colors[c]; + env->SetIntArrayRegion(result, 0, size, data); + free(data); + return result; +} + +extern "C" JNIEXPORT jintArray JNICALL Java_org_qtproject_qt5_android_ExtractStyle_extractChunkInfo(JNIEnv * env, jobject obj, jbyteArray chunkObj) +{ + size_t chunkSize = env->GetArrayLength(chunkObj); + void* storage = alloca(chunkSize); + env->GetByteArrayRegion(chunkObj, 0, chunkSize, + reinterpret_cast<jbyte*>(storage)); + + if (!env->ExceptionCheck()) + return Java_org_qtproject_qt5_android_ExtractStyle_extractNativeChunkInfo(env, obj, static_cast<Res_png_9patch*>(storage)); + else + env->ExceptionClear(); + return 0; +} + +// The following part was shamelessly stolen from ResourceTypes.cpp from Android's sources +/* + * Copyright (C) 2005 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +static void deserializeInternal(const void* inData, Res_png_9patch* outData) { + char* patch = (char*) inData; + if (inData != outData) { + memmove(&outData->wasDeserialized, patch, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors + memmove(&outData->paddingLeft, patch + 12, 4); // copy wasDeserialized, numXDivs, numYDivs, numColors + } + outData->wasDeserialized = true; + char* data = (char*)outData; + data += sizeof(Res_png_9patch); + outData->xDivs = (int32_t*) data; + data += outData->numXDivs * sizeof(int32_t); + outData->yDivs = (int32_t*) data; + data += outData->numYDivs * sizeof(int32_t); + outData->colors = (uint32_t*) data; +} + +Res_png_9patch* Res_png_9patch::deserialize(const void* inData) +{ + if (sizeof(void*) != sizeof(int32_t)) { + LOGE("Cannot deserialize on non 32-bit system\n"); + return NULL; + } + deserializeInternal(inData, (Res_png_9patch*) inData); + return (Res_png_9patch*) inData; +} |