1 /* 2 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.awt; 27 28 import java.util.Map; 29 import java.util.Set; 30 import java.util.Collection; 31 import java.util.Collections; 32 import java.util.HashMap; 33 import java.util.Iterator; 34 import sun.awt.SunHints; 35 import java.lang.ref.WeakReference; 36 37 /** 38 * The {@code RenderingHints} class defines and manages collections of 39 * keys and associated values which allow an application to provide input 40 * into the choice of algorithms used by other classes which perform 41 * rendering and image manipulation services. 42 * The {@link java.awt.Graphics2D} class, and classes that implement 43 * {@link java.awt.image.BufferedImageOp} and 44 * {@link java.awt.image.RasterOp} all provide methods to get and 45 * possibly to set individual or groups of {@code RenderingHints} 46 * keys and their associated values. 47 * When those implementations perform any rendering or image manipulation 48 * operations they should examine the values of any {@code RenderingHints} 49 * that were requested by the caller and tailor the algorithms used 50 * accordingly and to the best of their ability. 51 * <p> 52 * Note that since these keys and values are <i>hints</i>, there is 53 * no requirement that a given implementation supports all possible 54 * choices indicated below or that it can respond to requests to 55 * modify its choice of algorithm. 56 * The values of the various hint keys may also interact such that 57 * while all variants of a given key are supported in one situation, 58 * the implementation may be more restricted when the values associated 59 * with other keys are modified. 60 * For example, some implementations may be able to provide several 61 * types of dithering when the antialiasing hint is turned off, but 62 * have little control over dithering when antialiasing is on. 63 * The full set of supported keys and hints may also vary by destination 64 * since runtimes may use different underlying modules to render to 65 * the screen, or to {@link java.awt.image.BufferedImage} objects, 66 * or while printing. 67 * <p> 68 * Implementations are free to ignore the hints completely, but should 69 * try to use an implementation algorithm that is as close as possible 70 * to the request. 71 * If an implementation supports a given algorithm when any value is used 72 * for an associated hint key, then minimally it must do so when the 73 * value for that key is the exact value that specifies the algorithm. 74 * <p> 75 * The keys used to control the hints are all special values that 76 * subclass the associated {@link RenderingHints.Key} class. 77 * Many common hints are expressed below as static constants in this 78 * class, but the list is not meant to be exhaustive. 79 * Other hints may be created by other packages by defining new objects 80 * which subclass the {@code Key} class and defining the associated values. 81 */ 82 public class RenderingHints 83 implements Map<Object,Object>, Cloneable 84 { 85 /** 86 * Defines the base type of all keys used along with the 87 * {@link RenderingHints} class to control various 88 * algorithm choices in the rendering and imaging pipelines. 89 * Instances of this class are immutable and unique which 90 * means that tests for matches can be made using the 91 * {@code ==} operator instead of the more expensive 92 * {@code equals()} method. 93 */ 94 public abstract static class Key { 95 private static HashMap<Object,Object> identitymap = new HashMap<>(17); 96 97 private String getIdentity() { 98 // Note that the identity string is dependent on 3 variables: 99 // - the name of the subclass of Key 100 // - the identityHashCode of the subclass of Key 101 // - the integer key of the Key 102 // It is theoretically possible for 2 distinct keys to collide 103 // along all 3 of those attributes in the context of multiple 104 // class loaders, but that occurrence will be extremely rare and 105 // we account for that possibility below in the recordIdentity 106 // method by slightly relaxing our uniqueness guarantees if we 107 // end up in that situation. 108 return getClass().getName()+"@"+ 109 Integer.toHexString(System.identityHashCode(getClass()))+":"+ 110 Integer.toHexString(privatekey); 111 } 112 113 private static synchronized void recordIdentity(Key k) { 114 Object identity = k.getIdentity(); 115 Object otherref = identitymap.get(identity); 116 if (otherref != null) { 117 Key otherkey = (Key) ((WeakReference) otherref).get(); 118 if (otherkey != null && otherkey.getClass() == k.getClass()) { 119 throw new IllegalArgumentException(identity+ 120 " already registered"); 121 } 122 // Note that this system can fail in a mostly harmless 123 // way. If we end up generating the same identity 124 // String for 2 different classes (a very rare case) 125 // then we correctly avoid throwing the exception above, 126 // but we are about to drop through to a statement that 127 // will replace the entry for the old Key subclass with 128 // an entry for the new Key subclass. At that time the 129 // old subclass will be vulnerable to someone generating 130 // a duplicate Key instance for it. We could bail out 131 // of the method here and let the old identity keep its 132 // record in the map, but we are more likely to see a 133 // duplicate key go by for the new class than the old 134 // one since the new one is probably still in the 135 // initialization stage. In either case, the probability 136 // of loading 2 classes in the same VM with the same name 137 // and identityHashCode should be nearly impossible. 138 } 139 // Note: Use a weak reference to avoid holding on to extra 140 // objects and classes after they should be unloaded. 141 identitymap.put(identity, new WeakReference<Key>(k)); 142 } 143 144 private int privatekey; 145 146 /** 147 * Construct a key using the indicated private key. Each 148 * subclass of Key maintains its own unique domain of integer 149 * keys. No two objects with the same integer key and of the 150 * same specific subclass can be constructed. An exception 151 * will be thrown if an attempt is made to construct another 152 * object of a given class with the same integer key as a 153 * pre-existing instance of that subclass of Key. 154 * @param privatekey the specified key 155 */ 156 protected Key(int privatekey) { 157 this.privatekey = privatekey; 158 recordIdentity(this); 159 } 160 161 /** 162 * Returns true if the specified object is a valid value 163 * for this Key. 164 * @param val the <code>Object</code> to test for validity 165 * @return <code>true</code> if <code>val</code> is valid; 166 * <code>false</code> otherwise. 167 */ 168 public abstract boolean isCompatibleValue(Object val); 169 170 /** 171 * Returns the private integer key that the subclass 172 * instantiated this Key with. 173 * @return the private integer key that the subclass 174 * instantiated this Key with. 175 */ 176 protected final int intKey() { 177 return privatekey; 178 } 179 180 /** 181 * The hash code for all Key objects will be the same as the 182 * system identity code of the object as defined by the 183 * System.identityHashCode() method. 184 */ 185 public final int hashCode() { 186 return super.hashCode(); 187 } 188 189 /** 190 * The equals method for all Key objects will return the same 191 * result as the equality operator '=='. 192 */ 193 public final boolean equals(Object o) { 194 return this == o; 195 } 196 } 197 198 HashMap<Object,Object> hintmap = new HashMap<>(7); 199 200 /** 201 * Antialiasing hint key. 202 * The {@code ANTIALIASING} hint controls whether or not the 203 * geometry rendering methods of a {@link Graphics2D} object 204 * will attempt to reduce aliasing artifacts along the edges 205 * of shapes. 206 * <p> 207 * A typical antialiasing algorithm works by blending the existing 208 * colors of the pixels along the boundary of a shape with the 209 * requested fill paint according to the estimated partial pixel 210 * coverage of the shape. 211 * <p> 212 * The allowable values for this hint are 213 * <ul> 214 * <li>{@link #VALUE_ANTIALIAS_ON} 215 * <li>{@link #VALUE_ANTIALIAS_OFF} 216 * <li>{@link #VALUE_ANTIALIAS_DEFAULT} 217 * </ul> 218 */ 219 public static final Key KEY_ANTIALIASING = 220 SunHints.KEY_ANTIALIASING; 221 222 /** 223 * Antialiasing hint value -- rendering is done with antialiasing. 224 * @see #KEY_ANTIALIASING 225 */ 226 public static final Object VALUE_ANTIALIAS_ON = 227 SunHints.VALUE_ANTIALIAS_ON; 228 229 /** 230 * Antialiasing hint value -- rendering is done without antialiasing. 231 * @see #KEY_ANTIALIASING 232 */ 233 public static final Object VALUE_ANTIALIAS_OFF = 234 SunHints.VALUE_ANTIALIAS_OFF; 235 236 /** 237 * Antialiasing hint value -- rendering is done with a default 238 * antialiasing mode chosen by the implementation. 239 * @see #KEY_ANTIALIASING 240 */ 241 public static final Object VALUE_ANTIALIAS_DEFAULT = 242 SunHints.VALUE_ANTIALIAS_DEFAULT; 243 244 /** 245 * Rendering hint key. 246 * The {@code RENDERING} hint is a general hint that provides 247 * a high level recommendation as to whether to bias algorithm 248 * choices more for speed or quality when evaluating tradeoffs. 249 * This hint could be consulted for any rendering or image 250 * manipulation operation, but decisions will usually honor 251 * other, more specific hints in preference to this hint. 252 * <p> 253 * The allowable values for this hint are 254 * <ul> 255 * <li>{@link #VALUE_RENDER_SPEED} 256 * <li>{@link #VALUE_RENDER_QUALITY} 257 * <li>{@link #VALUE_RENDER_DEFAULT} 258 * </ul> 259 */ 260 public static final Key KEY_RENDERING = 261 SunHints.KEY_RENDERING; 262 263 /** 264 * Rendering hint value -- rendering algorithms are chosen 265 * with a preference for output speed. 266 * @see #KEY_RENDERING 267 */ 268 public static final Object VALUE_RENDER_SPEED = 269 SunHints.VALUE_RENDER_SPEED; 270 271 /** 272 * Rendering hint value -- rendering algorithms are chosen 273 * with a preference for output quality. 274 * @see #KEY_RENDERING 275 */ 276 public static final Object VALUE_RENDER_QUALITY = 277 SunHints.VALUE_RENDER_QUALITY; 278 279 /** 280 * Rendering hint value -- rendering algorithms are chosen 281 * by the implementation for a good tradeoff of performance 282 * vs. quality. 283 * @see #KEY_RENDERING 284 */ 285 public static final Object VALUE_RENDER_DEFAULT = 286 SunHints.VALUE_RENDER_DEFAULT; 287 288 /** 289 * Dithering hint key. 290 * The {@code DITHERING} hint controls how closely to approximate 291 * a color when storing into a destination with limited color 292 * resolution. 293 * <p> 294 * Some rendering destinations may support a limited number of 295 * color choices which may not be able to accurately represent 296 * the full spectrum of colors that can result during rendering 297 * operations. 298 * For such a destination the {@code DITHERING} hint controls 299 * whether rendering is done with a flat solid fill of a single 300 * pixel value which is the closest supported color to what was 301 * requested, or whether shapes will be filled with a pattern of 302 * colors which combine to better approximate that color. 303 * <p> 304 * The allowable values for this hint are 305 * <ul> 306 * <li>{@link #VALUE_DITHER_DISABLE} 307 * <li>{@link #VALUE_DITHER_ENABLE} 308 * <li>{@link #VALUE_DITHER_DEFAULT} 309 * </ul> 310 */ 311 public static final Key KEY_DITHERING = 312 SunHints.KEY_DITHERING; 313 314 /** 315 * Dithering hint value -- do not dither when rendering geometry. 316 * @see #KEY_DITHERING 317 */ 318 public static final Object VALUE_DITHER_DISABLE = 319 SunHints.VALUE_DITHER_DISABLE; 320 321 /** 322 * Dithering hint value -- dither when rendering geometry, if needed. 323 * @see #KEY_DITHERING 324 */ 325 public static final Object VALUE_DITHER_ENABLE = 326 SunHints.VALUE_DITHER_ENABLE; 327 328 /** 329 * Dithering hint value -- use a default for dithering chosen by 330 * the implementation. 331 * @see #KEY_DITHERING 332 */ 333 public static final Object VALUE_DITHER_DEFAULT = 334 SunHints.VALUE_DITHER_DEFAULT; 335 336 /** 337 * Text antialiasing hint key. 338 * The {@code TEXT_ANTIALIASING} hint can control the use of 339 * antialiasing algorithms for text independently of the 340 * choice used for shape rendering. 341 * Often an application may want to use antialiasing for text 342 * only and not for other shapes. 343 * Additionally, the algorithms for reducing the aliasing 344 * artifacts for text are often more sophisticated than those 345 * that have been developed for general rendering so this 346 * hint key provides additional values which can control 347 * the choices of some of those text-specific algorithms. 348 * If left in the {@code DEFAULT} state, this hint will 349 * generally defer to the value of the regular 350 * {@link #KEY_ANTIALIASING} hint key. 351 * <p> 352 * The allowable values for this hint are 353 * <ul> 354 * <li>{@link #VALUE_TEXT_ANTIALIAS_ON} 355 * <li>{@link #VALUE_TEXT_ANTIALIAS_OFF} 356 * <li>{@link #VALUE_TEXT_ANTIALIAS_DEFAULT} 357 * <li>{@link #VALUE_TEXT_ANTIALIAS_GASP} 358 * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB} 359 * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_HBGR} 360 * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_VRGB} 361 * <li>{@link #VALUE_TEXT_ANTIALIAS_LCD_VBGR} 362 * </ul> 363 */ 364 public static final Key KEY_TEXT_ANTIALIASING = 365 SunHints.KEY_TEXT_ANTIALIASING; 366 367 /** 368 * Text antialiasing hint value -- text rendering is done with 369 * some form of antialiasing. 370 * @see #KEY_TEXT_ANTIALIASING 371 */ 372 public static final Object VALUE_TEXT_ANTIALIAS_ON = 373 SunHints.VALUE_TEXT_ANTIALIAS_ON; 374 375 /** 376 * Text antialiasing hint value -- text rendering is done without 377 * any form of antialiasing. 378 * @see #KEY_TEXT_ANTIALIASING 379 */ 380 public static final Object VALUE_TEXT_ANTIALIAS_OFF = 381 SunHints.VALUE_TEXT_ANTIALIAS_OFF; 382 383 /** 384 * Text antialiasing hint value -- text rendering is done according 385 * to the {@link #KEY_ANTIALIASING} hint or a default chosen by the 386 * implementation. 387 * @see #KEY_TEXT_ANTIALIASING 388 */ 389 public static final Object VALUE_TEXT_ANTIALIAS_DEFAULT = 390 SunHints.VALUE_TEXT_ANTIALIAS_DEFAULT; 391 392 /** 393 * Text antialiasing hint value -- text rendering is requested to 394 * use information in the font resource which specifies for each point 395 * size whether to apply {@link #VALUE_TEXT_ANTIALIAS_ON} or 396 * {@link #VALUE_TEXT_ANTIALIAS_OFF}. 397 * <p> 398 * TrueType fonts typically provide this information in the 'gasp' table. 399 * In the absence of this information, the behaviour for a particular 400 * font and size is determined by implementation defaults. 401 * <p> 402 * <i>Note:</i>A font designer will typically carefully hint a font for 403 * the most common user interface point sizes. Consequently the 'gasp' 404 * table will likely specify to use only hinting at those sizes and not 405 * "smoothing". So in many cases the resulting text display is 406 * equivalent to {@code VALUE_TEXT_ANTIALIAS_OFF}. 407 * This may be unexpected but is correct. 408 * <p> 409 * Logical fonts which are composed of multiple physical fonts will for 410 * consistency will use the setting most appropriate for the overall 411 * composite font. 412 * 413 * @see #KEY_TEXT_ANTIALIASING 414 * @since 1.6 415 */ 416 public static final Object VALUE_TEXT_ANTIALIAS_GASP = 417 SunHints.VALUE_TEXT_ANTIALIAS_GASP; 418 419 /** 420 * Text antialiasing hint value -- request that text be displayed 421 * optimised for an LCD display with subpixels in order from display 422 * left to right of R,G,B such that the horizontal subpixel resolution 423 * is three times that of the full pixel horizontal resolution (HRGB). 424 * This is the most common configuration. 425 * Selecting this hint for displays with one of the other LCD subpixel 426 * configurations will likely result in unfocused text. 427 * <p> 428 * <i>Notes:</i><br> 429 * An implementation when choosing whether to apply any of the 430 * LCD text hint values may take into account factors including requiring 431 * color depth of the destination to be at least 15 bits per pixel 432 * (ie 5 bits per color component), 433 * characteristics of a font such as whether embedded bitmaps may 434 * produce better results, or when displaying to a non-local networked 435 * display device enabling it only if suitable protocols are available, 436 * or ignoring the hint if performing very high resolution rendering 437 * or the target device is not appropriate: eg when printing. 438 * <p> 439 * These hints can equally be applied when rendering to software images, 440 * but these images may not then be suitable for general export, as the 441 * text will have been rendered appropriately for a specific subpixel 442 * organisation. Also lossy images are not a good choice, nor image 443 * formats such as GIF which have limited colors. 444 * So unless the image is destined solely for rendering on a 445 * display device with the same configuration, some other text 446 * anti-aliasing hint such as 447 * {@link #VALUE_TEXT_ANTIALIAS_ON} 448 * may be a better choice. 449 * <p>Selecting a value which does not match the LCD display in use 450 * will likely lead to a degradation in text quality. 451 * On display devices (ie CRTs) which do not have the same characteristics 452 * as LCD displays, the overall effect may appear similar to standard text 453 * anti-aliasing, but the quality may be degraded by color distortion. 454 * Analog connected LCD displays may also show little advantage over 455 * standard text-antialiasing and be similar to CRTs. 456 * <p> 457 * In other words for the best results use an LCD display with a digital 458 * display connector and specify the appropriate sub-pixel configuration. 459 * 460 * @see #KEY_TEXT_ANTIALIASING 461 * @since 1.6 462 */ 463 public static final Object VALUE_TEXT_ANTIALIAS_LCD_HRGB = 464 SunHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB; 465 466 /** 467 * Text antialiasing hint value -- request that text be displayed 468 * optimised for an LCD display with subpixels in order from display 469 * left to right of B,G,R such that the horizontal subpixel resolution 470 * is three times that of the full pixel horizontal resolution (HBGR). 471 * This is a much less common configuration than HRGB. 472 * Selecting this hint for displays with one of the other LCD subpixel 473 * configurations will likely result in unfocused text. 474 * See {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB}, 475 * for more information on when this hint is applied. 476 * 477 * @see #KEY_TEXT_ANTIALIASING 478 * @since 1.6 479 */ 480 public static final Object VALUE_TEXT_ANTIALIAS_LCD_HBGR = 481 SunHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR; 482 483 /** 484 * Text antialiasing hint value -- request that text be displayed 485 * optimised for an LCD display with subpixel organisation from display 486 * top to bottom of R,G,B such that the vertical subpixel resolution is 487 * three times that of the full pixel vertical resolution (VRGB). 488 * Vertical orientation is very uncommon and probably mainly useful 489 * for a physically rotated display. 490 * Selecting this hint for displays with one of the other LCD subpixel 491 * configurations will likely result in unfocused text. 492 * See {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB}, 493 * for more information on when this hint is applied. 494 * 495 * @see #KEY_TEXT_ANTIALIASING 496 * @since 1.6 497 */ 498 public static final Object VALUE_TEXT_ANTIALIAS_LCD_VRGB = 499 SunHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB; 500 501 /** 502 * Text antialiasing hint value -- request that text be displayed 503 * optimised for an LCD display with subpixel organisation from display 504 * top to bottom of B,G,R such that the vertical subpixel resolution is 505 * three times that of the full pixel vertical resolution (VBGR). 506 * Vertical orientation is very uncommon and probably mainly useful 507 * for a physically rotated display. 508 * Selecting this hint for displays with one of the other LCD subpixel 509 * configurations will likely result in unfocused text. 510 * See {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB}, 511 * for more information on when this hint is applied. 512 * 513 * @see #KEY_TEXT_ANTIALIASING 514 * @since 1.6 515 */ 516 public static final Object VALUE_TEXT_ANTIALIAS_LCD_VBGR = 517 SunHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR; 518 519 520 /** 521 * LCD text contrast rendering hint key. 522 * The value is an <code>Integer</code> object which is used as a text 523 * contrast adjustment when used in conjunction with an LCD text 524 * anti-aliasing hint such as 525 * {@link #VALUE_TEXT_ANTIALIAS_LCD_HRGB}. 526 * <ul> 527 * <li>Values should be a positive integer in the range 100 to 250. 528 * <li>A lower value (eg 100) corresponds to higher contrast text when 529 * displaying dark text on a light background. 530 * <li>A higher value (eg 200) corresponds to lower contrast text when 531 * displaying dark text on a light background. 532 * <li>A typical useful value is in the narrow range 140-180. 533 * <li>If no value is specified, a system or implementation default value 534 * will be applied. 535 * </ul> 536 * The default value can be expected to be adequate for most purposes, 537 * so clients should rarely need to specify a value for this hint unless 538 * they have concrete information as to an appropriate value. 539 * A higher value does not mean a higher contrast, in fact the opposite 540 * is true. 541 * The correction is applied in a similar manner to a gamma adjustment 542 * for non-linear perceptual luminance response of display systems, but 543 * does not indicate a full correction for this. 544 * 545 * @see #KEY_TEXT_ANTIALIASING 546 * @since 1.6 547 */ 548 public static final Key KEY_TEXT_LCD_CONTRAST = 549 SunHints.KEY_TEXT_ANTIALIAS_LCD_CONTRAST; 550 551 /** 552 * Font fractional metrics hint key. 553 * The {@code FRACTIONALMETRICS} hint controls whether the positioning 554 * of individual character glyphs takes into account the sub-pixel 555 * accuracy of the scaled character advances of the font or whether 556 * such advance vectors are rounded to an integer number of whole 557 * device pixels. 558 * This hint only recommends how much accuracy should be used to 559 * position the glyphs and does not specify or recommend whether or 560 * not the actual rasterization or pixel bounds of the glyph should 561 * be modified to match. 562 * <p> 563 * Rendering text to a low resolution device like a screen will 564 * necessarily involve a number of rounding operations as the 565 * high quality and very precise definition of the shape and 566 * metrics of the character glyphs must be matched to discrete 567 * device pixels. 568 * Ideally the positioning of glyphs during text layout would be 569 * calculated by scaling the design metrics in the font according 570 * to the point size, but then the scaled advance width will not 571 * necessarily be an integer number of pixels. 572 * If the glyphs are positioned with sub-pixel accuracy according 573 * to these scaled design metrics then the rasterization would 574 * ideally need to be adjusted for each possible sub-pixel origin. 575 * <p> 576 * Unfortunately, scaling each glyph customized to its exact 577 * subpixel origin during text layout would be prohibitively 578 * expensive so a simplified system based on integer device 579 * positions is typically used to lay out the text. 580 * The rasterization of the glyph and the scaled advance width 581 * are both adjusted together to yield text that looks good at 582 * device resolution and has consistent integer pixel distances 583 * between glyphs that help the glyphs look uniformly and 584 * consistently spaced and readable. 585 * <p> 586 * This process of rounding advance widths for rasterized glyphs 587 * to integer distances means that the character density and the 588 * overall length of a string of text will be different from the 589 * theoretical design measurements due to the accumulation of 590 * a series of small differences in the adjusted widths of 591 * each glyph. 592 * The specific differences will be different for each glyph, 593 * some being wider and some being narrower than their theoretical 594 * design measurements. 595 * Thus the overall difference in character density and length 596 * will vary by a number of factors including the font, the 597 * specific device resolution being targeted, and the glyphs 598 * chosen to represent the string being rendered. 599 * As a result, rendering the same string at multiple device 600 * resolutions can yield widely varying metrics for whole strings. 601 * <p> 602 * When {@code FRACTIONALMETRICS} are enabled, the true font design 603 * metrics are scaled by the point size and used for layout with 604 * sub-pixel accuracy. 605 * The average density of glyphs and total length of a long 606 * string of characters will therefore more closely match the 607 * theoretical design of the font, but readability may be affected 608 * since individual pairs of characters may not always appear to 609 * be consistent distances apart depending on how the sub-pixel 610 * accumulation of the glyph origins meshes with the device pixel 611 * grid. 612 * Enabling this hint may be desirable when text layout is being 613 * performed that must be consistent across a wide variety of 614 * output resolutions. 615 * Specifically, this hint may be desirable in situations where 616 * the layout of text is being previewed on a low resolution 617 * device like a screen for output that will eventually be 618 * rendered on a high resolution printer or typesetting device. 619 * <p> 620 * When disabled, the scaled design metrics are rounded or adjusted 621 * to integer distances for layout. 622 * The distances between any specific pair of glyphs will be more 623 * uniform on the device, but the density and total length of long 624 * strings may no longer match the theoretical intentions of the 625 * font designer. 626 * Disabling this hint will typically produce more readable results 627 * on low resolution devices like computer monitors. 628 * <p> 629 * The allowable values for this key are 630 * <ul> 631 * <li>{@link #VALUE_FRACTIONALMETRICS_OFF} 632 * <li>{@link #VALUE_FRACTIONALMETRICS_ON} 633 * <li>{@link #VALUE_FRACTIONALMETRICS_DEFAULT} 634 * </ul> 635 */ 636 public static final Key KEY_FRACTIONALMETRICS = 637 SunHints.KEY_FRACTIONALMETRICS; 638 639 /** 640 * Font fractional metrics hint value -- character glyphs are 641 * positioned with advance widths rounded to pixel boundaries. 642 * @see #KEY_FRACTIONALMETRICS 643 */ 644 public static final Object VALUE_FRACTIONALMETRICS_OFF = 645 SunHints.VALUE_FRACTIONALMETRICS_OFF; 646 647 /** 648 * Font fractional metrics hint value -- character glyphs are 649 * positioned with sub-pixel accuracy. 650 * @see #KEY_FRACTIONALMETRICS 651 */ 652 public static final Object VALUE_FRACTIONALMETRICS_ON = 653 SunHints.VALUE_FRACTIONALMETRICS_ON; 654 655 /** 656 * Font fractional metrics hint value -- character glyphs are 657 * positioned with accuracy chosen by the implementation. 658 * @see #KEY_FRACTIONALMETRICS 659 */ 660 public static final Object VALUE_FRACTIONALMETRICS_DEFAULT = 661 SunHints.VALUE_FRACTIONALMETRICS_DEFAULT; 662 663 /** 664 * Interpolation hint key. 665 * The {@code INTERPOLATION} hint controls how image pixels are 666 * filtered or resampled during an image rendering operation. 667 * <p> 668 * Implicitly images are defined to provide color samples at 669 * integer coordinate locations. 670 * When images are rendered upright with no scaling onto a 671 * destination, the choice of which image pixels map to which 672 * device pixels is obvious and the samples at the integer 673 * coordinate locations in the image are transferred to the 674 * pixels at the corresponding integer locations on the device 675 * pixel grid one for one. 676 * When images are rendered in a scaled, rotated, or otherwise 677 * transformed coordinate system, then the mapping of device 678 * pixel coordinates back to the image can raise the question 679 * of what color sample to use for the continuous coordinates 680 * that lie between the integer locations of the provided image 681 * samples. 682 * Interpolation algorithms define functions which provide a 683 * color sample for any continuous coordinate in an image based 684 * on the color samples at the surrounding integer coordinates. 685 * <p> 686 * The allowable values for this hint are 687 * <ul> 688 * <li>{@link #VALUE_INTERPOLATION_NEAREST_NEIGHBOR} 689 * <li>{@link #VALUE_INTERPOLATION_BILINEAR} 690 * <li>{@link #VALUE_INTERPOLATION_BICUBIC} 691 * </ul> 692 */ 693 public static final Key KEY_INTERPOLATION = 694 SunHints.KEY_INTERPOLATION; 695 696 /** 697 * Interpolation hint value -- the color sample of the nearest 698 * neighboring integer coordinate sample in the image is used. 699 * Conceptually the image is viewed as a grid of unit-sized 700 * square regions of color centered around the center of each 701 * image pixel. 702 * <p> 703 * As the image is scaled up, it will look correspondingly blocky. 704 * As the image is scaled down, the colors for source pixels will 705 * be either used unmodified, or skipped entirely in the output 706 * representation. 707 * 708 * @see #KEY_INTERPOLATION 709 */ 710 public static final Object VALUE_INTERPOLATION_NEAREST_NEIGHBOR = 711 SunHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; 712 713 /** 714 * Interpolation hint value -- the color samples of the 4 nearest 715 * neighboring integer coordinate samples in the image are 716 * interpolated linearly to produce a color sample. 717 * Conceptually the image is viewed as a set of infinitely small 718 * point color samples which have value only at the centers of 719 * integer coordinate pixels and the space between those pixel 720 * centers is filled with linear ramps of colors that connect 721 * adjacent discrete samples in a straight line. 722 * <p> 723 * As the image is scaled up, there are no blocky edges between 724 * the colors in the image as there are with 725 * {@link #VALUE_INTERPOLATION_NEAREST_NEIGHBOR NEAREST_NEIGHBOR}, 726 * but the blending may show some subtle discontinuities along the 727 * horizontal and vertical edges that line up with the samples 728 * caused by a sudden change in the slope of the interpolation 729 * from one side of a sample to the other. 730 * As the image is scaled down, more image pixels have their 731 * color samples represented in the resulting output since each 732 * output pixel receives color information from up to 4 image 733 * pixels. 734 * 735 * @see #KEY_INTERPOLATION 736 */ 737 public static final Object VALUE_INTERPOLATION_BILINEAR = 738 SunHints.VALUE_INTERPOLATION_BILINEAR; 739 740 /** 741 * Interpolation hint value -- the color samples of 9 nearby 742 * integer coordinate samples in the image are interpolated using 743 * a cubic function in both {@code X} and {@code Y} to produce 744 * a color sample. 745 * Conceptually the view of the image is very similar to the view 746 * used in the {@link #VALUE_INTERPOLATION_BILINEAR BILINEAR} 747 * algorithm except that the ramps of colors that connect between 748 * the samples are curved and have better continuity of slope 749 * as they cross over between sample boundaries. 750 * <p> 751 * As the image is scaled up, there are no blocky edges and the 752 * interpolation should appear smoother and with better depictions 753 * of any edges in the original image than with {@code BILINEAR}. 754 * As the image is scaled down, even more of the original color 755 * samples from the original image will have their color information 756 * carried through and represented. 757 * 758 * @see #KEY_INTERPOLATION 759 */ 760 public static final Object VALUE_INTERPOLATION_BICUBIC = 761 SunHints.VALUE_INTERPOLATION_BICUBIC; 762 763 /** 764 * Alpha interpolation hint key. 765 * The {@code ALPHA_INTERPOLATION} hint is a general hint that 766 * provides a high level recommendation as to whether to bias 767 * alpha blending algorithm choices more for speed or quality 768 * when evaluating tradeoffs. 769 * <p> 770 * This hint could control the choice of alpha blending 771 * calculations that sacrifice some precision to use fast 772 * lookup tables or lower precision SIMD instructions. 773 * This hint could also control whether or not the color 774 * and alpha values are converted into a linear color space 775 * during the calculations for a more linear visual effect 776 * at the expense of additional per-pixel calculations. 777 * <p> 778 * The allowable values for this hint are 779 * <ul> 780 * <li>{@link #VALUE_ALPHA_INTERPOLATION_SPEED} 781 * <li>{@link #VALUE_ALPHA_INTERPOLATION_QUALITY} 782 * <li>{@link #VALUE_ALPHA_INTERPOLATION_DEFAULT} 783 * </ul> 784 */ 785 public static final Key KEY_ALPHA_INTERPOLATION = 786 SunHints.KEY_ALPHA_INTERPOLATION; 787 788 /** 789 * Alpha interpolation hint value -- alpha blending algorithms 790 * are chosen with a preference for calculation speed. 791 * @see #KEY_ALPHA_INTERPOLATION 792 */ 793 public static final Object VALUE_ALPHA_INTERPOLATION_SPEED = 794 SunHints.VALUE_ALPHA_INTERPOLATION_SPEED; 795 796 /** 797 * Alpha interpolation hint value -- alpha blending algorithms 798 * are chosen with a preference for precision and visual quality. 799 * @see #KEY_ALPHA_INTERPOLATION 800 */ 801 public static final Object VALUE_ALPHA_INTERPOLATION_QUALITY = 802 SunHints.VALUE_ALPHA_INTERPOLATION_QUALITY; 803 804 /** 805 * Alpha interpolation hint value -- alpha blending algorithms 806 * are chosen by the implementation for a good tradeoff of 807 * performance vs. quality. 808 * @see #KEY_ALPHA_INTERPOLATION 809 */ 810 public static final Object VALUE_ALPHA_INTERPOLATION_DEFAULT = 811 SunHints.VALUE_ALPHA_INTERPOLATION_DEFAULT; 812 813 /** 814 * Color rendering hint key. 815 * The {@code COLOR_RENDERING} hint controls the accuracy of 816 * approximation and conversion when storing colors into a 817 * destination image or surface. 818 * <p> 819 * When a rendering or image manipulation operation produces 820 * a color value that must be stored into a destination, it 821 * must first convert that color into a form suitable for 822 * storing into the destination image or surface. 823 * Minimally, the color components must be converted to bit 824 * representations and ordered in the correct order or an 825 * index into a color lookup table must be chosen before 826 * the data can be stored into the destination memory. 827 * Without this minimal conversion, the data in the destination 828 * would likely represent random, incorrect or possibly even 829 * unsupported values. 830 * Algorithms to quickly convert the results of rendering 831 * operations into the color format of most common destinations 832 * are well known and fairly optimal to execute. 833 * <p> 834 * Simply performing the most basic color format conversion to 835 * store colors into a destination can potentially ignore a 836 * difference in the calibration of the 837 * {@link java.awt.color.ColorSpace} 838 * of the source and destination or other factors such as the 839 * linearity of the gamma correction. 840 * Unless the source and destination {@code ColorSpace} are 841 * identical, to correctly perform a rendering operation with 842 * the most care taken for the accuracy of the colors being 843 * represented, the source colors should be converted to a 844 * device independent {@code ColorSpace} and the results then 845 * converted back to the destination {@code ColorSpace}. 846 * Furthermore, if calculations such as the blending of multiple 847 * source colors are to be performed during the rendering 848 * operation, greater visual clarity can be achieved if the 849 * intermediate device independent {@code ColorSpace} is 850 * chosen to have a linear relationship between the values 851 * being calculated and the perception of the human eye to 852 * the response curves of the output device. 853 * <p> 854 * The allowable values for this hint are 855 * <ul> 856 * <li>{@link #VALUE_COLOR_RENDER_SPEED} 857 * <li>{@link #VALUE_COLOR_RENDER_QUALITY} 858 * <li>{@link #VALUE_COLOR_RENDER_DEFAULT} 859 * </ul> 860 */ 861 public static final Key KEY_COLOR_RENDERING = 862 SunHints.KEY_COLOR_RENDERING; 863 864 /** 865 * Color rendering hint value -- perform the fastest color 866 * conversion to the format of the output device. 867 * @see #KEY_COLOR_RENDERING 868 */ 869 public static final Object VALUE_COLOR_RENDER_SPEED = 870 SunHints.VALUE_COLOR_RENDER_SPEED; 871 872 /** 873 * Color rendering hint value -- perform the color conversion 874 * calculations with the highest accuracy and visual quality. 875 * @see #KEY_COLOR_RENDERING 876 */ 877 public static final Object VALUE_COLOR_RENDER_QUALITY = 878 SunHints.VALUE_COLOR_RENDER_QUALITY; 879 880 /** 881 * Color rendering hint value -- perform color conversion 882 * calculations as chosen by the implementation to represent 883 * the best available tradeoff between performance and 884 * accuracy. 885 * @see #KEY_COLOR_RENDERING 886 */ 887 public static final Object VALUE_COLOR_RENDER_DEFAULT = 888 SunHints.VALUE_COLOR_RENDER_DEFAULT; 889 890 /** 891 * Stroke normalization control hint key. 892 * The {@code STROKE_CONTROL} hint controls whether a rendering 893 * implementation should or is allowed to modify the geometry 894 * of rendered shapes for various purposes. 895 * <p> 896 * Some implementations may be able to use an optimized platform 897 * rendering library which may be faster than traditional software 898 * rendering algorithms on a given platform, but which may also 899 * not support floating point coordinates. 900 * Some implementations may also have sophisticated algorithms 901 * which perturb the coordinates of a path so that wide lines 902 * appear more uniform in width and spacing. 903 * <p> 904 * If an implementation performs any type of modification or 905 * "normalization" of a path, it should never move the coordinates 906 * by more than half a pixel in any direction. 907 * <p> 908 * The allowable values for this hint are 909 * <ul> 910 * <li>{@link #VALUE_STROKE_NORMALIZE} 911 * <li>{@link #VALUE_STROKE_PURE} 912 * <li>{@link #VALUE_STROKE_DEFAULT} 913 * </ul> 914 * @since 1.3 915 */ 916 public static final Key KEY_STROKE_CONTROL = 917 SunHints.KEY_STROKE_CONTROL; 918 919 /** 920 * Stroke normalization control hint value -- geometry may be 921 * modified or left pure depending on the tradeoffs in a given 922 * implementation. 923 * Typically this setting allows an implementation to use a fast 924 * integer coordinate based platform rendering library, but does 925 * not specifically request normalization for uniformity or 926 * aesthetics. 927 * 928 * @see #KEY_STROKE_CONTROL 929 * @since 1.3 930 */ 931 public static final Object VALUE_STROKE_DEFAULT = 932 SunHints.VALUE_STROKE_DEFAULT; 933 934 /** 935 * Stroke normalization control hint value -- geometry should 936 * be normalized to improve uniformity or spacing of lines and 937 * overall aesthetics. 938 * Note that different normalization algorithms may be more 939 * successful than others for given input paths. 940 * 941 * @see #KEY_STROKE_CONTROL 942 * @since 1.3 943 */ 944 public static final Object VALUE_STROKE_NORMALIZE = 945 SunHints.VALUE_STROKE_NORMALIZE; 946 947 /** 948 * Stroke normalization control hint value -- geometry should 949 * be left unmodified and rendered with sub-pixel accuracy. 950 * 951 * @see #KEY_STROKE_CONTROL 952 * @since 1.3 953 */ 954 public static final Object VALUE_STROKE_PURE = 955 SunHints.VALUE_STROKE_PURE; 956 957 /** 958 * Image resolution variant hint key. 959 * The {@code RESOLUTION_VARIANT} hint controls which image resolution 960 * variant should be chosen for image drawing. 961 * 962 * <ul> 963 * <li>{@link #VALUE_RESOLUTION_VARIANT_DEFAULT} 964 * <li>{@link #VALUE_RESOLUTION_VARIANT_BASE} 965 * <li>{@link #VALUE_RESOLUTION_VARIANT_SIZE_FIT} 966 * <li>{@link #VALUE_RESOLUTION_VARIANT_DPI_FIT} 967 * </ul> 968 * @since 1.9 969 */ 970 public static final Key KEY_RESOLUTION_VARIANT = 971 SunHints.KEY_RESOLUTION_VARIANT; 972 973 /** 974 * Image resolution variant hint value -- an image resolution variant is 975 * chosen based on a default heuristic which may depend on the policies 976 * of the platform 977 * 978 * @see #KEY_RESOLUTION_VARIANT 979 * @since 1.9 980 */ 981 public static final Object VALUE_RESOLUTION_VARIANT_DEFAULT = 982 SunHints.VALUE_RESOLUTION_VARIANT_DEFAULT; 983 984 /** 985 * Image resolution variant hint value -- the standard resolution of an image 986 * is always used. 987 * 988 * @see #KEY_RESOLUTION_VARIANT 989 * @since 1.9 990 */ 991 public static final Object VALUE_RESOLUTION_VARIANT_BASE = 992 SunHints.VALUE_RESOLUTION_VARIANT_BASE; 993 994 /** 995 * Image resolution variant hint value -- an image resolution variant is 996 * chosen based on the DPI of the screen and the transform in the Graphics2D 997 * context. 998 * 999 * @see #KEY_RESOLUTION_VARIANT 1000 * @since 1.9 1001 */ 1002 public static final Object VALUE_RESOLUTION_VARIANT_SIZE_FIT = 1003 SunHints.VALUE_RESOLUTION_VARIANT_SIZE_FIT; 1004 1005 /** 1006 * Image resolution variant hint value -- an image resolution variant is 1007 * chosen based only on the DPI of the screen. 1008 * 1009 * @see #KEY_RESOLUTION_VARIANT 1010 * @since 1.9 1011 */ 1012 public static final Object VALUE_RESOLUTION_VARIANT_DPI_FIT = 1013 SunHints.VALUE_RESOLUTION_VARIANT_DPI_FIT; 1014 1015 /** 1016 * Constructs a new object with keys and values initialized 1017 * from the specified Map object which may be null. 1018 * @param init a map of key/value pairs to initialize the hints 1019 * or null if the object should be empty 1020 */ 1021 public RenderingHints(Map<Key,?> init) { 1022 if (init != null) { 1023 hintmap.putAll(init); 1024 } 1025 } 1026 1027 /** 1028 * Constructs a new object with the specified key/value pair. 1029 * @param key the key of the particular hint property 1030 * @param value the value of the hint property specified with 1031 * <code>key</code> 1032 */ 1033 public RenderingHints(Key key, Object value) { 1034 hintmap.put(key, value); 1035 } 1036 1037 /** 1038 * Returns the number of key-value mappings in this 1039 * <code>RenderingHints</code>. 1040 * 1041 * @return the number of key-value mappings in this 1042 * <code>RenderingHints</code>. 1043 */ 1044 public int size() { 1045 return hintmap.size(); 1046 } 1047 1048 /** 1049 * Returns <code>true</code> if this 1050 * <code>RenderingHints</code> contains no key-value mappings. 1051 * 1052 * @return <code>true</code> if this 1053 * <code>RenderingHints</code> contains no key-value mappings. 1054 */ 1055 public boolean isEmpty() { 1056 return hintmap.isEmpty(); 1057 } 1058 1059 /** 1060 * Returns {@code true} if this {@code RenderingHints} 1061 * contains a mapping for the specified key. 1062 * 1063 * @param key key whose presence in this 1064 * {@code RenderingHints} is to be tested. 1065 * @return {@code true} if this {@code RenderingHints} 1066 * contains a mapping for the specified key. 1067 * @exception ClassCastException if the key can not 1068 * be cast to {@code RenderingHints.Key} 1069 */ 1070 public boolean containsKey(Object key) { 1071 return hintmap.containsKey((Key) key); 1072 } 1073 1074 /** 1075 * Returns true if this RenderingHints maps one or more keys to the 1076 * specified value. 1077 * More formally, returns <code>true</code> if and only 1078 * if this <code>RenderingHints</code> 1079 * contains at least one mapping to a value <code>v</code> such that 1080 * <pre> 1081 * (value==null ? v==null : value.equals(v)) 1082 * </pre>. 1083 * This operation will probably require time linear in the 1084 * <code>RenderingHints</code> size for most implementations 1085 * of <code>RenderingHints</code>. 1086 * 1087 * @param value value whose presence in this 1088 * <code>RenderingHints</code> is to be tested. 1089 * @return <code>true</code> if this <code>RenderingHints</code> 1090 * maps one or more keys to the specified value. 1091 */ 1092 public boolean containsValue(Object value) { 1093 return hintmap.containsValue(value); 1094 } 1095 1096 /** 1097 * Returns the value to which the specified key is mapped. 1098 * @param key a rendering hint key 1099 * @return the value to which the key is mapped in this object or 1100 * {@code null} if the key is not mapped to any value in 1101 * this object. 1102 * @exception ClassCastException if the key can not 1103 * be cast to {@code RenderingHints.Key} 1104 * @see #put(Object, Object) 1105 */ 1106 public Object get(Object key) { 1107 return hintmap.get((Key) key); 1108 } 1109 1110 /** 1111 * Maps the specified {@code key} to the specified 1112 * {@code value} in this {@code RenderingHints} object. 1113 * Neither the key nor the value can be {@code null}. 1114 * The value can be retrieved by calling the {@code get} method 1115 * with a key that is equal to the original key. 1116 * @param key the rendering hint key. 1117 * @param value the rendering hint value. 1118 * @return the previous value of the specified key in this object 1119 * or {@code null} if it did not have one. 1120 * @exception NullPointerException if the key is 1121 * {@code null}. 1122 * @exception ClassCastException if the key can not 1123 * be cast to {@code RenderingHints.Key} 1124 * @exception IllegalArgumentException if the 1125 * {@link Key#isCompatibleValue(java.lang.Object) 1126 * Key.isCompatibleValue()} 1127 * method of the specified key returns false for the 1128 * specified value 1129 * @see #get(Object) 1130 */ 1131 public Object put(Object key, Object value) { 1132 if (!((Key) key).isCompatibleValue(value)) { 1133 throw new IllegalArgumentException(value+ 1134 " incompatible with "+ 1135 key); 1136 } 1137 return hintmap.put((Key) key, value); 1138 } 1139 1140 /** 1141 * Adds all of the keys and corresponding values from the specified 1142 * <code>RenderingHints</code> object to this 1143 * <code>RenderingHints</code> object. Keys that are present in 1144 * this <code>RenderingHints</code> object, but not in the specified 1145 * <code>RenderingHints</code> object are not affected. 1146 * @param hints the set of key/value pairs to be added to this 1147 * <code>RenderingHints</code> object 1148 */ 1149 public void add(RenderingHints hints) { 1150 hintmap.putAll(hints.hintmap); 1151 } 1152 1153 /** 1154 * Clears this <code>RenderingHints</code> object of all key/value 1155 * pairs. 1156 */ 1157 public void clear() { 1158 hintmap.clear(); 1159 } 1160 1161 /** 1162 * Removes the key and its corresponding value from this 1163 * {@code RenderingHints} object. This method does nothing if the 1164 * key is not in this {@code RenderingHints} object. 1165 * @param key the rendering hints key that needs to be removed 1166 * @exception ClassCastException if the key can not 1167 * be cast to {@code RenderingHints.Key} 1168 * @return the value to which the key had previously been mapped in this 1169 * {@code RenderingHints} object, or {@code null} 1170 * if the key did not have a mapping. 1171 */ 1172 public Object remove(Object key) { 1173 return hintmap.remove((Key) key); 1174 } 1175 1176 /** 1177 * Copies all of the mappings from the specified {@code Map} 1178 * to this {@code RenderingHints}. These mappings replace 1179 * any mappings that this {@code RenderingHints} had for any 1180 * of the keys currently in the specified {@code Map}. 1181 * @param m the specified {@code Map} 1182 * @exception ClassCastException class of a key or value 1183 * in the specified {@code Map} prevents it from being 1184 * stored in this {@code RenderingHints}. 1185 * @exception IllegalArgumentException some aspect 1186 * of a key or value in the specified {@code Map} 1187 * prevents it from being stored in 1188 * this {@code RenderingHints}. 1189 */ 1190 public void putAll(Map<?,?> m) { 1191 // ## javac bug? 1192 //if (m instanceof RenderingHints) { 1193 if (RenderingHints.class.isInstance(m)) { 1194 //hintmap.putAll(((RenderingHints) m).hintmap); 1195 for (Map.Entry<?,?> entry : m.entrySet()) 1196 hintmap.put(entry.getKey(), entry.getValue()); 1197 } else { 1198 // Funnel each key/value pair through our protected put method 1199 for (Map.Entry<?,?> entry : m.entrySet()) 1200 put(entry.getKey(), entry.getValue()); 1201 } 1202 } 1203 1204 /** 1205 * Returns a <code>Set</code> view of the Keys contained in this 1206 * <code>RenderingHints</code>. The Set is backed by the 1207 * <code>RenderingHints</code>, so changes to the 1208 * <code>RenderingHints</code> are reflected in the <code>Set</code>, 1209 * and vice-versa. If the <code>RenderingHints</code> is modified 1210 * while an iteration over the <code>Set</code> is in progress, 1211 * the results of the iteration are undefined. The <code>Set</code> 1212 * supports element removal, which removes the corresponding 1213 * mapping from the <code>RenderingHints</code>, via the 1214 * <code>Iterator.remove</code>, <code>Set.remove</code>, 1215 * <code>removeAll</code> <code>retainAll</code>, and 1216 * <code>clear</code> operations. It does not support 1217 * the <code>add</code> or <code>addAll</code> operations. 1218 * 1219 * @return a <code>Set</code> view of the keys contained 1220 * in this <code>RenderingHints</code>. 1221 */ 1222 public Set<Object> keySet() { 1223 return hintmap.keySet(); 1224 } 1225 1226 /** 1227 * Returns a <code>Collection</code> view of the values 1228 * contained in this <code>RenderingHints</code>. 1229 * The <code>Collection</code> is backed by the 1230 * <code>RenderingHints</code>, so changes to 1231 * the <code>RenderingHints</code> are reflected in 1232 * the <code>Collection</code>, and vice-versa. 1233 * If the <code>RenderingHints</code> is modified while 1234 * an iteration over the <code>Collection</code> is 1235 * in progress, the results of the iteration are undefined. 1236 * The <code>Collection</code> supports element removal, 1237 * which removes the corresponding mapping from the 1238 * <code>RenderingHints</code>, via the 1239 * <code>Iterator.remove</code>, 1240 * <code>Collection.remove</code>, <code>removeAll</code>, 1241 * <code>retainAll</code> and <code>clear</code> operations. 1242 * It does not support the <code>add</code> or 1243 * <code>addAll</code> operations. 1244 * 1245 * @return a <code>Collection</code> view of the values 1246 * contained in this <code>RenderingHints</code>. 1247 */ 1248 public Collection<Object> values() { 1249 return hintmap.values(); 1250 } 1251 1252 /** 1253 * Returns a <code>Set</code> view of the mappings contained 1254 * in this <code>RenderingHints</code>. Each element in the 1255 * returned <code>Set</code> is a <code>Map.Entry</code>. 1256 * The <code>Set</code> is backed by the <code>RenderingHints</code>, 1257 * so changes to the <code>RenderingHints</code> are reflected 1258 * in the <code>Set</code>, and vice-versa. If the 1259 * <code>RenderingHints</code> is modified while 1260 * while an iteration over the <code>Set</code> is in progress, 1261 * the results of the iteration are undefined. 1262 * <p> 1263 * The entrySet returned from a <code>RenderingHints</code> object 1264 * is not modifiable. 1265 * 1266 * @return a <code>Set</code> view of the mappings contained in 1267 * this <code>RenderingHints</code>. 1268 */ 1269 public Set<Map.Entry<Object,Object>> entrySet() { 1270 return Collections.unmodifiableMap(hintmap).entrySet(); 1271 } 1272 1273 /** 1274 * Compares the specified <code>Object</code> with this 1275 * <code>RenderingHints</code> for equality. 1276 * Returns <code>true</code> if the specified object is also a 1277 * <code>Map</code> and the two <code>Map</code> objects represent 1278 * the same mappings. More formally, two <code>Map</code> objects 1279 * <code>t1</code> and <code>t2</code> represent the same mappings 1280 * if <code>t1.keySet().equals(t2.keySet())</code> and for every 1281 * key <code>k</code> in <code>t1.keySet()</code>, 1282 * <pre> 1283 * (t1.get(k)==null ? t2.get(k)==null : t1.get(k).equals(t2.get(k))) 1284 * </pre>. 1285 * This ensures that the <code>equals</code> method works properly across 1286 * different implementations of the <code>Map</code> interface. 1287 * 1288 * @param o <code>Object</code> to be compared for equality with 1289 * this <code>RenderingHints</code>. 1290 * @return <code>true</code> if the specified <code>Object</code> 1291 * is equal to this <code>RenderingHints</code>. 1292 */ 1293 public boolean equals(Object o) { 1294 if (o instanceof RenderingHints) { 1295 return hintmap.equals(((RenderingHints) o).hintmap); 1296 } else if (o instanceof Map) { 1297 return hintmap.equals(o); 1298 } 1299 return false; 1300 } 1301 1302 /** 1303 * Returns the hash code value for this <code>RenderingHints</code>. 1304 * The hash code of a <code>RenderingHints</code> is defined to be 1305 * the sum of the hashCodes of each <code>Entry</code> in the 1306 * <code>RenderingHints</code> object's entrySet view. This ensures that 1307 * <code>t1.equals(t2)</code> implies that 1308 * <code>t1.hashCode()==t2.hashCode()</code> for any two <code>Map</code> 1309 * objects <code>t1</code> and <code>t2</code>, as required by the general 1310 * contract of <code>Object.hashCode</code>. 1311 * 1312 * @return the hash code value for this <code>RenderingHints</code>. 1313 * @see java.util.Map.Entry#hashCode() 1314 * @see Object#hashCode() 1315 * @see Object#equals(Object) 1316 * @see #equals(Object) 1317 */ 1318 public int hashCode() { 1319 return hintmap.hashCode(); 1320 } 1321 1322 /** 1323 * Creates a clone of this <code>RenderingHints</code> object 1324 * that has the same contents as this <code>RenderingHints</code> 1325 * object. 1326 * @return a clone of this instance. 1327 */ 1328 @SuppressWarnings("unchecked") 1329 public Object clone() { 1330 RenderingHints rh; 1331 try { 1332 rh = (RenderingHints) super.clone(); 1333 if (hintmap != null) { 1334 rh.hintmap = (HashMap<Object,Object>) hintmap.clone(); 1335 } 1336 } catch (CloneNotSupportedException e) { 1337 // this shouldn't happen, since we are Cloneable 1338 throw new InternalError(e); 1339 } 1340 1341 return rh; 1342 } 1343 1344 /** 1345 * Returns a rather long string representation of the hashmap 1346 * which contains the mappings of keys to values for this 1347 * <code>RenderingHints</code> object. 1348 * @return a string representation of this object. 1349 */ 1350 public String toString() { 1351 if (hintmap == null) { 1352 return getClass().getName() + "@" + 1353 Integer.toHexString(hashCode()) + 1354 " (0 hints)"; 1355 } 1356 1357 return hintmap.toString(); 1358 } 1359 }