private static void formatStyle( final StringBuilder builder, final SimpleTextAttributes attributes) { final Color fgColor = attributes.getFgColor(); final Color bgColor = attributes.getBgColor(); final int style = attributes.getStyle(); final int pos = builder.length(); if (fgColor != null) { builder .append("color:#") .append(Integer.toString(fgColor.getRGB() & 0xFFFFFF, 16)) .append(';'); } if (bgColor != null) { builder .append("background-color:#") .append(Integer.toString(bgColor.getRGB() & 0xFFFFFF, 16)) .append(';'); } if ((style & SimpleTextAttributes.STYLE_BOLD) != 0) { builder.append("font-weight:bold;"); } if ((style & SimpleTextAttributes.STYLE_ITALIC) != 0) { builder.append("font-style:italic;"); } if ((style & SimpleTextAttributes.STYLE_UNDERLINE) != 0) { builder.append("text-decoration:underline;"); } else if ((style & SimpleTextAttributes.STYLE_STRIKEOUT) != 0) { builder.append("text-decoration:line-through;"); } if (builder.length() > pos) { builder.insert(pos, " style=\""); builder.append('"'); } }
protected int doPaintText(Graphics2D g, int offset, boolean focusAroundIcon) { // If there is no icon, then we have to add left internal padding if (offset == 0) { offset = myIpad.left; } int textStart = offset; if (myBorder != null) { offset += myBorder.getBorderInsets(this).left; } final List<Object[]> searchMatches = new ArrayList<>(); applyAdditionalHints(g); final Font baseFont = getBaseFont(); g.setFont(baseFont); offset += computeTextAlignShift(baseFont); int baseSize = baseFont.getSize(); FontMetrics baseMetrics = g.getFontMetrics(); Rectangle area = computePaintArea(); final int textBaseline = area.y + getTextBaseLine(baseMetrics, area.height); boolean wasSmaller = false; for (int i = 0; i < myFragments.size(); i++) { final SimpleTextAttributes attributes = myAttributes.get(i); Font font = g.getFont(); boolean isSmaller = attributes.isSmaller(); if (font.getStyle() != attributes.getFontStyle() || isSmaller != wasSmaller) { // derive font only if it is necessary font = font.deriveFont( attributes.getFontStyle(), isSmaller ? UIUtil.getFontSize(UIUtil.FontSize.SMALL) : baseSize); } wasSmaller = isSmaller; g.setFont(font); final FontMetrics metrics = g.getFontMetrics(font); final int fragmentWidth = computeStringWidth(i, font); final int fragmentPadding = myFragmentPadding.get(i); final Color bgColor = attributes.isSearchMatch() ? null : attributes.getBgColor(); if ((attributes.isOpaque() || isOpaque()) && bgColor != null) { g.setColor(bgColor); g.fillRect(offset, 0, fragmentWidth, getHeight()); } Color color = attributes.getFgColor(); if (color == null) { // in case if color is not defined we have to get foreground color from Swing // hierarchy color = getForeground(); } if (!isEnabled()) { color = UIUtil.getInactiveTextColor(); } g.setColor(color); final int fragmentAlignment = myFragmentAlignment.get(i); final int endOffset; if (fragmentPadding > 0 && fragmentPadding > fragmentWidth) { endOffset = fragmentPadding; if (fragmentAlignment == SwingConstants.RIGHT || fragmentAlignment == SwingConstants.TRAILING) { offset = fragmentPadding - fragmentWidth; } } else { endOffset = offset + fragmentWidth; } if (!attributes.isSearchMatch()) { if (shouldDrawMacShadow()) { g.setColor(SHADOW_COLOR); doDrawString(g, i, offset, textBaseline + 1); } if (shouldDrawDimmed()) { color = ColorUtil.dimmer(color); } g.setColor(color); doDrawString(g, i, offset, textBaseline); } // for some reason strokeState here may be incorrect, resetting the stroke helps g.setStroke(g.getStroke()); // 1. Strikeout effect if (attributes.isStrikeout() && !attributes.isSearchMatch()) { EffectPainter.STRIKE_THROUGH.paint( g, offset, textBaseline, fragmentWidth, getCharHeight(g), font); } // 2. Waved effect if (attributes.isWaved()) { if (attributes.getWaveColor() != null) { g.setColor(attributes.getWaveColor()); } EffectPainter.WAVE_UNDERSCORE.paint( g, offset, textBaseline + 1, fragmentWidth, Math.max(2, metrics.getDescent()), font); } // 3. Underline if (attributes.isUnderline()) { EffectPainter.LINE_UNDERSCORE.paint( g, offset, textBaseline, fragmentWidth, metrics.getDescent(), font); } // 4. Bold Dotted Line if (attributes.isBoldDottedLine()) { final int dottedAt = SystemInfo.isMac ? textBaseline : textBaseline + 1; final Color lineColor = attributes.getWaveColor(); UIUtil.drawBoldDottedLine( g, offset, offset + fragmentWidth, dottedAt, bgColor, lineColor, isOpaque()); } if (attributes.isSearchMatch()) { searchMatches.add( new Object[] { offset, offset + fragmentWidth, textBaseline, myFragments.get(i), g.getFont(), attributes }); } offset = endOffset; } // Paint focus border around the text and icon (if necessary) if (myPaintFocusBorder && myBorder != null) { if (focusAroundIcon) { myBorder.paintBorder(this, g, 0, 0, getWidth(), getHeight()); } else { myBorder.paintBorder(this, g, textStart, 0, getWidth() - textStart, getHeight()); } } // draw search matches after all for (final Object[] info : searchMatches) { Integer x1 = (Integer) info[0]; Integer x2 = (Integer) info[1]; UIUtil.drawSearchMatch(g, x1, x2, getHeight()); g.setFont((Font) info[4]); Integer baseline = (Integer) info[2]; String text = (String) info[3]; if (shouldDrawMacShadow()) { g.setColor(SHADOW_COLOR); g.drawString(text, x1, baseline + 1); } g.setColor(new JBColor(Gray._50, Gray._0)); g.drawString(text, x1, baseline); if (((SimpleTextAttributes) info[5]).isStrikeout()) { EffectPainter.STRIKE_THROUGH.paint(g, x1, baseline, x2 - x1, getCharHeight(g), g.getFont()); } } return offset; }