1 19 20 package org.netbeans.editor; 21 22 import java.awt.Color ; 23 import java.awt.Font ; 24 import java.util.Enumeration ; 25 import java.util.HashMap ; 26 import java.util.WeakHashMap ; 27 import javax.swing.JComponent ; 28 import javax.swing.text.AttributeSet ; 29 import javax.swing.text.StyleConstants ; 30 31 59 60 public final class Coloring implements java.io.Serializable { 61 62 68 public static final int FONT_MODE_APPLY_NAME = 1; 69 70 76 public static final int FONT_MODE_APPLY_STYLE = 2; 77 78 84 public static final int FONT_MODE_APPLY_SIZE = 4; 85 86 90 public static final int FONT_MODE_DEFAULT 91 = FONT_MODE_APPLY_NAME | FONT_MODE_APPLY_STYLE | FONT_MODE_APPLY_SIZE; 92 93 94 private Font font; 95 96 97 private int fontMode; 98 99 100 private Color foreColor; 101 102 103 private Color backColor; 104 105 106 private Color underlineColor; 107 108 109 private Color waveUnderlineColor; 110 111 112 private Color strikeThroughColor; 113 114 121 private transient HashMap fontAndForeColorCache; 122 123 124 private transient HashMap backColorCache; 125 126 static final long serialVersionUID =-1382649127124476675L; 127 128 129 public Coloring() { 130 this(null, null, null); 131 } 132 133 134 public Coloring(Font font, Color foreColor, Color backColor) { 135 this(font, FONT_MODE_DEFAULT, foreColor, backColor, null, null); 136 } 137 138 139 public Coloring(Font font, int fontMode, Color foreColor, Color backColor) { 140 this(font, fontMode, foreColor, backColor, null, null); 141 } 142 143 public Coloring(Font font, int fontMode, Color foreColor, 144 Color backColor, Color underlineColor, Color strikeThroughColor) { 145 this(font, fontMode, foreColor, backColor, underlineColor, strikeThroughColor, null); 146 } 147 148 149 public Coloring(Font font, int fontMode, Color foreColor, 150 Color backColor, Color underlineColor, Color strikeThroughColor, Color waveUnderlineColor) { 151 font = (fontMode != 0) ? font : null; 152 fontMode = (font != null) ? fontMode : FONT_MODE_DEFAULT; 153 154 this.font = font; 155 this.fontMode = fontMode; 156 157 this.foreColor = foreColor; 158 this.backColor = backColor; 159 160 this.underlineColor = underlineColor; 161 this.strikeThroughColor = strikeThroughColor; 162 this.waveUnderlineColor = waveUnderlineColor; 163 164 checkCaches(); 165 } 166 167 private void checkCaches() { 168 boolean createFontCache = (font != null && fontMode != 0 && fontMode != FONT_MODE_DEFAULT); 170 boolean createForeColorCache = (foreColor != null && hasAlpha(foreColor)); 171 if (createFontCache || createForeColorCache) { 172 fontAndForeColorCache = new HashMap ( 173 (createFontCache && createForeColorCache) ? 47 : 23); 174 } 175 176 if (backColor != null && hasAlpha(backColor)) { 177 backColorCache = new HashMap (23); 178 } 179 } 180 181 182 private boolean hasAlpha(Color c) { 183 return ((c.getRGB() & 0xFF000000) != 0xFF000000); 184 } 185 186 187 public Font getFont() { 188 return font; 189 } 190 191 192 public int getFontMode() { 193 return fontMode; 194 } 195 196 197 public Color getForeColor() { 198 return foreColor; 199 } 200 201 202 public Color getBackColor() { 203 return backColor; 204 } 205 206 207 public Color getUnderlineColor() { 208 return underlineColor; 209 } 210 211 212 public Color getWaveUnderlineColor() { 213 return waveUnderlineColor; 214 } 215 216 217 public Color getStrikeThroughColor() { 218 return strikeThroughColor; 219 } 220 221 222 private Font modifyFont(Font f) { 223 return new Font ( 224 ((fontMode & FONT_MODE_APPLY_NAME) != 0) ? font.getName() : f.getName(), 225 ((fontMode & FONT_MODE_APPLY_STYLE) != 0) ? font.getStyle() : f.getStyle(), 226 ((fontMode & FONT_MODE_APPLY_SIZE) != 0) ? font.getSize() : f.getSize() 227 ); 228 } 229 230 private Color modifyForeColor(Color underForeColor) { 231 int alpha = foreColor.getAlpha(); int fcRGB = foreColor.getRGB(); 233 int underRGB = underForeColor.getRGB(); 234 235 int rgb = (((foreColor.getRed() * alpha 236 + underForeColor.getRed() * (255 - alpha)) / 255) & 0x000000FF) << 16; 237 238 rgb += ((((fcRGB & 0x0000FF00) * alpha 239 + (underRGB & 0x0000FF00) * (255 - alpha)) / 255) & 0x0000FF00) + ((((fcRGB & 0x000000FF) * alpha 241 + (underRGB & 0x000000FF) * (255 - alpha)) / 255) & 0x000000FF); 243 return new Color (rgb, false); 244 } 245 246 private Color modifyBackColor(Color underBackColor) { 247 int alpha = backColor.getAlpha(); int bcRGB = backColor.getRGB(); 249 int underRGB = underBackColor.getRGB(); 250 int rgb = (((backColor.getRed() * alpha 251 + underBackColor.getRed() * (255 - alpha)) / 255) & 0x000000FF) << 16; 252 253 254 rgb += ((((bcRGB & 0x0000FF00) * alpha 255 + (underRGB & 0x0000FF00) * (255 - alpha)) / 255) & 0x0000FF00) + ((((bcRGB & 0x000000FF) * alpha 257 + (underRGB & 0x000000FF) * (255 - alpha)) / 255) & 0x000000FF); 259 return new Color (rgb, false); 260 } 261 262 263 public void apply(DrawContext ctx) { 264 if (font != null) { 266 if (fontMode == FONT_MODE_DEFAULT) { 267 ctx.setFont(font); 268 269 } else { Font origFont = ctx.getFont(); 271 if (origFont != null) { 272 synchronized (fontAndForeColorCache) { 273 Font f = (Font )fontAndForeColorCache.get(origFont); 274 if (f == null) { 275 f = modifyFont(origFont); 276 fontAndForeColorCache.put(origFont, f); 277 } 278 ctx.setFont(f); 279 } 280 } 281 } 282 } 283 284 if (foreColor != null) { 286 if (!hasAlpha(foreColor)) { ctx.setForeColor(foreColor); 288 289 } else { Color origForeColor = ctx.getForeColor(); 291 if (origForeColor != null) { 292 synchronized (fontAndForeColorCache) { 293 Color fc = (Color )fontAndForeColorCache.get(origForeColor); 294 if (fc == null) { 295 fc = modifyForeColor(origForeColor); 296 fontAndForeColorCache.put(origForeColor, fc); 297 } 298 ctx.setForeColor(fc); 299 } 300 } 301 } 302 } 303 304 if (backColor != null) { 306 if (!hasAlpha(backColor)) { 307 ctx.setBackColor(backColor); 308 309 } else { Color origBackColor = ctx.getBackColor(); 311 if (origBackColor != null) { 312 synchronized (backColorCache) { 313 Color bc = (Color )backColorCache.get(origBackColor); 314 if (bc == null) { 315 bc = modifyBackColor(origBackColor); 316 backColorCache.put(origBackColor, bc); 317 } 318 ctx.setBackColor(bc); 319 } 320 } 321 } 322 } 323 324 if (underlineColor != null) { 325 ctx.setUnderlineColor(underlineColor); 326 } 327 328 if (waveUnderlineColor != null) { 329 ctx.setWaveUnderlineColor(waveUnderlineColor); 330 } 331 332 if (strikeThroughColor != null) { 333 ctx.setStrikeThroughColor(strikeThroughColor); 334 } 335 } 336 337 340 public void apply(JComponent c) { 341 if (font != null) { 343 if (fontMode == FONT_MODE_DEFAULT) { 344 c.setFont(font); 345 346 } else { Font origFont = c.getFont(); 348 if (origFont != null) { 349 synchronized (fontAndForeColorCache) { 350 Font f = (Font )fontAndForeColorCache.get(origFont); 351 if (f == null) { 352 f = modifyFont(origFont); 353 fontAndForeColorCache.put(origFont, f); 354 } 355 c.setFont(f); 356 } 357 } 358 } 359 } 360 361 if (foreColor != null) { 363 if (!hasAlpha(foreColor)) { 364 c.setForeground(foreColor); 365 366 } else { Color origForeColor = c.getForeground(); 368 if (origForeColor != null) { 369 synchronized (fontAndForeColorCache) { 370 Color fc = (Color )fontAndForeColorCache.get(origForeColor); 371 if (fc == null) { 372 fc = modifyForeColor(origForeColor); 373 fontAndForeColorCache.put(origForeColor, fc); 374 } 375 c.setForeground(fc); 376 } 377 } 378 } 379 } 380 381 if (backColor != null) { 383 if (!hasAlpha(backColor)) { 384 c.setBackground(backColor); 385 386 } else { Color origBackColor = c.getBackground(); 388 if (origBackColor != null) { 389 synchronized (backColorCache) { 390 Color bc = (Color )backColorCache.get(origBackColor); 391 if (bc == null) { 392 bc = modifyBackColor(origBackColor); 393 backColorCache.put(origBackColor, bc); 394 } 395 c.setBackground(bc); 396 } 397 } 398 } 399 } 400 } 401 402 407 public Coloring apply(Coloring c) { 408 if (c == null) { return this; 410 } 411 412 Font newFont = c.font; 413 int newFontMode = FONT_MODE_DEFAULT; 414 Color newForeColor = c.foreColor; 415 Color newBackColor = c.backColor; 416 Color newUnderlineColor = c.underlineColor; 417 Color newWaveUnderlineColor = c.waveUnderlineColor; 418 Color newStrikeThroughColor = c.strikeThroughColor; 419 420 if (font != null) { 422 if (fontMode == FONT_MODE_DEFAULT) { 423 newFont = font; 424 425 } else { if (newFont != null) { 427 synchronized (fontAndForeColorCache) { 428 Font f = (Font )fontAndForeColorCache.get(newFont); 429 if (f == null) { 430 f = modifyFont(newFont); 431 fontAndForeColorCache.put(newFont, f); 432 } 433 newFont = f; 434 } 435 } 436 } 437 438 } else { newFontMode = c.fontMode; 441 } 442 443 if (foreColor != null) { 445 if (!hasAlpha(foreColor)) { 446 newForeColor = foreColor; 447 448 } else { if (newForeColor != null) { 450 synchronized (fontAndForeColorCache) { 451 Color fc = (Color )fontAndForeColorCache.get(newForeColor); 452 if (fc == null) { 453 fc = modifyForeColor(newForeColor); 454 fontAndForeColorCache.put(newForeColor, fc); 455 } 456 newForeColor = fc; 457 } 458 } 459 } 460 } 461 462 if (backColor != null) { 464 if (!hasAlpha(backColor)) { 465 newBackColor = backColor; 466 467 } else { newBackColor = backColor; 469 if (newBackColor != null) { 470 synchronized (backColorCache) { 471 Color bc = (Color )backColorCache.get(newBackColor); 472 if (bc == null) { 473 bc = modifyBackColor(newBackColor); 474 backColorCache.put(newBackColor, bc); 475 } 476 newBackColor = bc; 477 } 478 } 479 } 480 } 481 482 if (underlineColor != null) { 483 newUnderlineColor = underlineColor; 484 } 485 486 if (waveUnderlineColor != null) { 487 newWaveUnderlineColor = waveUnderlineColor; 488 } 489 490 if (strikeThroughColor != null) { 491 newStrikeThroughColor = strikeThroughColor; 492 } 493 494 if (c.fontMode != FONT_MODE_DEFAULT 495 || newFont != c.font || newForeColor != c.foreColor || newBackColor != c.backColor || newUnderlineColor != c.underlineColor || newWaveUnderlineColor != c.waveUnderlineColor || newStrikeThroughColor != c.strikeThroughColor ) { 502 return new Coloring(newFont, newFontMode, 503 newForeColor, newBackColor, 504 newUnderlineColor, newStrikeThroughColor, newWaveUnderlineColor 505 ); 506 } else { 507 return c; } 509 510 } 511 512 513 public boolean equals(Object o) { 514 if (o instanceof Coloring) { 515 Coloring c = (Coloring)o; 516 return ((font == null && c.font == null) || (font != null && font.equals(c.font))) 517 && (fontMode == c.fontMode) 518 && ((foreColor == null && c.foreColor == null) 519 || (foreColor != null && foreColor.equals(c.foreColor))) 520 && ((backColor == null && c.backColor == null) 521 || (backColor != null && backColor.equals(c.backColor))) 522 && ((underlineColor == null && c.underlineColor == null) 523 || (underlineColor != null && underlineColor.equals(c.underlineColor))) 524 && ((waveUnderlineColor == null && c.waveUnderlineColor == null) 525 || (waveUnderlineColor != null && waveUnderlineColor.equals(c.waveUnderlineColor))) 526 && ((strikeThroughColor == null && c.strikeThroughColor == null) 527 || (strikeThroughColor != null 528 && strikeThroughColor.equals(c.strikeThroughColor))); 529 } 530 return false; 531 } 532 533 public int hashCode() { 534 return font.hashCode() ^ foreColor.hashCode() ^ backColor.hashCode(); 535 } 536 537 540 public static Coloring changeFont(Coloring c, Font newFont) { 541 return changeFont(c, newFont, c.getFontMode()); 542 } 543 544 547 public static Coloring changeFont(Coloring c, Font newFont, int newFontMode) { 548 if ((newFont == null && c.font == null) 549 || (newFont != null && newFont.equals(c.font) 550 && c.fontMode == newFontMode) 551 ) { 552 return c; 553 } 554 555 return new Coloring(newFont, c.foreColor, c.backColor); 556 } 557 558 562 public static Coloring changeForeColor(Coloring c, Color newForeColor) { 563 if ((newForeColor == null && c.foreColor == null) 564 || (newForeColor != null && newForeColor.equals(c.foreColor)) 565 ) { 566 return c; 567 } 568 569 return new Coloring(c.font, newForeColor, c.backColor); 570 } 571 572 576 public static Coloring changeBackColor(Coloring c, Color newBackColor) { 577 if ((newBackColor == null && c.backColor == null) 578 || (newBackColor != null && newBackColor.equals(c.backColor)) 579 ) { 580 return c; 581 } 582 583 return new Coloring(c.font, c.foreColor, newBackColor); 584 } 585 586 private void readObject(java.io.ObjectInputStream ois) 587 throws java.io.IOException , ClassNotFoundException { 588 ois.defaultReadObject(); 589 590 if (fontMode == 0) { 591 fontMode = FONT_MODE_DEFAULT; 592 } 593 594 checkCaches(); 595 } 596 597 public String toString() { 598 return "font=" + font + ", fontMode=" + fontMode + ", foreColor=" + foreColor + ", backColor=" + backColor + ", underlineColor=" + underlineColor + ", waveUnderlineColor=" + waveUnderlineColor + ", strikeThroughColor=" + strikeThroughColor; } 605 606 private static final WeakHashMap <AttributeSet , Coloring> colorings = new WeakHashMap <AttributeSet , Coloring>(); 607 608 629 public static Coloring fromAttributeSet(AttributeSet as) { 630 synchronized (colorings) { 631 Coloring coloring = colorings.get(as); 632 633 if (coloring == null) { 634 Object [] fontObj = toFont(as); 635 636 coloring = new Coloring( 637 (Font ) fontObj[0], 638 ((Integer ) fontObj[1]).intValue(), 639 (Color ) as.getAttribute(StyleConstants.Foreground), 640 (Color ) as.getAttribute(StyleConstants.Background), 641 (Color ) as.getAttribute(StyleConstants.Underline), 642 (Color ) as.getAttribute(StyleConstants.StrikeThrough), 643 findWaveUnderlineColorHack(as) 644 ); 645 646 colorings.put(as, coloring); 647 } 648 649 return coloring; 650 } 651 } 652 653 private static Color findWaveUnderlineColorHack(AttributeSet as) { 655 Enumeration <?> names = as.getAttributeNames(); 656 657 while (names.hasMoreElements()) { 658 Object name = names.nextElement(); 659 if (name != null && name.toString().equals("wave underline color")) { return (Color ) as.getAttribute(name); 661 } 662 } 663 664 return null; 665 } 666 667 private static Object [] toFont(AttributeSet as) { 668 int applyMode = 0; 669 670 String fontFamily = null; 672 { 673 Object fontFamilyObj = as.getAttribute(StyleConstants.FontFamily); 674 if (fontFamilyObj instanceof String ) { 675 fontFamily = (String ) fontFamilyObj; 676 applyMode += Coloring.FONT_MODE_APPLY_NAME; 677 } 678 } 679 680 int fontSize = 0; 682 { 683 Object fontSizeObj = as.getAttribute(StyleConstants.FontSize); 684 if (fontSizeObj instanceof Integer ) { 685 fontSize = ((Integer ) fontSizeObj).intValue(); 686 applyMode += Coloring.FONT_MODE_APPLY_SIZE; 687 } 688 } 689 690 int style = 0; 692 { 693 Object boldStyleObj = as.getAttribute(StyleConstants.Bold); 694 Object italicStyleObj = as.getAttribute(StyleConstants.Italic); 695 696 if (boldStyleObj != null || italicStyleObj != null) { 697 if (Boolean.TRUE.equals(boldStyleObj)){ 698 style += Font.BOLD; 699 } 700 701 if (Boolean.TRUE.equals(italicStyleObj)){ 702 style += Font.ITALIC; 703 } 704 705 applyMode += Coloring.FONT_MODE_APPLY_STYLE; 706 } 707 } 708 709 return new Object [] { 710 new Font (fontFamily, style, fontSize), 711 new Integer (applyMode) 712 }; 713 } 714 715 } 716 | Popular Tags |