From 62fecce1d30ffa0a801dbac42c10f235aa1a93cd Mon Sep 17 00:00:00 2001 From: Olga Miller Date: Tue, 7 Feb 2017 22:03:52 +0100 Subject: [PATCH] Read system fonts from XML for text overlay font selection --- .../java/om/sstvencoder/EditTextActivity.java | 64 +++++- .../java/om/sstvencoder/FontFamilySet.java | 196 ++++++++++++++++++ .../main/res/layout/activity_edit_text.xml | 6 + 3 files changed, 256 insertions(+), 10 deletions(-) create mode 100644 app/src/main/java/om/sstvencoder/FontFamilySet.java diff --git a/app/src/main/java/om/sstvencoder/EditTextActivity.java b/app/src/main/java/om/sstvencoder/EditTextActivity.java index e221e47..e091a14 100644 --- a/app/src/main/java/om/sstvencoder/EditTextActivity.java +++ b/app/src/main/java/om/sstvencoder/EditTextActivity.java @@ -28,6 +28,8 @@ import android.widget.CheckBox; import android.widget.EditText; import android.widget.Spinner; +import java.util.List; + import om.sstvencoder.ColorPalette.ColorPaletteView; import om.sstvencoder.TextOverlay.Label; @@ -37,6 +39,10 @@ public class EditTextActivity extends AppCompatActivity implements AdapterView.O private EditText mEditText; private ColorPaletteView mColorPaletteView; private float mTextSize; + private FontFamilySet mFontFamilySet; + private FontFamilySet.FontFamily mSelectedFontFamily; + private List mFontFamilyNameList; + private CheckBox mEditItalic, mEditBold; @Override protected void onCreate(Bundle savedInstanceState) { @@ -44,6 +50,8 @@ public class EditTextActivity extends AppCompatActivity implements AdapterView.O setContentView(R.layout.activity_edit_text); mEditText = (EditText) findViewById(R.id.edit_text); mColorPaletteView = (ColorPaletteView) findViewById(R.id.edit_color); + mEditBold = (CheckBox) findViewById(R.id.edit_bold); + mEditItalic = (CheckBox) findViewById(R.id.edit_italic); } @Override @@ -51,19 +59,33 @@ public class EditTextActivity extends AppCompatActivity implements AdapterView.O super.onStart(); Label label = (Label) getIntent().getSerializableExtra(EXTRA); mEditText.setText(label.getText()); - mTextSize = label.getTextSize(); - initTextSizeSpinner(textSizeToPosition(mTextSize)); - ((CheckBox) findViewById(R.id.edit_italic)).setChecked(label.getItalic()); - ((CheckBox) findViewById(R.id.edit_bold)).setChecked(label.getBold()); + initTextSizeSpinner(label.getTextSize()); + mEditBold.setChecked(label.getBold()); + mEditItalic.setChecked(label.getItalic()); mColorPaletteView.setColor(label.getForeColor()); + initFontFamilySpinner(label.getFamilyName()); + updateBoldAndItalic(); } - private void initTextSizeSpinner(int position) { + private void initFontFamilySpinner(String familyName) { + Spinner editFontFamily = (Spinner) findViewById(R.id.edit_font_family); + editFontFamily.setOnItemSelectedListener(this); + mFontFamilySet = new FontFamilySet(); + mSelectedFontFamily = mFontFamilySet.getFontFamily(familyName); + mFontFamilyNameList = mFontFamilySet.getFontFamilyDisplayNameList(); + editFontFamily.setAdapter(new ArrayAdapter<>(this, + android.R.layout.simple_spinner_dropdown_item, mFontFamilyNameList)); + editFontFamily.setSelection(mFontFamilyNameList.indexOf(mSelectedFontFamily.displayName)); + } + + private void initTextSizeSpinner(float textSize) { + mTextSize = textSize; Spinner editTextSize = (Spinner) findViewById(R.id.edit_text_size); editTextSize.setOnItemSelectedListener(this); String[] textSizeList = new String[]{"Small", "Normal", "Large", "Huge"}; - editTextSize.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, textSizeList)); - editTextSize.setSelection(position); + editTextSize.setAdapter(new ArrayAdapter<>(this, + android.R.layout.simple_spinner_dropdown_item, textSizeList)); + editTextSize.setSelection(textSizeToPosition(textSize)); } private int textSizeToPosition(float textSize) { @@ -79,7 +101,28 @@ public class EditTextActivity extends AppCompatActivity implements AdapterView.O @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { - mTextSize = positionToTextSize(position); + switch (parent.getId()) { + case R.id.edit_text_size: + mTextSize = positionToTextSize(position); + break; + case R.id.edit_font_family: + String displayName = mFontFamilyNameList.get(position); + mSelectedFontFamily = mFontFamilySet.getFontFamilyFromDisplayName(displayName); + updateBoldAndItalic(); + break; + default: + break; + } + } + + private void updateBoldAndItalic() { + mEditBold.setEnabled(mSelectedFontFamily.bold); + if (!mEditBold.isEnabled()) + mEditBold.setChecked(false); + + mEditItalic.setEnabled(mSelectedFontFamily.italic); + if (!mEditItalic.isEnabled()) + mEditItalic.setChecked(false); } @Override @@ -114,8 +157,9 @@ public class EditTextActivity extends AppCompatActivity implements AdapterView.O Label label = new Label(); label.setText(mEditText.getText().toString()); label.setTextSize(mTextSize); - label.setItalic(((CheckBox) findViewById(R.id.edit_italic)).isChecked()); - label.setBold(((CheckBox) findViewById(R.id.edit_bold)).isChecked()); + label.setFamilyName(mSelectedFontFamily.name); + label.setItalic(mEditItalic.isChecked()); + label.setBold(mEditBold.isChecked()); label.setForeColor(mColorPaletteView.getColor()); return label; } diff --git a/app/src/main/java/om/sstvencoder/FontFamilySet.java b/app/src/main/java/om/sstvencoder/FontFamilySet.java new file mode 100644 index 0000000..9ce4820 --- /dev/null +++ b/app/src/main/java/om/sstvencoder/FontFamilySet.java @@ -0,0 +1,196 @@ +/* +Copyright 2017 Olga Miller + +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. +*/ +package om.sstvencoder; + +import android.support.annotation.NonNull; +import android.util.Xml; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +class FontFamilySet { + class FontFamily { + String name; + String displayName; + boolean bold; + boolean italic; + } + + private final List mFamilySet; + + FontFamilySet() { + mFamilySet = new ArrayList<>(); + fillWithSystemFonts(mFamilySet); + if (mFamilySet.size() == 0) + mFamilySet.add(getDefaultFontFamily()); + } + + @NonNull + private FontFamily getDefaultFontFamily() { + FontFamily defaultFontFamily = new FontFamily(); + defaultFontFamily.name = null; + defaultFontFamily.displayName = "Default"; + defaultFontFamily.bold = true; + defaultFontFamily.italic = true; + return defaultFontFamily; + } + + @NonNull + FontFamily getFontFamily(String name) { + if (name != null) { + for (FontFamily fontFamily : mFamilySet) { + if (name.equals(fontFamily.name)) + return fontFamily; + } + } + return mFamilySet.get(0); + } + + @NonNull + FontFamily getFontFamilyFromDisplayName(@NonNull String displayName) { + for (FontFamily fontFamily : mFamilySet) { + if (displayName.equals(fontFamily.displayName)) + return fontFamily; + } + return mFamilySet.get(0); + } + + @NonNull + List getFontFamilyDisplayNameList() { + List names = new ArrayList<>(); + for (FontFamily fontFamily : mFamilySet) + names.add(fontFamily.displayName); + return names; + } + + private void fillWithSystemFonts(@NonNull List familySet) { + File fontsFile = new File("/system/etc/system_fonts.xml"); + if (!fontsFile.exists()) { + fontsFile = new File("/system/etc/fonts.xml"); + if (!fontsFile.exists()) + return; + } + InputStream in = null; + try { + in = new FileInputStream(fontsFile); + XmlPullParser parser = Xml.newPullParser(); + parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); + parser.setInput(in, null); + parser.next(); + if (parser.getEventType() == XmlPullParser.START_TAG && parser.getName().equals("familyset")) + readFamilySet(parser, familySet); + } catch (Exception ignore) { + } finally { + if (in != null) { + try { + in.close(); + } catch (Exception ignore) { + } + } + } + } + + private void readFamilySet(@NonNull XmlPullParser parser, @NonNull List familySet) + throws XmlPullParserException, IOException { + while (parser.next() != XmlPullParser.END_TAG) { + if (parser.getEventType() == XmlPullParser.START_TAG && parser.getName().equals("family")) { + FontFamily fontFamily = readFamily(parser); + if (fontFamily.displayName != null) + familySet.add(fontFamily); + } + } + } + + @NonNull + private FontFamily readFamily(@NonNull XmlPullParser parser) + throws XmlPullParserException, IOException { + FontFamily fontFamily = new FontFamily(); + + while (parser.next() != XmlPullParser.END_TAG) { + if (parser.getEventType() == XmlPullParser.START_TAG) { + switch (parser.getName()) { + case "nameset": + readNameSet(parser, fontFamily); + break; + case "fileset": + readFileSet(parser, fontFamily); + break; + } + } + } + return fontFamily; + } + + private void readNameSet(@NonNull XmlPullParser parser, @NonNull FontFamily fontFamily) + throws XmlPullParserException, IOException { + while (parser.next() != XmlPullParser.END_TAG) { + if (parser.getEventType() == XmlPullParser.START_TAG && parser.getName().equals("name")) { + if (fontFamily.name == null) + fontFamily.name = readText(parser); + else { + // skip all other names + parser.next(); + parser.next(); + } + } + } + } + + private void readFileSet(@NonNull XmlPullParser parser, @NonNull FontFamily fontFamily) + throws XmlPullParserException, IOException { + while (parser.next() != XmlPullParser.END_TAG) { + if (parser.getEventType() == XmlPullParser.START_TAG && parser.getName().equals("file")) + parseDisplayNameAndStyle(readText(parser), fontFamily); + } + } + + private void parseDisplayNameAndStyle(String fontFileName, @NonNull FontFamily fontFamily) { + // Example: RobotoCondensed-LightItalic.ttf + // { "RobotoCondensed", "LightItalic" } + String[] familyInfo = fontFileName.split("\\.")[0].split("-"); + String s = ""; + if (familyInfo.length > 1) { + s = familyInfo[1]; + if (s.contains("Bold")) + fontFamily.bold = true; + if (s.contains("Italic")) + fontFamily.italic = true; + } + if (fontFamily.displayName == null) { + // "Light" + s = s.replace("Regular", "").replace("Bold", "").replace("Italic", ""); + // "Roboto Condensed Light" + fontFamily.displayName = (familyInfo[0] + s).replaceAll("(\\p{Ll})(\\p{Lu})", "$1 $2"); + } + } + + private String readText(@NonNull XmlPullParser parser) + throws IOException, XmlPullParserException { + String text = ""; + if (parser.next() == XmlPullParser.TEXT) { + text = parser.getText(); + parser.next(); + } + return text; + } +} diff --git a/app/src/main/res/layout/activity_edit_text.xml b/app/src/main/res/layout/activity_edit_text.xml index 2d77cee..1a8844f 100644 --- a/app/src/main/res/layout/activity_edit_text.xml +++ b/app/src/main/res/layout/activity_edit_text.xml @@ -16,6 +16,12 @@ android:inputType="text" android:textSize="32sp"/> + +