1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17/**
18 * @author Alexey A. Petrenko
19 * @version $Revision$
20 */
21
22package java.awt;
23
24import java.util.Collection;
25import java.util.HashMap;
26import java.util.Iterator;
27import java.util.Map;
28import java.util.Set;
29
30/**
31 * The RenderingHints class represents preferences for the rendering algorithms.
32 * The preferences are arbitrary and can be specified by Map objects or by
33 * key-value pairs.
34 *
35 * @since Android 1.0
36 */
37public class RenderingHints implements Map<Object, Object>, Cloneable {
38
39    /**
40     * The Constant KEY_ALPHA_INTERPOLATION - alpha interpolation rendering hint
41     * key.
42     */
43    public static final Key KEY_ALPHA_INTERPOLATION = new KeyImpl(1);
44
45    /**
46     * The Constant VALUE_ALPHA_INTERPOLATION_DEFAULT - alpha interpolation
47     * rendering hint value.
48     */
49    public static final Object VALUE_ALPHA_INTERPOLATION_DEFAULT = new KeyValue(
50            KEY_ALPHA_INTERPOLATION);
51
52    /**
53     * The Constant VALUE_ALPHA_INTERPOLATION_SPEED - alpha interpolation
54     * rendering hint value.
55     */
56    public static final Object VALUE_ALPHA_INTERPOLATION_SPEED = new KeyValue(
57            KEY_ALPHA_INTERPOLATION);
58
59    /**
60     * The Constant VALUE_ALPHA_INTERPOLATION_QUALITY - alpha interpolation
61     * rendering hint value.
62     */
63    public static final Object VALUE_ALPHA_INTERPOLATION_QUALITY = new KeyValue(
64            KEY_ALPHA_INTERPOLATION);
65
66    /**
67     * The Constant KEY_ANTIALIASING - antialiasing rendering hint key.
68     */
69    public static final Key KEY_ANTIALIASING = new KeyImpl(2);
70
71    /**
72     * The Constant VALUE_ANTIALIAS_DEFAULT - antialiasing rendering hint value.
73     */
74    public static final Object VALUE_ANTIALIAS_DEFAULT = new KeyValue(KEY_ANTIALIASING);
75
76    /**
77     * The Constant VALUE_ANTIALIAS_ON - antialiasing rendering hint value.
78     */
79    public static final Object VALUE_ANTIALIAS_ON = new KeyValue(KEY_ANTIALIASING);
80
81    /**
82     * The Constant VALUE_ANTIALIAS_OFF - antialiasing rendering hint value.
83     */
84    public static final Object VALUE_ANTIALIAS_OFF = new KeyValue(KEY_ANTIALIASING);
85
86    /**
87     * The Constant KEY_COLOR_RENDERING - color rendering hint key.
88     */
89    public static final Key KEY_COLOR_RENDERING = new KeyImpl(3);
90
91    /**
92     * The Constant VALUE_COLOR_RENDER_DEFAULT - color rendering hint value.
93     */
94    public static final Object VALUE_COLOR_RENDER_DEFAULT = new KeyValue(KEY_COLOR_RENDERING);
95
96    /**
97     * The Constant VALUE_COLOR_RENDER_SPEED - color rendering hint value.
98     */
99    public static final Object VALUE_COLOR_RENDER_SPEED = new KeyValue(KEY_COLOR_RENDERING);
100
101    /**
102     * The Constant VALUE_COLOR_RENDER_QUALITY - color rendering hint value.
103     */
104    public static final Object VALUE_COLOR_RENDER_QUALITY = new KeyValue(KEY_COLOR_RENDERING);
105
106    /**
107     * The Constant KEY_DITHERING - dithering rendering hint key.
108     */
109    public static final Key KEY_DITHERING = new KeyImpl(4);
110
111    /**
112     * The Constant VALUE_DITHER_DEFAULT - dithering rendering hint value.
113     */
114    public static final Object VALUE_DITHER_DEFAULT = new KeyValue(KEY_DITHERING);
115
116    /**
117     * The Constant VALUE_DITHER_DISABLE - dithering rendering hint value.
118     */
119    public static final Object VALUE_DITHER_DISABLE = new KeyValue(KEY_DITHERING);
120
121    /**
122     * The Constant VALUE_DITHER_DISABLE - dithering rendering hint value.
123     */
124    public static final Object VALUE_DITHER_ENABLE = new KeyValue(KEY_DITHERING);
125
126    /**
127     * The Constant KEY_FRACTIONALMETRICS - fractional metrics rendering hint
128     * key.
129     */
130    public static final Key KEY_FRACTIONALMETRICS = new KeyImpl(5);
131
132    /**
133     * The Constant VALUE_FRACTIONALMETRICS_DEFAULT - fractional metrics
134     * rendering hint value.
135     */
136    public static final Object VALUE_FRACTIONALMETRICS_DEFAULT = new KeyValue(KEY_FRACTIONALMETRICS);
137
138    /**
139     * The Constant VALUE_FRACTIONALMETRICS_ON - fractional metrics rendering
140     * hint value.
141     */
142    public static final Object VALUE_FRACTIONALMETRICS_ON = new KeyValue(KEY_FRACTIONALMETRICS);
143
144    /**
145     * The Constant VALUE_FRACTIONALMETRICS_OFF - fractional metrics rendering
146     * hint value.
147     */
148    public static final Object VALUE_FRACTIONALMETRICS_OFF = new KeyValue(KEY_FRACTIONALMETRICS);
149
150    /**
151     * The Constant KEY_INTERPOLATION - interpolation rendering hint key.
152     */
153    public static final Key KEY_INTERPOLATION = new KeyImpl(6);
154
155    /**
156     * The Constant VALUE_INTERPOLATION_BICUBIC - interpolation rendering hint
157     * value.
158     */
159    public static final Object VALUE_INTERPOLATION_BICUBIC = new KeyValue(KEY_INTERPOLATION);
160
161    /**
162     * The Constant VALUE_INTERPOLATION_BILINEAR - interpolation rendering hint
163     * value.
164     */
165    public static final Object VALUE_INTERPOLATION_BILINEAR = new KeyValue(KEY_INTERPOLATION);
166
167    /**
168     * The Constant VALUE_INTERPOLATION_NEAREST_NEIGHBOR - interpolation
169     * rendering hint value.
170     */
171    public static final Object VALUE_INTERPOLATION_NEAREST_NEIGHBOR = new KeyValue(
172            KEY_INTERPOLATION);
173
174    /**
175     * The Constant KEY_RENDERING - rendering hint key.
176     */
177    public static final Key KEY_RENDERING = new KeyImpl(7);
178
179    /**
180     * The Constant VALUE_RENDER_DEFAULT - rendering hint value.
181     */
182    public static final Object VALUE_RENDER_DEFAULT = new KeyValue(KEY_RENDERING);
183
184    /**
185     * The Constant VALUE_RENDER_SPEED - rendering hint value.
186     */
187    public static final Object VALUE_RENDER_SPEED = new KeyValue(KEY_RENDERING);
188
189    /**
190     * The Constant VALUE_RENDER_QUALITY - rendering hint value.
191     */
192    public static final Object VALUE_RENDER_QUALITY = new KeyValue(KEY_RENDERING);
193
194    /**
195     * The Constant KEY_STROKE_CONTROL - stroke control hint key.
196     */
197    public static final Key KEY_STROKE_CONTROL = new KeyImpl(8);
198
199    /**
200     * The Constant VALUE_STROKE_DEFAULT - stroke hint value.
201     */
202    public static final Object VALUE_STROKE_DEFAULT = new KeyValue(KEY_STROKE_CONTROL);
203
204    /**
205     * The Constant VALUE_STROKE_NORMALIZE - stroke hint value.
206     */
207    public static final Object VALUE_STROKE_NORMALIZE = new KeyValue(KEY_STROKE_CONTROL);
208
209    /**
210     * The Constant VALUE_STROKE_PURE - stroke hint value.
211     */
212    public static final Object VALUE_STROKE_PURE = new KeyValue(KEY_STROKE_CONTROL);
213
214    /**
215     * The Constant KEY_TEXT_ANTIALIASING - text antialiasing hint key.
216     */
217    public static final Key KEY_TEXT_ANTIALIASING = new KeyImpl(9);
218
219    /**
220     * The Constant VALUE_TEXT_ANTIALIAS_DEFAULT - text antialiasing hint key.
221     */
222    public static final Object VALUE_TEXT_ANTIALIAS_DEFAULT = new KeyValue(KEY_TEXT_ANTIALIASING);
223
224    /**
225     * The Constant VALUE_TEXT_ANTIALIAS_ON - text antialiasing hint key.
226     */
227    public static final Object VALUE_TEXT_ANTIALIAS_ON = new KeyValue(KEY_TEXT_ANTIALIASING);
228
229    /**
230     * The Constant VALUE_TEXT_ANTIALIAS_OFF - text antialiasing hint key.
231     */
232    public static final Object VALUE_TEXT_ANTIALIAS_OFF = new KeyValue(KEY_TEXT_ANTIALIASING);
233
234    /** The map. */
235    private HashMap<Object, Object> map = new HashMap<Object, Object>();
236
237    /**
238     * Instantiates a new rendering hints object from specified Map object with
239     * defined key/value pairs or null for empty RenderingHints.
240     *
241     * @param map
242     *            the Map object with defined key/value pairs or null for empty
243     *            RenderingHints.
244     */
245    public RenderingHints(Map<Key, ?> map) {
246        super();
247        if (map != null) {
248            putAll(map);
249        }
250    }
251
252    /**
253     * Instantiates a new rendering hints object with the specified key/value
254     * pair.
255     *
256     * @param key
257     *            the key of hint property.
258     * @param value
259     *            the value of hint property.
260     */
261    public RenderingHints(Key key, Object value) {
262        super();
263        put(key, value);
264    }
265
266    /**
267     * Adds the properties represented by key/value pairs from the specified
268     * RenderingHints object to current object.
269     *
270     * @param hints
271     *            the RenderingHints to be added.
272     */
273    public void add(RenderingHints hints) {
274        map.putAll(hints.map);
275    }
276
277    /**
278     * Puts the specified value to the specified key. Neither the key nor the
279     * value can be null.
280     *
281     * @param key
282     *            the rendering hint key.
283     * @param value
284     *            the rendering hint value.
285     * @return the previous rendering hint value assigned to the key or null.
286     */
287    public Object put(Object key, Object value) {
288        if (!((Key)key).isCompatibleValue(value)) {
289            throw new IllegalArgumentException();
290        }
291
292        return map.put(key, value);
293    }
294
295    /**
296     * Removes the specified key and corresponding value from the RenderingHints
297     * object.
298     *
299     * @param key
300     *            the specified hint key to be removed.
301     * @return the object of previous rendering hint value which is assigned to
302     *         the specified key, or null.
303     */
304    public Object remove(Object key) {
305        return map.remove(key);
306    }
307
308    /**
309     * Gets the value assigned to the specified key.
310     *
311     * @param key
312     *            the rendering hint key.
313     * @return the object assigned to the specified key.
314     */
315    public Object get(Object key) {
316        return map.get(key);
317    }
318
319    /**
320     * Returns a set of rendering hints keys for current RenderingHints object.
321     *
322     * @return the set of rendering hints keys.
323     */
324    public Set<Object> keySet() {
325        return map.keySet();
326    }
327
328    /**
329     * Returns a set of Map.Entry objects which contain current RenderingHint
330     * key/value pairs.
331     *
332     * @return the a set of mapped RenderingHint key/value pairs.
333     */
334    public Set<Map.Entry<Object, Object>> entrySet() {
335        return map.entrySet();
336    }
337
338    /**
339     * Puts all of the preferences from the specified Map into the current
340     * RenderingHints object. These mappings replace all existing preferences.
341     *
342     * @param m
343     *            the specified Map of preferences.
344     */
345    public void putAll(Map<?, ?> m) {
346        if (m instanceof RenderingHints) {
347            map.putAll(((RenderingHints)m).map);
348        } else {
349            Set<?> entries = m.entrySet();
350
351            if (entries != null) {
352                Iterator<?> it = entries.iterator();
353                while (it.hasNext()) {
354                    Map.Entry<?, ?> entry = (Map.Entry<?, ?>)it.next();
355                    Key key = (Key)entry.getKey();
356                    Object val = entry.getValue();
357                    put(key, val);
358                }
359            }
360        }
361    }
362
363    /**
364     * Returns a Collection of values contained in current RenderingHints
365     * object.
366     *
367     * @return the Collection of RenderingHints's values.
368     */
369    public Collection<Object> values() {
370        return map.values();
371    }
372
373    /**
374     * Checks whether or not current RenderingHints object contains at least one
375     * the value which is equal to the specified Object.
376     *
377     * @param value
378     *            the specified Object.
379     * @return true, if the specified object is assigned to at least one
380     *         RenderingHint's key, false otherwise.
381     */
382    public boolean containsValue(Object value) {
383        return map.containsValue(value);
384    }
385
386    /**
387     * Checks whether or not current RenderingHints object contains the key
388     * which is equal to the specified Object.
389     *
390     * @param key
391     *            the specified Object.
392     * @return true, if the RenderingHints object contains the specified Object
393     *         as a key, false otherwise.
394     */
395    public boolean containsKey(Object key) {
396        if (key == null) {
397            throw new NullPointerException();
398        }
399
400        return map.containsKey(key);
401    }
402
403    /**
404     * Checks whether or not the RenderingHints object contains any key/value
405     * pairs.
406     *
407     * @return true, if the RenderingHints object is empty, false otherwise.
408     */
409    public boolean isEmpty() {
410        return map.isEmpty();
411    }
412
413    /**
414     * Clears the RenderingHints of all key/value pairs.
415     */
416    public void clear() {
417        map.clear();
418    }
419
420    /**
421     * Returns the number of key/value pairs in the RenderingHints.
422     *
423     * @return the number of key/value pairs.
424     */
425    public int size() {
426        return map.size();
427    }
428
429    /**
430     * Compares the RenderingHints object with the specified object.
431     *
432     * @param o
433     *            the specified Object to be compared.
434     * @return true, if the Object is a Map whose key/value pairs match this
435     *         RenderingHints' key/value pairs, false otherwise.
436     */
437    @Override
438    public boolean equals(Object o) {
439        if (!(o instanceof Map)) {
440            return false;
441        }
442
443        Map<?, ?> m = (Map<?, ?>)o;
444        Set<?> keys = keySet();
445        if (!keys.equals(m.keySet())) {
446            return false;
447        }
448
449        Iterator<?> it = keys.iterator();
450        while (it.hasNext()) {
451            Key key = (Key)it.next();
452            Object v1 = get(key);
453            Object v2 = m.get(key);
454            if (!(v1 == null ? v2 == null : v1.equals(v2))) {
455                return false;
456            }
457        }
458        return true;
459    }
460
461    /**
462     * Returns the hash code for this RenderingHints object.
463     *
464     * @return the hash code for this RenderingHints object.
465     */
466    @Override
467    public int hashCode() {
468        return map.hashCode();
469    }
470
471    /**
472     * Returns the clone of the RenderingHints object with the same contents.
473     *
474     * @return the clone of the RenderingHints instance.
475     */
476    @SuppressWarnings("unchecked")
477    @Override
478    public Object clone() {
479        RenderingHints clone = new RenderingHints(null);
480        clone.map = (HashMap<Object, Object>)this.map.clone();
481        return clone;
482    }
483
484    /**
485     * Returns the string representation of the RenderingHints object.
486     *
487     * @return the String object which represents RenderingHints object.
488     */
489    @Override
490    public String toString() {
491        return "RenderingHints[" + map.toString() + "]"; //$NON-NLS-1$ //$NON-NLS-2$
492    }
493
494    /**
495     * The RenderingHints.Key class is abstract and defines a base type for all
496     * RenderingHints keys.
497     *
498     * @since Android 1.0
499     */
500    public abstract static class Key {
501
502        /** The key. */
503        private final int key;
504
505        /**
506         * Instantiates a new key with unique integer identifier. No two objects
507         * of the same subclass with the same integer key can be instantiated.
508         *
509         * @param key
510         *            the unique key.
511         */
512        protected Key(int key) {
513            this.key = key;
514        }
515
516        /**
517         * Compares the Key object with the specified object.
518         *
519         * @param o
520         *            the specified Object to be compared.
521         * @return true, if the Key is equal to the specified object, false
522         *         otherwise.
523         */
524        @Override
525        public final boolean equals(Object o) {
526            return this == o;
527        }
528
529        /**
530         * Returns the hash code for this Key object.
531         *
532         * @return the hash code for this Key object.
533         */
534        @Override
535        public final int hashCode() {
536            return System.identityHashCode(this);
537        }
538
539        /**
540         * Returns integer unique key with which this Key object has been
541         * instantiated.
542         *
543         * @return the integer unique key with which this Key object has been
544         *         instantiated.
545         */
546        protected final int intKey() {
547            return key;
548        }
549
550        /**
551         * Checks whether or not specified value is compatible with the Key.
552         *
553         * @param val
554         *            the Object.
555         * @return true, if the specified value is compatible with the Key,
556         *         false otherwise.
557         */
558        public abstract boolean isCompatibleValue(Object val);
559    }
560
561    /**
562     * Private implementation of Key class.
563     */
564    private static class KeyImpl extends Key {
565
566        /**
567         * Instantiates a new key implementation.
568         *
569         * @param key
570         *            the key.
571         */
572        protected KeyImpl(int key) {
573            super(key);
574        }
575
576        @Override
577        public boolean isCompatibleValue(Object val) {
578            if (!(val instanceof KeyValue)) {
579                return false;
580            }
581
582            return ((KeyValue)val).key == this;
583        }
584    }
585
586    /**
587     * Private class KeyValue is used as value for Key class instance.
588     */
589    private static class KeyValue {
590
591        /**
592         * The key.
593         */
594        private final Key key;
595
596        /**
597         * Instantiates a new key value.
598         *
599         * @param key
600         *            the key.
601         */
602        protected KeyValue(Key key) {
603            this.key = key;
604        }
605    }
606}
607