001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2020, by Object Refinery Limited and Contributors. 006 * 007 * Project Info: http://www.jfree.org/jfreechart/index.html 008 * 009 * This library is free software; you can redistribute it and/or modify it 010 * under the terms of the GNU Lesser General Public License as published by 011 * the Free Software Foundation; either version 2.1 of the License, or 012 * (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but 015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 017 * License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this library; if not, write to the Free Software 021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 022 * USA. 023 * 024 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 025 * Other names may be trademarks of their respective owners.] 026 * 027 * --------------- 028 * ChartUtils.java 029 * --------------- 030 * (C) Copyright 2001-2020, by Object Refinery Limited and Contributors. 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): Wolfgang Irler; 034 * Richard Atkinson; 035 * Xavier Poinsard; 036 * 037 */ 038 039package org.jfree.chart; 040 041import java.awt.Graphics2D; 042import java.awt.geom.AffineTransform; 043import java.awt.geom.Rectangle2D; 044import java.awt.image.BufferedImage; 045import java.io.BufferedOutputStream; 046import java.io.File; 047import java.io.FileOutputStream; 048import java.io.IOException; 049import java.io.OutputStream; 050import java.io.PrintWriter; 051 052import org.jfree.chart.encoders.EncoderUtil; 053import org.jfree.chart.encoders.ImageFormat; 054import org.jfree.chart.imagemap.ImageMapUtils; 055import org.jfree.chart.imagemap.OverLIBToolTipTagFragmentGenerator; 056import org.jfree.chart.imagemap.StandardToolTipTagFragmentGenerator; 057import org.jfree.chart.imagemap.StandardURLTagFragmentGenerator; 058import org.jfree.chart.imagemap.ToolTipTagFragmentGenerator; 059import org.jfree.chart.imagemap.URLTagFragmentGenerator; 060import org.jfree.chart.util.Args; 061 062/** 063 * A collection of utility methods for JFreeChart. Includes methods for 064 * converting charts to image formats (PNG and JPEG) plus creating simple HTML 065 * image maps. 066 * 067 * @see ImageMapUtils 068 */ 069public abstract class ChartUtils { 070 071 /** 072 * Applies the current theme to the specified chart. This method is 073 * provided for convenience, the theme itself is stored in the 074 * {@link ChartFactory} class. 075 * 076 * @param chart the chart ({@code null} not permitted). 077 * 078 * @since 1.0.11 079 */ 080 public static void applyCurrentTheme(JFreeChart chart) { 081 ChartFactory.getChartTheme().apply(chart); 082 } 083 084 /** 085 * Writes a chart to an output stream in PNG format. 086 * 087 * @param out the output stream ({@code null} not permitted). 088 * @param chart the chart ({@code null} not permitted). 089 * @param width the image width. 090 * @param height the image height. 091 * 092 * @throws IOException if there are any I/O errors. 093 */ 094 public static void writeChartAsPNG(OutputStream out, JFreeChart chart, 095 int width, int height) throws IOException { 096 097 // defer argument checking... 098 writeChartAsPNG(out, chart, width, height, null); 099 100 } 101 102 /** 103 * Writes a chart to an output stream in PNG format. 104 * 105 * @param out the output stream ({@code null} not permitted). 106 * @param chart the chart ({@code null} not permitted). 107 * @param width the image width. 108 * @param height the image height. 109 * @param encodeAlpha encode alpha? 110 * @param compression the compression level (0-9). 111 * 112 * @throws IOException if there are any I/O errors. 113 */ 114 public static void writeChartAsPNG(OutputStream out, JFreeChart chart, 115 int width, int height, boolean encodeAlpha, int compression) 116 throws IOException { 117 118 // defer argument checking... 119 ChartUtils.writeChartAsPNG(out, chart, width, height, null, 120 encodeAlpha, compression); 121 122 } 123 124 /** 125 * Writes a chart to an output stream in PNG format. This method allows 126 * you to pass in a {@link ChartRenderingInfo} object, to collect 127 * information about the chart dimensions/entities. You will need this 128 * info if you want to create an HTML image map. 129 * 130 * @param out the output stream ({@code null} not permitted). 131 * @param chart the chart ({@code null} not permitted). 132 * @param width the image width. 133 * @param height the image height. 134 * @param info the chart rendering info ({@code null} permitted). 135 * 136 * @throws IOException if there are any I/O errors. 137 */ 138 public static void writeChartAsPNG(OutputStream out, JFreeChart chart, 139 int width, int height, ChartRenderingInfo info) 140 throws IOException { 141 142 Args.nullNotPermitted(chart, "chart"); 143 BufferedImage bufferedImage 144 = chart.createBufferedImage(width, height, info); 145 EncoderUtil.writeBufferedImage(bufferedImage, ImageFormat.PNG, out); 146 } 147 148 /** 149 * Writes a chart to an output stream in PNG format. This method allows 150 * you to pass in a {@link ChartRenderingInfo} object, to collect 151 * information about the chart dimensions/entities. You will need this 152 * info if you want to create an HTML image map. 153 * 154 * @param out the output stream ({@code null} not permitted). 155 * @param chart the chart ({@code null} not permitted). 156 * @param width the image width. 157 * @param height the image height. 158 * @param info carries back chart rendering info ({@code null} 159 * permitted). 160 * @param encodeAlpha encode alpha? 161 * @param compression the PNG compression level (0-9). 162 * 163 * @throws IOException if there are any I/O errors. 164 */ 165 public static void writeChartAsPNG(OutputStream out, JFreeChart chart, 166 int width, int height, ChartRenderingInfo info, 167 boolean encodeAlpha, int compression) throws IOException { 168 169 Args.nullNotPermitted(out, "out"); 170 Args.nullNotPermitted(chart, "chart"); 171 BufferedImage chartImage = chart.createBufferedImage(width, height, 172 BufferedImage.TYPE_INT_ARGB, info); 173 ChartUtils.writeBufferedImageAsPNG(out, chartImage, encodeAlpha, 174 compression); 175 176 } 177 178 /** 179 * Writes a scaled version of a chart to an output stream in PNG format. 180 * 181 * @param out the output stream ({@code null} not permitted). 182 * @param chart the chart ({@code null} not permitted). 183 * @param width the unscaled chart width. 184 * @param height the unscaled chart height. 185 * @param widthScaleFactor the horizontal scale factor. 186 * @param heightScaleFactor the vertical scale factor. 187 * 188 * @throws IOException if there are any I/O problems. 189 */ 190 public static void writeScaledChartAsPNG(OutputStream out, 191 JFreeChart chart, int width, int height, int widthScaleFactor, 192 int heightScaleFactor) throws IOException { 193 194 Args.nullNotPermitted(out, "out"); 195 Args.nullNotPermitted(chart, "chart"); 196 197 double desiredWidth = width * widthScaleFactor; 198 double desiredHeight = height * heightScaleFactor; 199 double defaultWidth = width; 200 double defaultHeight = height; 201 boolean scale = false; 202 203 // get desired width and height from somewhere then... 204 if ((widthScaleFactor != 1) || (heightScaleFactor != 1)) { 205 scale = true; 206 } 207 208 double scaleX = desiredWidth / defaultWidth; 209 double scaleY = desiredHeight / defaultHeight; 210 211 BufferedImage image = new BufferedImage((int) desiredWidth, 212 (int) desiredHeight, BufferedImage.TYPE_INT_ARGB); 213 Graphics2D g2 = image.createGraphics(); 214 215 if (scale) { 216 AffineTransform saved = g2.getTransform(); 217 g2.transform(AffineTransform.getScaleInstance(scaleX, scaleY)); 218 chart.draw(g2, new Rectangle2D.Double(0, 0, defaultWidth, 219 defaultHeight), null, null); 220 g2.setTransform(saved); 221 g2.dispose(); 222 } 223 else { 224 chart.draw(g2, new Rectangle2D.Double(0, 0, defaultWidth, 225 defaultHeight), null, null); 226 } 227 out.write(encodeAsPNG(image)); 228 229 } 230 231 /** 232 * Saves a chart to the specified file in PNG format. 233 * 234 * @param file the file name ({@code null} not permitted). 235 * @param chart the chart ({@code null} not permitted). 236 * @param width the image width. 237 * @param height the image height. 238 * 239 * @throws IOException if there are any I/O errors. 240 */ 241 public static void saveChartAsPNG(File file, JFreeChart chart, 242 int width, int height) throws IOException { 243 244 // defer argument checking... 245 saveChartAsPNG(file, chart, width, height, null); 246 247 } 248 249 /** 250 * Saves a chart to a file in PNG format. This method allows you to pass 251 * in a {@link ChartRenderingInfo} object, to collect information about the 252 * chart dimensions/entities. You will need this info if you want to 253 * create an HTML image map. 254 * 255 * @param file the file ({@code null} not permitted). 256 * @param chart the chart ({@code null} not permitted). 257 * @param width the image width. 258 * @param height the image height. 259 * @param info the chart rendering info ({@code null} permitted). 260 * 261 * @throws IOException if there are any I/O errors. 262 */ 263 public static void saveChartAsPNG(File file, JFreeChart chart, 264 int width, int height, ChartRenderingInfo info) 265 throws IOException { 266 267 Args.nullNotPermitted(file, "file"); 268 OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); 269 try { 270 ChartUtils.writeChartAsPNG(out, chart, width, height, info); 271 } 272 finally { 273 out.close(); 274 } 275 } 276 277 /** 278 * Saves a chart to a file in PNG format. This method allows you to pass 279 * in a {@link ChartRenderingInfo} object, to collect information about the 280 * chart dimensions/entities. You will need this info if you want to 281 * create an HTML image map. 282 * 283 * @param file the file ({@code null} not permitted). 284 * @param chart the chart ({@code null} not permitted). 285 * @param width the image width. 286 * @param height the image height. 287 * @param info the chart rendering info ({@code null} permitted). 288 * @param encodeAlpha encode alpha? 289 * @param compression the PNG compression level (0-9). 290 * 291 * @throws IOException if there are any I/O errors. 292 */ 293 public static void saveChartAsPNG(File file, JFreeChart chart, 294 int width, int height, ChartRenderingInfo info, boolean encodeAlpha, 295 int compression) throws IOException { 296 297 Args.nullNotPermitted(file, "file"); 298 Args.nullNotPermitted(chart, "chart"); 299 OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); 300 try { 301 writeChartAsPNG(out, chart, width, height, info, encodeAlpha, 302 compression); 303 } 304 finally { 305 out.close(); 306 } 307 308 } 309 310 /** 311 * Writes a chart to an output stream in JPEG format. Please note that 312 * JPEG is a poor format for chart images, use PNG if possible. 313 * 314 * @param out the output stream ({@code null} not permitted). 315 * @param chart the chart ({@code null} not permitted). 316 * @param width the image width. 317 * @param height the image height. 318 * 319 * @throws IOException if there are any I/O errors. 320 */ 321 public static void writeChartAsJPEG(OutputStream out, 322 JFreeChart chart, int width, int height) throws IOException { 323 324 // defer argument checking... 325 writeChartAsJPEG(out, chart, width, height, null); 326 327 } 328 329 /** 330 * Writes a chart to an output stream in JPEG format. Please note that 331 * JPEG is a poor format for chart images, use PNG if possible. 332 * 333 * @param out the output stream ({@code null} not permitted). 334 * @param quality the quality setting. 335 * @param chart the chart ({@code null} not permitted). 336 * @param width the image width. 337 * @param height the image height. 338 * 339 * @throws IOException if there are any I/O errors. 340 */ 341 public static void writeChartAsJPEG(OutputStream out, float quality, 342 JFreeChart chart, int width, int height) throws IOException { 343 344 // defer argument checking... 345 ChartUtils.writeChartAsJPEG(out, quality, chart, width, height, 346 null); 347 348 } 349 350 /** 351 * Writes a chart to an output stream in JPEG format. This method allows 352 * you to pass in a {@link ChartRenderingInfo} object, to collect 353 * information about the chart dimensions/entities. You will need this 354 * info if you want to create an HTML image map. 355 * 356 * @param out the output stream ({@code null} not permitted). 357 * @param chart the chart ({@code null} not permitted). 358 * @param width the image width. 359 * @param height the image height. 360 * @param info the chart rendering info ({@code null} permitted). 361 * 362 * @throws IOException if there are any I/O errors. 363 */ 364 public static void writeChartAsJPEG(OutputStream out, JFreeChart chart, 365 int width, int height, ChartRenderingInfo info) 366 throws IOException { 367 368 Args.nullNotPermitted(out, "out"); 369 Args.nullNotPermitted(chart, "chart"); 370 BufferedImage image = chart.createBufferedImage(width, height, 371 BufferedImage.TYPE_INT_RGB, info); 372 EncoderUtil.writeBufferedImage(image, ImageFormat.JPEG, out); 373 374 } 375 376 /** 377 * Writes a chart to an output stream in JPEG format. This method allows 378 * you to pass in a {@link ChartRenderingInfo} object, to collect 379 * information about the chart dimensions/entities. You will need this 380 * info if you want to create an HTML image map. 381 * 382 * @param out the output stream ({@code null} not permitted). 383 * @param quality the output quality (0.0f to 1.0f). 384 * @param chart the chart ({@code null} not permitted). 385 * @param width the image width. 386 * @param height the image height. 387 * @param info the chart rendering info ({@code null} permitted). 388 * 389 * @throws IOException if there are any I/O errors. 390 */ 391 public static void writeChartAsJPEG(OutputStream out, float quality, 392 JFreeChart chart, int width, int height, ChartRenderingInfo info) 393 throws IOException { 394 395 Args.nullNotPermitted(out, "out"); 396 Args.nullNotPermitted(chart, "chart"); 397 BufferedImage image = chart.createBufferedImage(width, height, 398 BufferedImage.TYPE_INT_RGB, info); 399 EncoderUtil.writeBufferedImage(image, ImageFormat.JPEG, out, quality); 400 401 } 402 403 /** 404 * Saves a chart to a file in JPEG format. 405 * 406 * @param file the file ({@code null} not permitted). 407 * @param chart the chart ({@code null} not permitted). 408 * @param width the image width. 409 * @param height the image height. 410 * 411 * @throws IOException if there are any I/O errors. 412 */ 413 public static void saveChartAsJPEG(File file, JFreeChart chart, 414 int width, int height) throws IOException { 415 416 // defer argument checking... 417 saveChartAsJPEG(file, chart, width, height, null); 418 419 } 420 421 /** 422 * Saves a chart to a file in JPEG format. 423 * 424 * @param file the file ({@code null} not permitted). 425 * @param quality the JPEG quality setting. 426 * @param chart the chart ({@code null} not permitted). 427 * @param width the image width. 428 * @param height the image height. 429 * 430 * @throws IOException if there are any I/O errors. 431 */ 432 public static void saveChartAsJPEG(File file, float quality, 433 JFreeChart chart, int width, int height) throws IOException { 434 435 // defer argument checking... 436 saveChartAsJPEG(file, quality, chart, width, height, null); 437 438 } 439 440 /** 441 * Saves a chart to a file in JPEG format. This method allows you to pass 442 * in a {@link ChartRenderingInfo} object, to collect information about the 443 * chart dimensions/entities. You will need this info if you want to 444 * create an HTML image map. 445 * 446 * @param file the file name ({@code null} not permitted). 447 * @param chart the chart ({@code null} not permitted). 448 * @param width the image width. 449 * @param height the image height. 450 * @param info the chart rendering info ({@code null} permitted). 451 * 452 * @throws IOException if there are any I/O errors. 453 */ 454 public static void saveChartAsJPEG(File file, JFreeChart chart, 455 int width, int height, ChartRenderingInfo info) throws IOException { 456 457 Args.nullNotPermitted(file, "file"); 458 Args.nullNotPermitted(chart, "chart"); 459 OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); 460 try { 461 writeChartAsJPEG(out, chart, width, height, info); 462 } 463 finally { 464 out.close(); 465 } 466 467 } 468 469 /** 470 * Saves a chart to a file in JPEG format. This method allows you to pass 471 * in a {@link ChartRenderingInfo} object, to collect information about the 472 * chart dimensions/entities. You will need this info if you want to 473 * create an HTML image map. 474 * 475 * @param file the file name ({@code null} not permitted). 476 * @param quality the quality setting. 477 * @param chart the chart ({@code null} not permitted). 478 * @param width the image width. 479 * @param height the image height. 480 * @param info the chart rendering info ({@code null} permitted). 481 * 482 * @throws IOException if there are any I/O errors. 483 */ 484 public static void saveChartAsJPEG(File file, float quality, 485 JFreeChart chart, int width, int height, 486 ChartRenderingInfo info) throws IOException { 487 488 Args.nullNotPermitted(file, "file"); 489 Args.nullNotPermitted(chart, "chart"); 490 OutputStream out = new BufferedOutputStream(new FileOutputStream( 491 file)); 492 try { 493 writeChartAsJPEG(out, quality, chart, width, height, info); 494 } 495 finally { 496 out.close(); 497 } 498 499 } 500 501 /** 502 * Writes a {@link BufferedImage} to an output stream in JPEG format. 503 * 504 * @param out the output stream ({@code null} not permitted). 505 * @param image the image ({@code null} not permitted). 506 * 507 * @throws IOException if there are any I/O errors. 508 */ 509 public static void writeBufferedImageAsJPEG(OutputStream out, 510 BufferedImage image) throws IOException { 511 512 // defer argument checking... 513 writeBufferedImageAsJPEG(out, 0.75f, image); 514 515 } 516 517 /** 518 * Writes a {@link BufferedImage} to an output stream in JPEG format. 519 * 520 * @param out the output stream ({@code null} not permitted). 521 * @param quality the image quality (0.0f to 1.0f). 522 * @param image the image ({@code null} not permitted). 523 * 524 * @throws IOException if there are any I/O errors. 525 */ 526 public static void writeBufferedImageAsJPEG(OutputStream out, float quality, 527 BufferedImage image) throws IOException { 528 529 EncoderUtil.writeBufferedImage(image, ImageFormat.JPEG, out, quality); 530 531 } 532 533 /** 534 * Writes a {@link BufferedImage} to an output stream in PNG format. 535 * 536 * @param out the output stream ({@code null} not permitted). 537 * @param image the image ({@code null} not permitted). 538 * 539 * @throws IOException if there are any I/O errors. 540 */ 541 public static void writeBufferedImageAsPNG(OutputStream out, 542 BufferedImage image) throws IOException { 543 544 EncoderUtil.writeBufferedImage(image, ImageFormat.PNG, out); 545 546 } 547 548 /** 549 * Writes a {@link BufferedImage} to an output stream in PNG format. 550 * 551 * @param out the output stream ({@code null} not permitted). 552 * @param image the image ({@code null} not permitted). 553 * @param encodeAlpha encode alpha? 554 * @param compression the compression level (0-9). 555 * 556 * @throws IOException if there are any I/O errors. 557 */ 558 public static void writeBufferedImageAsPNG(OutputStream out, 559 BufferedImage image, boolean encodeAlpha, int compression) 560 throws IOException { 561 562 EncoderUtil.writeBufferedImage(image, ImageFormat.PNG, out, 563 compression, encodeAlpha); 564 } 565 566 /** 567 * Encodes a {@link BufferedImage} to PNG format. 568 * 569 * @param image the image ({@code null} not permitted). 570 * 571 * @return A byte array in PNG format. 572 * 573 * @throws IOException if there is an I/O problem. 574 */ 575 public static byte[] encodeAsPNG(BufferedImage image) throws IOException { 576 return EncoderUtil.encode(image, ImageFormat.PNG); 577 } 578 579 /** 580 * Encodes a {@link BufferedImage} to PNG format. 581 * 582 * @param image the image ({@code null} not permitted). 583 * @param encodeAlpha encode alpha? 584 * @param compression the PNG compression level (0-9). 585 * 586 * @return The byte array in PNG format. 587 * 588 * @throws IOException if there is an I/O problem. 589 */ 590 public static byte[] encodeAsPNG(BufferedImage image, boolean encodeAlpha, 591 int compression) throws IOException { 592 return EncoderUtil.encode(image, ImageFormat.PNG, compression, 593 encodeAlpha); 594 } 595 596 /** 597 * Writes an image map to an output stream. 598 * 599 * @param writer the writer ({@code null} not permitted). 600 * @param name the map name ({@code null} not permitted). 601 * @param info the chart rendering info ({@code null} not permitted). 602 * @param useOverLibForToolTips whether to use OverLIB for tooltips 603 * (http://www.bosrup.com/web/overlib/). 604 * 605 * @throws IOException if there are any I/O errors. 606 */ 607 public static void writeImageMap(PrintWriter writer, String name, 608 ChartRenderingInfo info, boolean useOverLibForToolTips) 609 throws IOException { 610 611 ToolTipTagFragmentGenerator toolTipTagFragmentGenerator; 612 if (useOverLibForToolTips) { 613 toolTipTagFragmentGenerator 614 = new OverLIBToolTipTagFragmentGenerator(); 615 } 616 else { 617 toolTipTagFragmentGenerator 618 = new StandardToolTipTagFragmentGenerator(); 619 } 620 ImageMapUtils.writeImageMap(writer, name, info, 621 toolTipTagFragmentGenerator, 622 new StandardURLTagFragmentGenerator()); 623 624 } 625 626 /** 627 * Writes an image map to the specified writer. 628 * 629 * @param writer the writer ({@code null} not permitted). 630 * @param name the map name ({@code null} not permitted). 631 * @param info the chart rendering info ({@code null} not permitted). 632 * @param toolTipTagFragmentGenerator a generator for the HTML fragment 633 * that will contain the tooltip text ({@code null} not permitted 634 * if {@code info} contains tooltip information). 635 * @param urlTagFragmentGenerator a generator for the HTML fragment that 636 * will contain the URL reference ({@code null} not permitted if 637 * {@code info} contains URLs). 638 * 639 * @throws IOException if there are any I/O errors. 640 */ 641 public static void writeImageMap(PrintWriter writer, String name, 642 ChartRenderingInfo info, 643 ToolTipTagFragmentGenerator toolTipTagFragmentGenerator, 644 URLTagFragmentGenerator urlTagFragmentGenerator) 645 throws IOException { 646 647 writer.println(ImageMapUtils.getImageMap(name, info, 648 toolTipTagFragmentGenerator, urlTagFragmentGenerator)); 649 } 650 651 /** 652 * Creates an HTML image map. This method maps to 653 * {@link ImageMapUtils#getImageMap(String, ChartRenderingInfo, 654 * ToolTipTagFragmentGenerator, URLTagFragmentGenerator)}, using default 655 * generators. 656 * 657 * @param name the map name ({@code null} not permitted). 658 * @param info the chart rendering info ({@code null} not permitted). 659 * 660 * @return The map tag. 661 */ 662 public static String getImageMap(String name, ChartRenderingInfo info) { 663 return ImageMapUtils.getImageMap(name, info, 664 new StandardToolTipTagFragmentGenerator(), 665 new StandardURLTagFragmentGenerator()); 666 } 667 668 /** 669 * Creates an HTML image map. This method maps directly to 670 * {@link ImageMapUtils#getImageMap(String, ChartRenderingInfo, 671 * ToolTipTagFragmentGenerator, URLTagFragmentGenerator)}. 672 * 673 * @param name the map name ({@code null} not permitted). 674 * @param info the chart rendering info ({@code null} not permitted). 675 * @param toolTipTagFragmentGenerator a generator for the HTML fragment 676 * that will contain the tooltip text ({@code null} not permitted 677 * if {@code info} contains tooltip information). 678 * @param urlTagFragmentGenerator a generator for the HTML fragment that 679 * will contain the URL reference ({@code null} not permitted if 680 * {@code info} contains URLs). 681 * 682 * @return The map tag. 683 */ 684 public static String getImageMap(String name, ChartRenderingInfo info, 685 ToolTipTagFragmentGenerator toolTipTagFragmentGenerator, 686 URLTagFragmentGenerator urlTagFragmentGenerator) { 687 688 return ImageMapUtils.getImageMap(name, info, 689 toolTipTagFragmentGenerator, urlTagFragmentGenerator); 690 691 } 692 693}