private void merge(TextAttributes attributes) {
   Color myBackground = myMergedAttributes.getBackgroundColor();
   if (myBackground == null || myDefaultBackground.equals(myBackground)) {
     myMergedAttributes.setBackgroundColor(attributes.getBackgroundColor());
   }
   Color myForeground = myMergedAttributes.getForegroundColor();
   if (myForeground == null || myDefaultForeground.equals(myForeground)) {
     myMergedAttributes.setForegroundColor(attributes.getForegroundColor());
   }
   if (myMergedAttributes.getFontType() == Font.PLAIN) {
     myMergedAttributes.setFontType(attributes.getFontType());
   }
 }
 private static TextAttributes mergeAttributes(TextAttributes primary, TextAttributes secondary) {
   if (primary == null) return secondary;
   if (secondary == null) return primary;
   return new TextAttributes(
       primary.getForegroundColor() == null
           ? secondary.getForegroundColor()
           : primary.getForegroundColor(),
       primary.getBackgroundColor() == null
           ? secondary.getBackgroundColor()
           : primary.getBackgroundColor(),
       primary.getEffectColor() == null ? secondary.getEffectColor() : primary.getEffectColor(),
       primary.getEffectType() == null ? secondary.getEffectType() : primary.getEffectType(),
       primary.getFontType() == Font.PLAIN ? secondary.getFontType() : primary.getFontType());
 }
  private void highlightInjectedSyntax(
      @NotNull PsiFile injectedPsi, @NotNull HighlightInfoHolder holder) {
    List<Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange>>
        tokens = InjectedLanguageUtil.getHighlightTokens(injectedPsi);
    if (tokens == null) return;

    final Language injectedLanguage = injectedPsi.getLanguage();
    Project project = injectedPsi.getProject();
    SyntaxHighlighter syntaxHighlighter =
        SyntaxHighlighterFactory.getSyntaxHighlighter(
            injectedLanguage, project, injectedPsi.getVirtualFile());
    final TextAttributes defaultAttrs = myGlobalScheme.getAttributes(HighlighterColors.TEXT);

    for (Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange> token :
        tokens) {
      ProgressManager.checkCanceled();
      IElementType tokenType = token.getFirst();
      PsiLanguageInjectionHost injectionHost = token.getSecond().getElement();
      if (injectionHost == null) continue;
      TextRange textRange = token.getThird();
      TextAttributesKey[] keys = syntaxHighlighter.getTokenHighlights(tokenType);
      if (textRange.getLength() == 0) continue;

      TextRange annRange = textRange.shiftRight(injectionHost.getTextRange().getStartOffset());
      // force attribute colors to override host' ones
      TextAttributes attributes = null;
      for (TextAttributesKey key : keys) {
        TextAttributes attrs2 = myGlobalScheme.getAttributes(key);
        if (attrs2 != null) {
          attributes = attributes == null ? attrs2 : TextAttributes.merge(attributes, attrs2);
        }
      }
      TextAttributes forcedAttributes;
      if (attributes == null || attributes.isEmpty() || attributes.equals(defaultAttrs)) {
        forcedAttributes = TextAttributes.ERASE_MARKER;
      } else {
        HighlightInfo info =
            HighlightInfo.newHighlightInfo(HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT)
                .range(annRange)
                .textAttributes(TextAttributes.ERASE_MARKER)
                .createUnconditionally();
        holder.add(info);

        forcedAttributes =
            new TextAttributes(
                attributes.getForegroundColor(),
                attributes.getBackgroundColor(),
                attributes.getEffectColor(),
                attributes.getEffectType(),
                attributes.getFontType());
      }

      HighlightInfo info =
          HighlightInfo.newHighlightInfo(HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT)
              .range(annRange)
              .textAttributes(forcedAttributes)
              .createUnconditionally();
      holder.add(info);
    }
  }
 @Override
 public TextAttributes getTextAttributes() {
   TextAttributes ta = myIterators[0].iterator.getTextAttributes();
   myMergedAttributes.setAttributes(
       ta.getForegroundColor(), ta.getBackgroundColor(), null, null, null, ta.getFontType());
   for (int i = 1; i < overlappingRangesCount; i++) {
     merge(myIterators[i].iterator.getTextAttributes());
   }
   return myMergedAttributes;
 }
 public void advance() {
   if (mySegmentIterator.atEnd()) {
     myRangeIterator.advance();
     TextAttributes textAttributes = myRangeIterator.getTextAttributes();
     myCurrentFontStyle = textAttributes == null ? Font.PLAIN : textAttributes.getFontType();
     myCurrentForegroundColor =
         textAttributes == null ? null : textAttributes.getForegroundColor();
     myCurrentBackgroundColor =
         textAttributes == null ? null : textAttributes.getBackgroundColor();
     mySegmentIterator.reset(
         myRangeIterator.getRangeStart(), myRangeIterator.getRangeEnd(), myCurrentFontStyle);
   }
   mySegmentIterator.advance();
 }
 private void findNextSuitableRange() {
   myNextAttributes = null;
   while (myIterator.hasNext()) {
     RangeHighlighterEx highlighter = myIterator.next();
     if (highlighter == null
         || !highlighter.isValid()
         || !isInterestedInLayer(highlighter.getLayer())) {
       continue;
     }
     // LINES_IN_RANGE highlighters are not supported currently
     myNextStart = Math.max(highlighter.getStartOffset(), myStartOffset);
     myNextEnd = Math.min(highlighter.getEndOffset(), myEndOffset);
     if (myNextStart >= myEndOffset) {
       break;
     }
     if (myNextStart < myCurrentEnd) {
       continue; // overlapping ranges withing document markup model are not supported currently
     }
     TextAttributes attributes = null;
     Object tooltip = highlighter.getErrorStripeTooltip();
     if (tooltip instanceof HighlightInfo) {
       HighlightInfo info = (HighlightInfo) tooltip;
       TextAttributesKey key = info.forcedTextAttributesKey;
       if (key == null) {
         HighlightInfoType type = info.type;
         key = type.getAttributesKey();
       }
       if (key != null) {
         attributes = myColorsScheme.getAttributes(key);
       }
     }
     if (attributes == null) {
       continue;
     }
     Color foreground = attributes.getForegroundColor();
     Color background = attributes.getBackgroundColor();
     if ((foreground == null || myDefaultForeground.equals(foreground))
         && (background == null || myDefaultBackground.equals(background))
         && attributes.getFontType() == Font.PLAIN) {
       continue;
     }
     myNextAttributes = attributes;
     break;
   }
 }