Home | History | Annotate | Download | only in fontlab
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.fontlab;
     18 
     19 import java.util.Map;
     20 
     21 import android.app.Activity;
     22 import android.graphics.Color;
     23 import android.graphics.Paint;
     24 import android.graphics.Typeface;
     25 import android.graphics.drawable.PaintDrawable;
     26 import android.os.Bundle;
     27 import android.view.KeyEvent;
     28 import android.view.Menu;
     29 import android.view.MenuItem;
     30 import android.view.View;
     31 import android.widget.TextView;
     32 
     33 public class FontLab extends Activity {
     34     private static final int MIN_SIZE = 1;
     35     private static final int MAX_SIZE = 60;
     36 
     37     private static final float SCALE_X_RANGE = 20;
     38     private static final int MAX_SCALE_X = 20;
     39     private static final int MIN_SCALE_X = -19;   // -20 would make zero-scale
     40 
     41     private static final int MAX_GAMMA = 40;
     42     private static final int MIN_GAMMA = 1;
     43     private static final float GAMMA_RANGE = 20;
     44 
     45     private static final String[] sText = {
     46         "Applications Contacts Maps Google Browser Text messages Address book"
     47         + " Development Earth Quake Settings Voicemail Zoolander. Four score"
     48         + " and seven years ago our fathers brought forth on this continent, a"
     49         + " new nation, conceived in Liberty, and dedicated to the proposition"
     50         + " that all men are created equal. Now we are engaged in a great civil"
     51         + " war, testing whether that nation, or any nation so conceived and so"
     52         + " dedicated, can long endure. We are met on a great battle-field of"
     53         + " that war. We have come to dedicate a portion of that field, as a"
     54         + " final resting place for those who here gave their lives that that"
     55         + " nation might live. It is altogether fitting and proper that we"
     56         + " should do this. But, in a larger sense, we can not dedicate - we"
     57         + " can not consecrate - we can not hallow - this ground. The brave"
     58         + " men, living and dead, who struggled here, have consecrated it, far"
     59         + " above our poor power to add or detract. The world will little note,"
     60         + " nor long remember what we say here, but it can never forget what"
     61         + " they did here. It is for us the living, rather, to be dedicated"
     62         + " here to the unfinished work which they who fought here have thus"
     63         + " far so nobly advanced. It is rather for us to be here dedicated to"
     64         + " the great task remaining before us - that from these honored dead"
     65         + " we take increased devotion to that cause for which they gave the"
     66         + " last full measure of devotion - that we here highly resolve that"
     67         + " these dead shall not have died in vain - that this nation, under"
     68         + " God, shall have a new birth of freedom - and that government of the"
     69         + " people, by the people, for the people, shall not perish from the"
     70         + " earth."
     71         ,
     72         "A Spanish doctor on Tuesday stood by his opinion that Fidel Castro is recovering from stomach surgery despite a newspaper report stating the Cuban leader is in a serious condition after a number of failed operations."
     73         + " When Senator Wayne Allard, Republican of Colorado, announced Monday that he would not seek re-election, the uphill battle for his party to reclaim the Senate in 2008 became an even steeper climb."
     74         + " Naomi Campbell was today sentenced to five days' community service and ordered to attend an anger management course after she admitted throwing a mobile phone at her maid."
     75         ,
     76         "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 !@#$%^&*()-_=+[]\\{}|;':\",./<>?"
     77         ,
     78         "HaH HbH HcH HdH HeH HfH HgH HhH HiH HjH HkH HlH HmH HnH HoH HpH HqH HrH HsH HtH HuH HvH HwH HxH HyH HzH"
     79         + "HAH HBH HCH HDH HEH HFH HGH HHH HIH HJH HKH HLH HMH HNH HOH HPH HQH HRH HSH HTH HUH HVH HWH HXH HYH HZH"
     80     };
     81 
     82     private void updateText() {
     83         mTextIndex %= sText.length;
     84         String s = sText[mTextIndex];
     85         mColumn1.setText(s);
     86         mColumn2.setText(s);
     87     }
     88 
     89     public FontLab() {}
     90 
     91     public void onCreate(Bundle icicle) {
     92         super.onCreate(icicle);
     93         setContentView(R.layout.font_lab);
     94 
     95         mColumn1 = (TextView)findViewById(R.id.column1);
     96         mColumn2 = (TextView)findViewById(R.id.column2);
     97         mContentView = findViewById(R.id.content);
     98 
     99 
    100         mColumn1.setTextSize(mFontSize);
    101         mColumn2.setTextSize(mFontSize);
    102 
    103         mColumn1.setTextColor(Color.BLACK);
    104         mColumn1.setBackgroundDrawable(new PaintDrawable(Color.WHITE));
    105         mColumn2.setTextColor(Color.WHITE);
    106         mColumn2.setBackgroundDrawable(new PaintDrawable(Color.BLACK));
    107 
    108         refreshFont();
    109         updateTitle();
    110         updateText();
    111 
    112         setDefaultKeyMode(Activity.DEFAULT_KEYS_SHORTCUT);
    113 
    114         mColumn1.setPadding(5, 0, 5, 0);
    115         mColumn2.setPadding(5, 0, 5, 0);
    116     }
    117 
    118     private void updateTitle() {
    119         Typeface tf = mColumn1.getTypeface();
    120         String title = " PS=" + mFontSize + " X="
    121                     + (1 + mTextScaleXDelta/SCALE_X_RANGE)
    122                     + " G=" + (mGamma/GAMMA_RANGE)
    123                     + " S=" + ((mColumn1.getPaintFlags() & Paint.SUBPIXEL_TEXT_FLAG) != 0 ? 1 : 0)
    124                     + " " + sTypefaceName[mFontIndex]
    125                     + " " + sStyleName[tf.getStyle()]
    126                     ;
    127         setTitle(title);
    128     }
    129 
    130     /** Called when it is time to initialize the activity state. */
    131     protected void onRestoreInstanceState(Bundle state) {
    132         super.onRestoreInstanceState(state);
    133     }
    134 
    135     protected void onResume() {
    136         super.onResume();
    137     }
    138 
    139     private static final String sStyleName[] = {
    140         "Regular", "Bold", "Italic", "Bold Italic"
    141     };
    142     private static final String sTypefaceName[] = {
    143         "Sans",
    144         "Serif",
    145         "Mono"
    146     };
    147     private static final Typeface sTypeface[] = {
    148         Typeface.SANS_SERIF,
    149         Typeface.SERIF,
    150         Typeface.MONOSPACE
    151     };
    152     private static final int FONT_INDEX_SANS = 0;   // index into sTypeface
    153     private static final int FONT_INDEX_SERIF = 1;  // index into sTypeface
    154     private static final int FONT_INDEX_MONO = 2;   // index into sTypeface
    155 
    156     private static boolean canSupportStyle(Typeface tf, int styleBits) {
    157         tf = Typeface.create(tf, styleBits);
    158         return (tf.getStyle() & styleBits) == styleBits;
    159     }
    160 
    161     private void refreshFont() {
    162         Typeface tf = Typeface.create(sTypeface[mFontIndex], mFontStyle);
    163         mColumn1.setTypeface(tf);
    164         mColumn2.setTypeface(tf);
    165         updateTitle();
    166     }
    167 
    168     private MenuItem.OnMenuItemClickListener mFontClickListener = new MenuItem.OnMenuItemClickListener() {
    169         public boolean onMenuItemClick(MenuItem item) {
    170             mFontIndex = item.getItemId();
    171             refreshFont();
    172             return true;
    173         }
    174     };
    175 
    176     private void addFontMenu(Menu menu, int index) {
    177         MenuItem item = menu.add(0, index, 0, sTypefaceName[index]);
    178         item.setCheckable(true);
    179         item.setOnMenuItemClickListener(mFontClickListener);
    180         item.setChecked(index == mFontIndex);
    181     }
    182 
    183     private MenuItem.OnMenuItemClickListener mStyleClickListener = new MenuItem.OnMenuItemClickListener() {
    184         public boolean onMenuItemClick(MenuItem item) {
    185             mFontStyle = mFontStyle ^ item.getItemId();
    186             refreshFont();
    187             return true;
    188         }
    189     };
    190 
    191     private void addStyleMenu(Menu menu, int style, char shortCut) {
    192         MenuItem item = menu.add(0, style, 0, (style == Typeface.BOLD) ? "Bold" : "Italic");
    193         item.setCheckable(true);
    194         item.setOnMenuItemClickListener(mStyleClickListener);
    195         item.setChecked((mFontStyle & style) != 0);
    196 
    197         item.setVisible(canSupportStyle(sTypeface[mFontIndex], style));
    198         if (shortCut != 0) {
    199             item.setAlphabeticShortcut(shortCut);
    200         }
    201     }
    202 
    203     private MenuItem.OnMenuItemClickListener mFlagClickListener = new MenuItem.OnMenuItemClickListener() {
    204         public boolean onMenuItemClick(MenuItem item) {
    205             int mask = item.getItemId();
    206             mColumn1.setPaintFlags(mColumn1.getPaintFlags() ^ mask);
    207             mColumn2.setPaintFlags(mColumn2.getPaintFlags() ^ mask);
    208             updateTitle();
    209             return true;
    210         }
    211     };
    212 
    213     private
    214     void addFlagMenu(Menu menu, int paintFlag, String label, char shortCut) {
    215         MenuItem item = menu.add(0, paintFlag, 0, label);
    216         item.setCheckable(true);
    217         item.setOnMenuItemClickListener(mFlagClickListener);
    218         item.setChecked((mColumn1.getPaintFlags() & paintFlag) != 0);
    219         if (shortCut != 0) {
    220             item.setAlphabeticShortcut(shortCut);
    221         }
    222     }
    223 
    224     private static void addListenerMenu(MenuItem item,
    225                                         MenuItem.OnMenuItemClickListener listener,
    226                                         char keyChar) {
    227         item.setOnMenuItemClickListener(listener);
    228         if (keyChar != '\0') {
    229             item.setAlphabeticShortcut(keyChar);
    230         }
    231     }
    232 
    233     public boolean onCreateOptionsMenu(Menu menu) {
    234         super.onCreateOptionsMenu(menu);
    235         return true;
    236     }
    237 
    238     @Override public boolean onPrepareOptionsMenu(Menu menu) {
    239         super.onPrepareOptionsMenu(menu);
    240         menu.clear();
    241 
    242         addFontMenu(menu, FONT_INDEX_SANS);
    243         addFontMenu(menu, FONT_INDEX_SERIF);
    244 //        addFontMenu(menu, FONT_INDEX_MONO);
    245         addStyleMenu(menu, Typeface.BOLD, 'b');
    246         addStyleMenu(menu, Typeface.ITALIC, 'i');
    247         addFlagMenu(menu, Paint.SUBPIXEL_TEXT_FLAG, "SubPixel", 's');
    248         //        addFlagMenu(menu, Paint.DEV_KERN_TEXT_FLAG, "DevKern", 'k');
    249         menu.add(0, 0, 0, "Text").setOnMenuItemClickListener(mTextCallback).setAlphabeticShortcut('t');
    250 
    251         return true;
    252     }
    253 
    254     protected void onActivityResult(int requestCode, int resultCode,
    255                                     String data, Map extras) {
    256         if (resultCode == RESULT_OK) {
    257             switch (requestCode) {
    258             case BACKGROUND_PICKED:
    259                 {
    260                     int color = ((Integer)extras.get("text")).intValue();
    261                     mColumn1.setTextColor(color);
    262                     mColumn2.setTextColor(color);
    263 
    264                     int colorTranslucent = (color & 0x00FFFFFF) + 0x77000000;
    265 
    266                     setTitleColor(color);
    267 
    268                     Integer texture = (Integer)extras.get("texture");
    269                     if (texture != null) {
    270                         mContentView.setBackgroundResource(texture.intValue());
    271                     } else {
    272                         color = ((Integer)extras.get("bgcolor")).intValue();
    273                         mContentView.setBackgroundColor(color);
    274                     }
    275                 }
    276                 break;
    277             }
    278         }
    279     }
    280 
    281     @Override public boolean onKeyDown(int keyCode, KeyEvent event) {
    282         int size = mFontSize;
    283         int scaleX = mTextScaleXDelta;
    284 
    285         switch (keyCode) {
    286             case KeyEvent.KEYCODE_DPAD_DOWN:
    287                 size -= 1;
    288                 break;
    289             case KeyEvent.KEYCODE_DPAD_UP:
    290                 size += 1;
    291                 break;
    292             case KeyEvent.KEYCODE_DPAD_RIGHT:
    293                 scaleX += 1;
    294                 break;
    295             case KeyEvent.KEYCODE_DPAD_LEFT:
    296                 scaleX -= 1;
    297                 break;
    298             case KeyEvent.KEYCODE_U:
    299             case KeyEvent.KEYCODE_VOLUME_UP:
    300                 changeGamma(1);
    301                 return true;
    302             case KeyEvent.KEYCODE_D:
    303             case KeyEvent.KEYCODE_VOLUME_DOWN:
    304                 changeGamma(-1);
    305                 return true;
    306             default:
    307                 return super.onKeyDown(keyCode, event);
    308         }
    309 
    310         size = Math.min(MAX_SIZE, Math.max(MIN_SIZE, size));
    311         if (size != mFontSize) {
    312             mFontSize = size;
    313             mColumn1.setTextSize(mFontSize);
    314             mColumn2.setTextSize(mFontSize);
    315             updateTitle();
    316             return true;
    317         }
    318 
    319         scaleX = Math.min(MAX_SCALE_X, Math.max(MIN_SCALE_X, scaleX));
    320         if (scaleX != mTextScaleXDelta) {
    321             mTextScaleXDelta = scaleX;
    322             mColumn1.setTextScaleX(1 + scaleX / SCALE_X_RANGE);
    323             mColumn2.setTextScaleX(1 + scaleX / SCALE_X_RANGE);
    324             updateTitle();
    325             return true;
    326         }
    327 
    328         return super.onKeyDown(keyCode, event);
    329     }
    330 
    331     // default to gamma of 1.0
    332     private int mGamma = Math.round(1.0f * GAMMA_RANGE);
    333 
    334     private void changeGamma(int delta) {
    335         int gamma = Math.min(MAX_GAMMA, Math.max(MIN_GAMMA, mGamma + delta));
    336         if (gamma != mGamma) {
    337             mGamma = gamma;
    338             updateTitle();
    339             float blackGamma = mGamma / GAMMA_RANGE;
    340             Typeface.setGammaForText(blackGamma, 1 / blackGamma);
    341             mContentView.invalidate();
    342         }
    343     }
    344 
    345     private void setFont(TextView t, TextView f, Map extras) {
    346         int style = ((Integer)extras.get("style")).intValue();
    347         String font = (String)extras.get("font");
    348         t.setTypeface(Typeface.create(font, style));
    349 
    350         f.setText((String)extras.get("title"));
    351     }
    352 
    353     MenuItem.OnMenuItemClickListener mTextCallback = new MenuItem.OnMenuItemClickListener() {
    354         public boolean onMenuItemClick(MenuItem item) {
    355             mTextIndex += 1;
    356             updateText();
    357             return true;
    358         }
    359     };
    360 
    361     private static final int BACKGROUND_PICKED = 1;
    362 
    363     private TextView mColumn1;
    364     private TextView mColumn2;
    365     private View mContentView;
    366     private int mFontIndex = FONT_INDEX_SANS;
    367     private int mFontStyle = Typeface.NORMAL;
    368     private int mFontSize = 18;
    369     private int mTextIndex;
    370     private int mTextScaleXDelta;
    371 }
    372 
    373