/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Stephan Wahlbrink <sw@wahlbrink.eu> - Annotations not painted when length is 0 / at document end - http://bugs.eclipse.org/bugs/show_bug.cgi?id=227534
 *******************************************************************************/
package org.eclipse.jface.text.source;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.TextStyle;
import org.eclipse.swt.widgets.Display;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.Platform;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IPaintPositionManager;
import org.eclipse.jface.text.IPainter;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextInputListener;
import org.eclipse.jface.text.ITextPresentationListener;
import org.eclipse.jface.text.ITextViewerExtension2;
import org.eclipse.jface.text.ITextViewerExtension4;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.JFaceTextUtil;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextPresentation;


/**
 * Paints decorations for annotations provided by an annotation model and/or
 * highlights them in the associated source viewer.
 * <p>
 * The annotation painter can be configured with drawing strategies. A drawing
 * strategy defines the visual presentation of a particular type of annotation
 * decoration.</p>
 * <p>
 * Clients usually instantiate and configure objects of this class.</p>
 *
 * @since 2.1
 */
public class AnnotationPainter implements IPainter, PaintListener, IAnnotationModelListener, IAnnotationModelListenerExtension, ITextPresentationListener {


	/**
	 * A drawing strategy draws the decoration for an annotation onto the text widget.
	 *
	 * @since 3.0
	 */
	public interface IDrawingStrategy {
		/**
		 * Draws a decoration for an annotation onto the specified GC at the given text range. There
		 * are two different invocation modes of the <code>draw</code> method:
		 * <ul>
		 * <li><strong>drawing mode:</strong> the passed GC is the graphics context of a paint
		 * event occurring on the text widget. The strategy should draw the decoration onto the
		 * graphics context, such that the decoration appears at the given range in the text
		 * widget.</li>
		 * <li><strong>clearing mode:</strong> the passed GC is <code>null</code>. In this case
		 * the strategy must invalidate enough of the text widget's client area to cover any
		 * decoration drawn in drawing mode. This can usually be accomplished by calling
		 * {@linkplain StyledText#redrawRange(int, int, boolean) textWidget.redrawRange(offset, length, true)}.</li>
		 * </ul>
		 *
		 * @param annotation the annotation to be drawn
		 * @param gc the graphics context, <code>null</code> when in clearing mode
		 * @param textWidget the text widget to draw on
		 * @param offset the offset of the line
		 * @param length the length of the line
		 * @param color the color of the line
		 */
		void draw(Annotation annotation, GC gc, StyledText textWidget, int offset, int length, Color color);
	}

	/**
	 * Squiggles drawing strategy.
	 *
	 * @since 3.0
	 * @deprecated As of 3.4, replaced by {@link AnnotationPainter.UnderlineStrategy}
	 */
	@Deprecated
	public static class SquigglesStrategy implements IDrawingStrategy {

		@Override
		public void draw(Annotation annotation, GC gc, StyledText textWidget, int offset, int length, Color color) {
			if (gc != null) {

				if (length < 1)
					return;

				Point left= textWidget.getLocationAtOffset(offset);
				Point right= textWidget.getLocationAtOffset(offset + length);
				Rectangle rect= textWidget.getTextBounds(offset, offset + length - 1);
				left.x= rect.x;
				right.x= rect.x + rect.width;

				int[] polyline= computePolyline(left, right, textWidget.getBaseline(offset), textWidget.getLineHeight(offset));

				gc.setLineWidth(0); // NOTE: 0 means width is 1 but with optimized performance
				gc.setLineStyle(SWT.LINE_SOLID);
				gc.setForeground(color);
				gc.drawPolyline(polyline);

			} else {
				textWidget.redrawRange(offset, length, true);
			}
		}

		/**
		 * Computes an array of alternating x and y values which are the corners of the squiggly line of the
		 * given height between the given end points.
		 *
		 * @param left the left end point
		 * @param right the right end point
		 * @param baseline the font's baseline
		 * @param lineHeight the height of the line
		 * @return the array of alternating x and y values which are the corners of the squiggly line
		 */
		private int[] computePolyline(Point left, Point right, int baseline, int lineHeight) {

			final int WIDTH= 4; // must be even
			final int HEIGHT= 2; // can be any number

			int peaks= (right.x - left.x) / WIDTH;
			if (peaks == 0 && right.x - left.x > 2)
				peaks= 1;

			int leftX= left.x;

			// compute (number of point) * 2
			int length= ((2 * peaks) + 1) * 2;
			if (length < 0)
				return new int[0];

			int[] coordinates= new int[length];

			// cache peeks' y-coordinates
			int top= left.y + Math.min(baseline + 1, lineHeight - HEIGHT - 1);
			int bottom= top + HEIGHT;

			// populate array with peek coordinates
			for (int i= 0; i < peaks; i++) {
				int index= 4 * i;
				coordinates[index]= leftX + (WIDTH * i);
				coordinates[index+1]= bottom;
				coordinates[index+2]= coordinates[index] + WIDTH/2;
				coordinates[index+3]= top;
			}

			// the last down flank is missing
			coordinates[length-2]= Math.min(Math.max(0, right.x - 1), left.x + (WIDTH * peaks));
			coordinates[length-1]= bottom;

			return coordinates;
		}
	}

	/**
	 * Drawing strategy that does nothing.
	 *
	 * @since 3.0
	 */
	public static final class NullStrategy implements IDrawingStrategy {

		@Override
		public void draw(Annotation annotation, GC gc, StyledText textWidget, int offset, int length, Color color) {
			// do nothing
		}
	}


	/**
	 * A text style painting strategy draws the decoration for an annotation
	 * onto the text widget by applying a {@link TextStyle} on a given
	 * {@link StyleRange}.
	 *
	 * @since 3.4
	 */
	public interface ITextStyleStrategy {

		/**
		 * Applies a text style on the given <code>StyleRange</code>.
		 *
		 * @param styleRange the style range on which to apply the text style
		 * @param annotationColor the color of the annotation
		 */
		void applyTextStyle(StyleRange styleRange, Color annotationColor);
	}


	/**
	 * @since 3.4
	 */
	public static final class HighlightingStrategy implements ITextStyleStrategy {
		@Override
		public void applyTextStyle(StyleRange styleRange, Color annotationColor) {
			styleRange.background= annotationColor;
		}
	}


	/**
	 * Underline text style strategy.
	 *
	 * @since 3.4
	 */
	public static final class UnderlineStrategy implements ITextStyleStrategy {

		int fUnderlineStyle;

		public UnderlineStrategy(int style) {
			Assert.isLegal(style == SWT.UNDERLINE_SINGLE || style == SWT.UNDERLINE_DOUBLE || style == SWT.UNDERLINE_ERROR || style == SWT.UNDERLINE_SQUIGGLE);
			fUnderlineStyle= style;
		}

		@Override
		public void applyTextStyle(StyleRange styleRange, Color annotationColor) {
			styleRange.underline= true;
			styleRange.underlineStyle= fUnderlineStyle;
			styleRange.underlineColor= annotationColor;
		}
	}


	/**
	 * Box text style strategy.
	 *
	 * @since 3.4
	 */
	public static final class BoxStrategy implements ITextStyleStrategy {

		int fBorderStyle;

		public BoxStrategy(int style) {
			Assert.isLegal(style == SWT.BORDER_DASH || style == SWT.BORDER_DOT || style == SWT.BORDER_SOLID);
			fBorderStyle= style;
		}

		@Override
		public void applyTextStyle(StyleRange styleRange, Color annotationColor) {
			styleRange.borderStyle= fBorderStyle;
			styleRange.borderColor= annotationColor;
		}
	}


	/**
	 * Implementation of <code>IRegion</code> that can be reused
	 * by setting the offset and the length.
	 */
	private static class ReusableRegion extends Position implements IRegion {}

	/**
	 * Tells whether this class is in debug mode.
	 * @since 3.0
	 */
	private static boolean DEBUG= "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jface.text/debug/AnnotationPainter"));  //$NON-NLS-1$//$NON-NLS-2$
	/**
	 * The squiggly painter strategy.
	 * @since 3.0
	 */
	private static final IDrawingStrategy SQUIGGLES_STRATEGY= new SquigglesStrategy();

	/**
	 * This strategy is used to mark the <code>null</code> value in the chache
	 * maps.
	 *
	 * @since 3.4
	 */
	private static final IDrawingStrategy NULL_STRATEGY= new NullStrategy();
	/**
	 * The squiggles painter id.
	 * @since 3.0
	 */
	private static final Object SQUIGGLES= new Object();
	/**
	 * The squiggly painter strategy.
	 *
	 * @since 3.4
	 */
	private static final ITextStyleStrategy HIGHLIGHTING_STRATEGY= new HighlightingStrategy();

	/**
	 * The highlighting text style strategy id.
	 *
	 * @since 3.4
	 */
	private static final Object HIGHLIGHTING= new Object();

	/**
	 * The presentation information (decoration) for an annotation.  Each such
	 * object represents one decoration drawn on the text area, such as squiggly lines
	 * and underlines.
	 */
	private static class Decoration {
		/** The position of this decoration */
		private Position fPosition;
		/** The color of this decoration */
		private Color fColor;
		/**
		 * The annotation's layer
		 * @since 3.0
		 */
		private int fLayer;
		/**
		 * The painting strategy for this decoration.
		 * @since 3.0
		 */
		private Object fPaintingStrategy;
	}


	/** Indicates whether this painter is active */
	private boolean fIsActive= false;
	/** Indicates whether this painter is managing decorations */
	private boolean fIsPainting= false;
	/** Indicates whether this painter is setting its annotation model */
	private volatile boolean  fIsSettingModel= false;
	/** The associated source viewer */
	private ISourceViewer fSourceViewer;
	/** The cached widget of the source viewer */
	private StyledText fTextWidget;
	/** The annotation model providing the annotations to be drawn */
	private IAnnotationModel fModel;
	/** The annotation access */
	private IAnnotationAccess fAnnotationAccess;
	/**
	 * The map with decorations
	 * @since 3.0
	 */
	private Map<Annotation, Decoration> fDecorationsMap= new HashMap<>(); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=50767
	/**
	 * The map with of highlighted decorations.
	 * @since 3.0
	 */
	private Map<Annotation, Decoration> fHighlightedDecorationsMap= new HashMap<>(); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=50767
	/**
	 * Mutex for highlighted decorations map.
	 * @since 3.0
	 */
	private Object fDecorationMapLock= new Object();
	/**
	 * Mutex for for decorations map.
	 * @since 3.0
	 */
	private Object fHighlightedDecorationsMapLock= new Object();
	/**
	 * Maps an annotation type to its registered color.
	 *
	 * @see #setAnnotationTypeColor(Object, Color)
	 */
	private Map<Object, Color> fAnnotationType2Color= new HashMap<>();

	/**
	 * Cache that maps the annotation type to its color.
	 * @since 3.4
	 */
	private Map<Object, Color> fCachedAnnotationType2Color= new HashMap<>();
	/**
	 * The range in which the current highlight annotations can be found.
	 * @since 3.0
	 */
	private Position fCurrentHighlightAnnotationRange= null;
	/**
	 * The range in which all added, removed and changed highlight
	 * annotations can be found since the last world change.
	 * @since 3.0
	 */
	private Position fTotalHighlightAnnotationRange= null;
	/**
	 * The range in which the currently drawn annotations can be found.
	 * @since 3.3
	 */
	private Position fCurrentDrawRange= null;
	/**
	 * The range in which all added, removed and changed drawn
	 * annotations can be found since the last world change.
	 * @since 3.3
	 */
	private Position fTotalDrawRange= null;
	/**
	 * The text input listener.
	 * @since 3.0
	 */
	private ITextInputListener fTextInputListener;
	/**
	 * Flag which tells that a new document input is currently being set.
	 * @since 3.0
	 */
	private boolean fInputDocumentAboutToBeChanged;
	/**
	 * Maps annotation types to painting strategy identifiers.
	 *
	 * @see #addAnnotationType(Object, Object)
	 * @since 3.0
	 */
	private Map<Object, Object> fAnnotationType2PaintingStrategyId= new HashMap<>();
	/**
	 * Maps annotation types to painting strategy identifiers.
	 * @since 3.4
	 */
	private Map<String, Object> fCachedAnnotationType2PaintingStrategy= new HashMap<>();

	/**
	 * Maps painting strategy identifiers to painting strategies.
	 *
	 * @since 3.0
	 */
	private Map<Object, Object> fPaintingStrategyId2PaintingStrategy= new HashMap<>();

	/**
	 * Reuse this region for performance reasons.
	 * @since 3.3
	 */
	private ReusableRegion fReusableRegion= new ReusableRegion();

	/**
	 * Creates a new annotation painter for the given source viewer and with the
	 * given annotation access. The painter is not initialized, i.e. no
	 * annotation types are configured to be painted.
	 *
	 * @param sourceViewer the source viewer for this painter
	 * @param access the annotation access for this painter
	 */
	public AnnotationPainter(ISourceViewer sourceViewer, IAnnotationAccess access) {
		fSourceViewer= sourceViewer;
		fAnnotationAccess= access;
		fTextWidget= sourceViewer.getTextWidget();

		// default drawing strategies: squiggles were the only decoration style before version 3.0
		fPaintingStrategyId2PaintingStrategy.put(SQUIGGLES, SQUIGGLES_STRATEGY);
		fPaintingStrategyId2PaintingStrategy.put(HIGHLIGHTING, HIGHLIGHTING_STRATEGY);
	}

	/**
	 * Returns whether this painter has to draw any squiggles.
	 *
	 * @return <code>true</code> if there are squiggles to be drawn, <code>false</code> otherwise
	 */
	private boolean hasDecorations() {
		synchronized (fDecorationMapLock) {
			return !fDecorationsMap.isEmpty();
		}
	}

	/**
	 * Enables painting. This painter registers a paint listener with the
	 * source viewer's widget.
	 */
	private void enablePainting() {
		if (!fIsPainting && hasDecorations()) {
			fIsPainting= true;
			fTextWidget.addPaintListener(this);
			handleDrawRequest(null);
		}
	}

	/**
	 * Disables painting, if is has previously been enabled. Removes
	 * any paint listeners registered with the source viewer's widget.
	 *
	 * @param redraw <code>true</code> if the widget should be redrawn after disabling
	 */
	private void disablePainting(boolean redraw) {
		if (fIsPainting) {
			fIsPainting= false;
			fTextWidget.removePaintListener(this);
			if (redraw && hasDecorations())
				handleDrawRequest(null);
		}
	}

	/**
	 * Sets the annotation model for this painter. Registers this painter
	 * as listener of the give model, if the model is not <code>null</code>.
	 *
	 * @param model the annotation model
	 */
	private void setModel(IAnnotationModel model) {
		if (fModel != model) {
			if (fModel != null)
				fModel.removeAnnotationModelListener(this);
			fModel= model;
			if (fModel != null) {
				try {
					fIsSettingModel= true;
					fModel.addAnnotationModelListener(this);
				} finally {
					fIsSettingModel= false;
				}
			}
		}
	}

	/**
	 * Updates the set of decorations based on the current state of
	 * the painter's annotation model.
	 *
	 * @param event the annotation model event
	 */
	private void catchupWithModel(AnnotationModelEvent event) {

		synchronized (fDecorationMapLock) {
			if (fDecorationsMap == null)
				return;
		}

		if (fModel == null) {
			// annotation model is null -> clear all
			synchronized (fDecorationMapLock) {
				fDecorationsMap.clear();
			}
			synchronized (fHighlightedDecorationsMapLock) {
				fHighlightedDecorationsMap.clear();
			}
			return;
		}

		IRegion clippingRegion= computeClippingRegion(null, true);
		IDocument document= fSourceViewer.getDocument();

		int highlightAnnotationRangeStart= Integer.MAX_VALUE;
		int highlightAnnotationRangeEnd= -1;

		int drawRangeStart= Integer.MAX_VALUE;
		int drawRangeEnd= -1;

		Map<Annotation, Decoration> decorationsMap;
		Map<Annotation, Decoration> highlightedDecorationsMap;

		// Clone decoration maps
		synchronized (fDecorationMapLock) {
			decorationsMap= new HashMap<>(fDecorationsMap);
		}
		synchronized (fHighlightedDecorationsMapLock) {
			highlightedDecorationsMap= new HashMap<>(fHighlightedDecorationsMap);
		}

		boolean isWorldChange= false;

		Iterator<Annotation> e;
		if (event == null || event.isWorldChange()) {
			isWorldChange= true;

			if (DEBUG && event == null)
				System.out.println("AP: INTERNAL CHANGE"); //$NON-NLS-1$

			Iterator<Entry<Annotation, Decoration>> iter= decorationsMap.entrySet().iterator();
			while (iter.hasNext()) {
				Entry<Annotation, Decoration> entry= iter.next();
				Annotation annotation= entry.getKey();
				Decoration decoration= entry.getValue();
				drawDecoration(decoration, null, annotation, clippingRegion, document);
			}

			decorationsMap.clear();

			highlightedDecorationsMap.clear();

			e= fModel.getAnnotationIterator();


		} else {

			// Remove annotations
			Annotation[] removedAnnotations= event.getRemovedAnnotations();
			for (int i= 0, length= removedAnnotations.length; i < length; i++) {
				Annotation annotation= removedAnnotations[i];
				Decoration decoration= highlightedDecorationsMap.remove(annotation);
				if (decoration != null) {
					Position position= decoration.fPosition;
					if (position != null) {
						highlightAnnotationRangeStart= Math.min(highlightAnnotationRangeStart, position.offset);
						highlightAnnotationRangeEnd= Math.max(highlightAnnotationRangeEnd, position.offset + position.length);
					}
				}
				decoration= decorationsMap.remove(annotation);
				if (decoration != null) {
					drawDecoration(decoration, null, annotation, clippingRegion, document);
					Position position= decoration.fPosition;
					if (position != null) {
						drawRangeStart= Math.min(drawRangeStart, position.offset);
						drawRangeEnd= Math.max(drawRangeEnd, position.offset + position.length);
					}
				}

			}

			// Update existing annotations
			Annotation[] changedAnnotations= event.getChangedAnnotations();
			for (int i= 0, length= changedAnnotations.length; i < length; i++) {
				Annotation annotation= changedAnnotations[i];

				boolean isHighlighting= false;

				Decoration decoration= highlightedDecorationsMap.get(annotation);

				if (decoration != null) {
					isHighlighting= true;
					// The call below updates the decoration - no need to create new decoration
					decoration= getDecoration(annotation, decoration);
					if (decoration == null) {
						Decoration removedDecoration= highlightedDecorationsMap.remove(annotation);
						if (removedDecoration != null) {
							highlightAnnotationRangeStart= Math.min(highlightAnnotationRangeStart, removedDecoration.fPosition.offset);
							highlightAnnotationRangeEnd= Math.max(highlightAnnotationRangeEnd, removedDecoration.fPosition.offset + removedDecoration.fPosition.length);
						}
					}

				} else {
					decoration= getDecoration(annotation, decoration);
					if (decoration != null && decoration.fPaintingStrategy instanceof ITextStyleStrategy) {
						highlightedDecorationsMap.put(annotation, decoration);
						isHighlighting= true;
					}
				}

				boolean usesDrawingStrategy= !isHighlighting && decoration != null;

				Position position= null;
				if (decoration == null)
					position= fModel.getPosition(annotation);
				else
					position= decoration.fPosition;

				if (position != null && !position.isDeleted()) {
					if (isHighlighting) {
						highlightAnnotationRangeStart= Math.min(highlightAnnotationRangeStart, position.offset);
						highlightAnnotationRangeEnd= Math.max(highlightAnnotationRangeEnd, position.offset + position.length);
					}
					if (usesDrawingStrategy) {
						drawRangeStart= Math.min(drawRangeStart, position.offset);
						drawRangeEnd= Math.max(drawRangeEnd, position.offset + position.length);
					}
				} else {
					Decoration removedDecoration= highlightedDecorationsMap.remove(annotation);
					if (removedDecoration != null) {
						highlightAnnotationRangeStart= Math.min(highlightAnnotationRangeStart, removedDecoration.fPosition.offset);
						highlightAnnotationRangeEnd= Math.max(highlightAnnotationRangeEnd, removedDecoration.fPosition.offset + removedDecoration.fPosition.length);
					}
				}

				if (usesDrawingStrategy) {
					Decoration oldDecoration= decorationsMap.get(annotation);
					if (oldDecoration != null) {
						drawDecoration(oldDecoration, null, annotation, clippingRegion, document);
						if (decoration != null)
							decorationsMap.put(annotation, decoration);
						else
							decorationsMap.remove(annotation);
					}
				}
			}

			e= Arrays.asList(event.getAddedAnnotations()).iterator();
		}

		// Add new annotations
		while (e.hasNext()) {
			Annotation annotation= e.next();
			Decoration pp= getDecoration(annotation, null);
			if (pp != null) {
				if (pp.fPaintingStrategy instanceof IDrawingStrategy) {
					decorationsMap.put(annotation, pp);
					drawRangeStart= Math.min(drawRangeStart, pp.fPosition.offset);
					drawRangeEnd= Math.max(drawRangeEnd, pp.fPosition.offset + pp.fPosition.length);
				} else if (pp.fPaintingStrategy instanceof ITextStyleStrategy) {
					highlightedDecorationsMap.put(annotation, pp);
					highlightAnnotationRangeStart= Math.min(highlightAnnotationRangeStart, pp.fPosition.offset);
					highlightAnnotationRangeEnd= Math.max(highlightAnnotationRangeEnd, pp.fPosition.offset + pp.fPosition.length);
				}

			}
		}

		synchronized (fDecorationMapLock) {
			fDecorationsMap= decorationsMap;
			updateDrawRanges(drawRangeStart, drawRangeEnd, isWorldChange);
		}

		synchronized (fHighlightedDecorationsMapLock) {
			fHighlightedDecorationsMap= highlightedDecorationsMap;
			updateHighlightRanges(highlightAnnotationRangeStart, highlightAnnotationRangeEnd, isWorldChange);
		}
	}

	/**
	 * Updates the remembered highlight ranges.
	 *
	 * @param highlightAnnotationRangeStart the start of the range
	 * @param highlightAnnotationRangeEnd	the end of the range
	 * @param isWorldChange					tells whether the range belongs to a annotation model event reporting a world change
	 * @since 3.0
	 */
	private void updateHighlightRanges(int highlightAnnotationRangeStart, int highlightAnnotationRangeEnd, boolean isWorldChange) {
		if (highlightAnnotationRangeStart != Integer.MAX_VALUE) {

			int maxRangeStart= highlightAnnotationRangeStart;
			int maxRangeEnd= highlightAnnotationRangeEnd;

			if (fTotalHighlightAnnotationRange != null) {
				maxRangeStart= Math.min(maxRangeStart, fTotalHighlightAnnotationRange.offset);
				maxRangeEnd= Math.max(maxRangeEnd, fTotalHighlightAnnotationRange.offset + fTotalHighlightAnnotationRange.length);
			}

			if (fTotalHighlightAnnotationRange == null)
				fTotalHighlightAnnotationRange= new Position(0);
			if (fCurrentHighlightAnnotationRange == null)
				fCurrentHighlightAnnotationRange= new Position(0);

			if (isWorldChange) {
				fTotalHighlightAnnotationRange.offset= highlightAnnotationRangeStart;
				fTotalHighlightAnnotationRange.length= highlightAnnotationRangeEnd - highlightAnnotationRangeStart;
				fCurrentHighlightAnnotationRange.offset= maxRangeStart;
				fCurrentHighlightAnnotationRange.length= maxRangeEnd - maxRangeStart;
			} else {
				fTotalHighlightAnnotationRange.offset= maxRangeStart;
				fTotalHighlightAnnotationRange.length= maxRangeEnd - maxRangeStart;
				fCurrentHighlightAnnotationRange.offset=highlightAnnotationRangeStart;
				fCurrentHighlightAnnotationRange.length= highlightAnnotationRangeEnd - highlightAnnotationRangeStart;
			}
		} else {
			if (isWorldChange) {
				fCurrentHighlightAnnotationRange= fTotalHighlightAnnotationRange;
				fTotalHighlightAnnotationRange= null;
			} else {
				fCurrentHighlightAnnotationRange= null;
			}
		}

		adaptToDocumentLength(fCurrentHighlightAnnotationRange);
		adaptToDocumentLength(fTotalHighlightAnnotationRange);
	}

	/**
	 * Updates the remembered decoration ranges.
	 *
	 * @param drawRangeStart	the start of the range
	 * @param drawRangeEnd		the end of the range
	 * @param isWorldChange		tells whether the range belongs to a annotation model event reporting a world change
	 * @since 3.3
	 */
	private void updateDrawRanges(int drawRangeStart, int drawRangeEnd, boolean isWorldChange) {
		if (drawRangeStart != Integer.MAX_VALUE) {

			int maxRangeStart= drawRangeStart;
			int maxRangeEnd= drawRangeEnd;

			if (fTotalDrawRange != null) {
				maxRangeStart= Math.min(maxRangeStart, fTotalDrawRange.offset);
				maxRangeEnd= Math.max(maxRangeEnd, fTotalDrawRange.offset + fTotalDrawRange.length);
			}

			if (fTotalDrawRange == null)
				fTotalDrawRange= new Position(0);
			if (fCurrentDrawRange == null)
				fCurrentDrawRange= new Position(0);

			if (isWorldChange) {
				fTotalDrawRange.offset= drawRangeStart;
				fTotalDrawRange.length= drawRangeEnd - drawRangeStart;
				fCurrentDrawRange.offset= maxRangeStart;
				fCurrentDrawRange.length= maxRangeEnd - maxRangeStart;
			} else {
				fTotalDrawRange.offset= maxRangeStart;
				fTotalDrawRange.length= maxRangeEnd - maxRangeStart;
				fCurrentDrawRange.offset=drawRangeStart;
				fCurrentDrawRange.length= drawRangeEnd - drawRangeStart;
			}
		} else {
			if (isWorldChange) {
				fCurrentDrawRange= fTotalDrawRange;
				fTotalDrawRange= null;
			} else {
				fCurrentDrawRange= null;
			}
		}

		adaptToDocumentLength(fCurrentDrawRange);
		adaptToDocumentLength(fTotalDrawRange);
	}

	/**
	 * Adapts the given position to the document length.
	 *
	 * @param position the position to adapt
	 * @since 3.0
	 */
	private void adaptToDocumentLength(Position position) {
		if (position == null)
			return;

		int length= fSourceViewer.getDocument().getLength();
		position.offset= Math.min(position.offset, length);
		position.length= Math.min(position.length, length - position.offset);
	}

	/**
	 * Returns a decoration for the given annotation if this
	 * annotation is valid and shown by this painter.
	 *
	 * @param annotation 			the annotation
	 * @param decoration 			the decoration to be adapted and returned or <code>null</code> if a new one must be created
	 * @return the decoration or <code>null</code> if there's no valid one
	 * @since 3.0
	 */
	private Decoration getDecoration(Annotation annotation, Decoration decoration) {

		if (annotation.isMarkedDeleted())
			return null;

		String type= annotation.getType();

		Object paintingStrategy= getPaintingStrategy(type);
		if (paintingStrategy == null || paintingStrategy instanceof NullStrategy)
			return null;

		Color color= getColor(type);
		if (color == null)
			return null;

		Position position= fModel.getPosition(annotation);
		if (position == null || position.isDeleted())
			return null;

		if (decoration == null)
			decoration= new Decoration();

		decoration.fPosition= position;
		decoration.fColor= color;
		if (fAnnotationAccess instanceof IAnnotationAccessExtension) {
			IAnnotationAccessExtension extension= (IAnnotationAccessExtension) fAnnotationAccess;
			decoration.fLayer= extension.getLayer(annotation);
		} else {
			decoration.fLayer= IAnnotationAccessExtension.DEFAULT_LAYER;
		}

		decoration.fPaintingStrategy= paintingStrategy;

		return decoration;
	}

	/**
	 * Returns the painting strategy for the given annotation.
	 *
	 * @param type the annotation type
	 * @return the annotation painter
	 * @since 3.0
	 */
	private Object getPaintingStrategy(final String type) {
		Object strategy= fCachedAnnotationType2PaintingStrategy.get(type);
		if (strategy != null)
			return strategy;

		strategy= fPaintingStrategyId2PaintingStrategy.get(fAnnotationType2PaintingStrategyId.get(type));
		if (strategy != null) {
			fCachedAnnotationType2PaintingStrategy.put(type, strategy);
			return strategy;
		}

		if (fAnnotationAccess instanceof IAnnotationAccessExtension) {
			IAnnotationAccessExtension ext = (IAnnotationAccessExtension) fAnnotationAccess;
			Object[] sts = ext.getSupertypes(type);
			for (int i= 0; i < sts.length; i++) {
				strategy= fPaintingStrategyId2PaintingStrategy.get(fAnnotationType2PaintingStrategyId.get(sts[i]));
				if (strategy != null) {
					fCachedAnnotationType2PaintingStrategy.put(type, strategy);
					return strategy;
				}
			}
		}

		fCachedAnnotationType2PaintingStrategy.put(type, NULL_STRATEGY);
		return null;

	}

	/**
	 * Returns the color for the given annotation type
	 *
	 * @param annotationType the annotation type
	 * @return the color
	 * @since 3.0
	 */
	private Color getColor(final Object annotationType) {
		Color color= fCachedAnnotationType2Color.get(annotationType);
		if (color != null)
			return color;

		color= fAnnotationType2Color.get(annotationType);
		if (color != null) {
			fCachedAnnotationType2Color.put(annotationType, color);
			return color;
		}

		if (fAnnotationAccess instanceof IAnnotationAccessExtension) {
			IAnnotationAccessExtension extension= (IAnnotationAccessExtension) fAnnotationAccess;
			Object[] superTypes= extension.getSupertypes(annotationType);
			if (superTypes != null) {
				for (int i= 0; i < superTypes.length; i++) {
					color= fAnnotationType2Color.get(superTypes[i]);
					if (color != null) {
						fCachedAnnotationType2Color.put(annotationType, color);
						return color;
					}
				}
			}
		}

		return null;
	}

	/**
	 * Recomputes the squiggles to be drawn and redraws them.
	 *
	 * @param event the annotation model event
	 * @since 3.0
	 */
	private void updatePainting(AnnotationModelEvent event) {
		disablePainting(event == null);

		catchupWithModel(event);

		if (!fInputDocumentAboutToBeChanged)
			invalidateTextPresentation();

		enablePainting();
	}

	private void invalidateTextPresentation() {
		IRegion r= null;
		synchronized (fHighlightedDecorationsMapLock) {
		    if (fCurrentHighlightAnnotationRange != null)
		    	r= new Region(fCurrentHighlightAnnotationRange.getOffset(), fCurrentHighlightAnnotationRange.getLength());
		}
		if (r == null)
			return;

		if (fSourceViewer instanceof ITextViewerExtension2) {
			if (DEBUG)
				System.out.println("AP: invalidating offset: " + r.getOffset() + ", length= " + r.getLength()); //$NON-NLS-1$ //$NON-NLS-2$

			((ITextViewerExtension2)fSourceViewer).invalidateTextPresentation(r.getOffset(), r.getLength());

		} else {
			fSourceViewer.invalidateTextPresentation();
		}
	}

	@Override
	public void applyTextPresentation(TextPresentation tp) {
		Set<Entry<Annotation, Decoration>> decorations;

		synchronized (fHighlightedDecorationsMapLock) {
			if (fHighlightedDecorationsMap == null || fHighlightedDecorationsMap.isEmpty())
				return;

			decorations= new HashSet<>(fHighlightedDecorationsMap.entrySet());
		}

		IRegion region= tp.getExtent();

		if (DEBUG)
			System.out.println("AP: applying text presentation offset: " + region.getOffset() + ", length= " + region.getLength()); //$NON-NLS-1$ //$NON-NLS-2$

		for (int layer= 0, maxLayer= 1;	layer < maxLayer; layer++) {

			for (Iterator<Entry<Annotation, Decoration>> iter= decorations.iterator(); iter.hasNext();) {
				Entry<Annotation, Decoration> entry= iter.next();

				Annotation a= entry.getKey();
				if (a.isMarkedDeleted())
					continue;

				Decoration pp = entry.getValue();

				maxLayer= Math.max(maxLayer, pp.fLayer + 1); // dynamically update layer maximum
				if (pp.fLayer != layer)	// wrong layer: skip annotation
					continue;

				Position p= pp.fPosition;
				if (fSourceViewer instanceof ITextViewerExtension5) {
					ITextViewerExtension5 extension3= (ITextViewerExtension5) fSourceViewer;
					if (null == extension3.modelRange2WidgetRange(new Region(p.getOffset(), p.getLength())))
						continue;
				} else if (!fSourceViewer.overlapsWithVisibleRegion(p.offset, p.length)) {
					continue;
				}

				int regionEnd= region.getOffset() + region.getLength();
				int pEnd= p.getOffset() + p.getLength();
				if (pEnd >= region.getOffset() && regionEnd > p.getOffset()) {
					int start= Math.max(p.getOffset(), region.getOffset());
					int end= Math.min(regionEnd, pEnd);
					int length= Math.max(end - start, 0);
					StyleRange styleRange= new StyleRange(start, length, null, null);
					((ITextStyleStrategy)pp.fPaintingStrategy).applyTextStyle(styleRange, pp.fColor);
					tp.mergeStyleRange(styleRange);
				}
			}
		}
	}

	@Override
	public synchronized void modelChanged(final IAnnotationModel model) {
		if (DEBUG)
			System.err.println("AP: OLD API of AnnotationModelListener called"); //$NON-NLS-1$

		modelChanged(new AnnotationModelEvent(model));
	}

	@Override
	public void modelChanged(final AnnotationModelEvent event) {
		Display textWidgetDisplay;
		try {
			StyledText textWidget= fTextWidget;
			if (textWidget == null || textWidget.isDisposed())
				return;
			textWidgetDisplay= textWidget.getDisplay();
		} catch (SWTException ex) {
			if (ex.code == SWT.ERROR_WIDGET_DISPOSED)
				return;
			throw ex;
		}

		if (fIsSettingModel) {
			// inside the UI thread -> no need for posting
			if (textWidgetDisplay == Display.getCurrent())
				updatePainting(event);
			else {
				/*
				 * we can throw away the changes since
				 * further update painting will happen
				 */
				return;
			}
		} else {
			if (DEBUG && event != null && event.isWorldChange()) {
				System.out.println("AP: WORLD CHANGED, stack trace follows:"); //$NON-NLS-1$
				new Throwable().printStackTrace(System.out);
			}

			// XXX: posting here is a problem for annotations that are being
			// removed and the positions of which are not updated to document
			// changes any more. If the document gets modified between
			// now and running the posted runnable, the position information
			// is not accurate any longer.
			textWidgetDisplay.asyncExec(new Runnable() {
				@Override
				public void run() {
					if (fTextWidget != null && !fTextWidget.isDisposed())
						updatePainting(event);
				}
			});
		}
	}

	/**
	 * Sets the color in which the squiggly for the given annotation type should be drawn.
	 *
	 * @param annotationType the annotation type
	 * @param color the color
	 */
	public void setAnnotationTypeColor(Object annotationType, Color color) {
		if (color != null)
			fAnnotationType2Color.put(annotationType, color);
		else
			fAnnotationType2Color.remove(annotationType);
		fCachedAnnotationType2Color.clear();
	}

	/**
	 * Adds the given annotation type to the list of annotation types whose annotations should be
	 * painted by this painter using squiggly drawing. If the annotation type is already in this
	 * list, this method is without effect.
	 * 
	 * @param annotationType the annotation type
	 * @deprecated As of 3.4 replaced by
	 *             {@link #addTextStyleStrategy(Object, AnnotationPainter.ITextStyleStrategy)} and
	 *             {@link UnderlineStrategy}
	 */
	@Deprecated
	public void addAnnotationType(Object annotationType) {
		addAnnotationType(annotationType, SQUIGGLES);
	}

	/**
	 * Adds the given annotation type to the list of annotation types whose annotations should be
	 * painted by this painter using the given strategy. If the annotation type is already in this
	 * list, the old strategy gets replaced.
	 * 
	 * @param annotationType the annotation type
	 * @param strategyID the id of the drawing or text style strategy that should be used for this
	 *            annotation type
	 * @since 3.0
	 */
	public void addAnnotationType(Object annotationType, Object strategyID) {
		fAnnotationType2PaintingStrategyId.put(annotationType, strategyID);
		fCachedAnnotationType2PaintingStrategy.clear();

		if (fTextInputListener == null) {
			fTextInputListener= new ITextInputListener() {

				@Override
				public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
					fInputDocumentAboutToBeChanged= true;
				}

				@Override
				public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
					fInputDocumentAboutToBeChanged= false;
				}
			};
			fSourceViewer.addTextInputListener(fTextInputListener);
		}

	}

	/**
	 * Registers a new drawing strategy under the given ID. If there is already a
	 * strategy registered under <code>id</code>, the old strategy gets replaced.
	 * <p>The given id can be referenced when adding annotation types, see
	 * {@link #addAnnotationType(Object, Object)}.</p>
	 *
	 * @param id the identifier under which the strategy can be referenced, not <code>null</code>
	 * @param strategy the new strategy
	 * @since 3.0
	 */
	public void addDrawingStrategy(Object id, IDrawingStrategy strategy) {
		// don't permit null as null is used to signal that an annotation type is not
		// registered with a specific strategy, and that its annotation hierarchy should be searched
		if (id == null)
			throw new IllegalArgumentException();
		fPaintingStrategyId2PaintingStrategy.put(id, strategy);
		fCachedAnnotationType2PaintingStrategy.clear();
	}

	/**
	 * Registers a new drawing strategy under the given ID. If there is already
	 * a strategy registered under <code>id</code>, the old strategy gets
	 * replaced.
	 * <p>
	 * The given id can be referenced when adding annotation types, see
	 * {@link #addAnnotationType(Object, Object)}.</p>
	 * <p>
	 * <strong>Note:</strong> The annotations will only be painted if this
	 * painter has been registered as text presentation listener on the viewer.</p>
	 *
	 * @param id the identifier under which the strategy can be referenced, not <code>null</code>
	 * @param strategy the new strategy
	 * @see ITextViewerExtension4#addTextPresentationListener(ITextPresentationListener)
	 * @since 3.4
	 */
	public void addTextStyleStrategy(Object id, ITextStyleStrategy strategy) {
		// don't permit null as null is used to signal that an annotation type is not
		// registered with a specific strategy, and that its annotation hierarchy should be searched
		if (id == null)
			throw new IllegalArgumentException();
		fPaintingStrategyId2PaintingStrategy.put(id, strategy);
		fCachedAnnotationType2PaintingStrategy.clear();
	}

	/**
	 * Adds the given annotation type to the list of annotation types whose
	 * annotations should be highlighted this painter. If the annotation  type
	 * is already in this list, this method is without effect.
	 * <p>
	 * <strong>Note:</strong> The annotations will only be painted if this
	 * painter has been registered as text presentation listener on the viewer.</p>
	 *
	 * @param annotationType the annotation type
	 * @see ITextViewerExtension4#addTextPresentationListener(ITextPresentationListener)
	 * @since 3.0
	 */
	public void addHighlightAnnotationType(Object annotationType) {
		addAnnotationType(annotationType, HIGHLIGHTING);
	}

	/**
	 * Removes the given annotation type from the list of annotation types whose
	 * annotations are painted by this painter. If the annotation type is not
	 * in this list, this method is without effect.
	 *
	 * @param annotationType the annotation type
	 */
	public void removeAnnotationType(Object annotationType) {
		fCachedAnnotationType2PaintingStrategy.clear();
		fAnnotationType2PaintingStrategyId.remove(annotationType);
		if (fAnnotationType2PaintingStrategyId.isEmpty() && fTextInputListener != null) {
			fSourceViewer.removeTextInputListener(fTextInputListener);
			fTextInputListener= null;
			fInputDocumentAboutToBeChanged= false;
		}
	}

	/**
	 * Removes the given annotation type from the list of annotation types whose
	 * annotations are highlighted by this painter. If the annotation type is not
	 * in this list, this method is without effect.
	 *
	 * @param annotationType the annotation type
	 * @since 3.0
	 */
	public void removeHighlightAnnotationType(Object annotationType) {
		removeAnnotationType(annotationType);
	}

	/**
	 * Clears the list of annotation types whose annotations are
	 * painted by this painter.
	 */
	public void removeAllAnnotationTypes() {
		fCachedAnnotationType2PaintingStrategy.clear();
		fAnnotationType2PaintingStrategyId.clear();
		if (fTextInputListener != null) {
			fSourceViewer.removeTextInputListener(fTextInputListener);
			fTextInputListener= null;
		}
	}

	/**
	 * Returns whether the list of annotation types whose annotations are painted
	 * by this painter contains at least on element.
	 *
	 * @return <code>true</code> if there is an annotation type whose annotations are painted
	 */
	public boolean isPaintingAnnotations() {
		return !fAnnotationType2PaintingStrategyId.isEmpty();
	}

	@Override
	public void dispose() {

		if (fAnnotationType2Color != null) {
			fAnnotationType2Color.clear();
			fAnnotationType2Color= null;
		}

		if (fCachedAnnotationType2Color != null) {
			fCachedAnnotationType2Color.clear();
			fCachedAnnotationType2Color= null;
		}

		if (fCachedAnnotationType2PaintingStrategy != null) {
			fCachedAnnotationType2PaintingStrategy.clear();
			fCachedAnnotationType2PaintingStrategy= null;
		}

		if (fAnnotationType2PaintingStrategyId != null) {
			fAnnotationType2PaintingStrategyId.clear();
			fAnnotationType2PaintingStrategyId= null;
		}

		fTextWidget= null;
		fSourceViewer= null;
		fAnnotationAccess= null;
		fModel= null;
		synchronized (fDecorationMapLock) {
			fDecorationsMap= null;
		}
		synchronized (fHighlightedDecorationsMapLock) {
			fHighlightedDecorationsMap= null;
		}
	}

	/**
	 * Returns the document offset of the upper left corner of the source viewer's view port,
	 * possibly including partially visible lines.
	 *
	 * @return the document offset if the upper left corner of the view port
	 */
	private int getInclusiveTopIndexStartOffset() {

		if (fTextWidget != null && !fTextWidget.isDisposed()) {
			int top= JFaceTextUtil.getPartialTopIndex(fSourceViewer);
			try {
				IDocument document= fSourceViewer.getDocument();
				return document.getLineOffset(top);
			} catch (BadLocationException x) {
			}
		}

		return -1;
	}

	/**
	 * Returns the first invisible document offset of the lower right corner of the source viewer's view port,
	 * possibly including partially visible lines.
	 *
	 * @return the first invisible document offset of the lower right corner of the view port
	 */
	private int getExclusiveBottomIndexEndOffset() {

		if (fTextWidget != null && !fTextWidget.isDisposed()) {
			int bottom= JFaceTextUtil.getPartialBottomIndex(fSourceViewer);
			try {
				IDocument document= fSourceViewer.getDocument();

				if (bottom >= document.getNumberOfLines())
					bottom= document.getNumberOfLines() - 1;

				return document.getLineOffset(bottom) + document.getLineLength(bottom);
			} catch (BadLocationException x) {
			}
		}

		return -1;
	}

	@Override
	public void paintControl(PaintEvent event) {
		if (fTextWidget != null)
			handleDrawRequest(event);
	}

	/**
	 * Handles the request to draw the annotations using the given graphical context.
	 *
	 * @param event the paint event or <code>null</code>
	 */
	private void handleDrawRequest(PaintEvent event) {

		if (fTextWidget == null) {
			// is already disposed
			return;
		}

		IRegion clippingRegion= computeClippingRegion(event, false);
		if (clippingRegion == null)
			return;

		int vOffset= clippingRegion.getOffset();
		int vLength= clippingRegion.getLength();

		final GC gc= event != null ? event.gc : null;

		// Clone decorations
		Collection<Entry<Annotation, Decoration>> decorations;
		synchronized (fDecorationMapLock) {
			decorations= new ArrayList<>(fDecorationsMap.size());
			decorations.addAll(fDecorationsMap.entrySet());
		}

		/*
		 * Create a new list of annotations to be drawn, since removing from decorations is more
		 * expensive. One bucket per drawing layer. Use linked lists as addition is cheap here.
		 */
		ArrayList<LinkedList<Entry<Annotation, Decoration>>> toBeDrawn= new ArrayList<>(10);
		for (Iterator<Entry<Annotation, Decoration>> e = decorations.iterator(); e.hasNext();) {
			Entry<Annotation, Decoration> entry= e.next();

			Annotation a= entry.getKey();
			Decoration pp = entry.getValue();
			// prune any annotation that is not drawable or does not need drawing
			if (!(a.isMarkedDeleted() || skip(a) || !regionsTouchOrOverlap(pp.fPosition.getOffset(), pp.fPosition.getLength(), vOffset, vLength))) {
				// ensure sized appropriately
				for (int i= toBeDrawn.size(); i <= pp.fLayer; i++)
					toBeDrawn.add(new LinkedList<>());
				toBeDrawn.get(pp.fLayer).add(entry);
			}
		}
		IDocument document= fSourceViewer.getDocument();
		for (Iterator<LinkedList<Entry<Annotation, Decoration>>> it= toBeDrawn.iterator(); it.hasNext();) {
			LinkedList<Entry<Annotation, Decoration>> layer= it.next();
			for (Iterator<Entry<Annotation, Decoration>> e = layer.iterator(); e.hasNext();) {
				Entry<Annotation, Decoration> entry= e.next();
				Annotation a= entry.getKey();
				Decoration pp = entry.getValue();
				drawDecoration(pp, gc, a, clippingRegion, document);
			}
		}
	}

	private void drawDecoration(Decoration pp, GC gc, Annotation annotation, IRegion clippingRegion, IDocument document) {
		if (clippingRegion == null)
			return;

		if (!(pp.fPaintingStrategy instanceof IDrawingStrategy))
			return;

		IDrawingStrategy drawingStrategy= (IDrawingStrategy)pp.fPaintingStrategy;

		int clippingOffset= clippingRegion.getOffset();
		int clippingLength= clippingRegion.getLength();

		Position p= pp.fPosition;
		try {

			int startLine= document.getLineOfOffset(p.getOffset());
			int lastInclusive= Math.max(p.getOffset(), p.getOffset() + p.getLength() - 1);
			int endLine= document.getLineOfOffset(lastInclusive);

			for (int i= startLine; i <= endLine; i++) {
				int lineOffset= document.getLineOffset(i);
				int paintStart= Math.max(lineOffset, p.getOffset());
				String lineDelimiter= document.getLineDelimiter(i);
				int delimiterLength= lineDelimiter != null ? lineDelimiter.length() : 0;
				int paintLength= Math.min(lineOffset + document.getLineLength(i) - delimiterLength, p.getOffset() + p.getLength()) - paintStart;
				if (paintLength >= 0 && regionsTouchOrOverlap(paintStart, paintLength, clippingOffset, clippingLength)) {
					// otherwise inside a line delimiter
					IRegion widgetRange= getWidgetRange(paintStart, paintLength);
					if (widgetRange != null) {
						drawingStrategy.draw(annotation, gc, fTextWidget, widgetRange.getOffset(), widgetRange.getLength(), pp.fColor);
					}
				}
			}

		} catch (BadLocationException x) {
		}
	}

	/**
	 * Computes the model (document) region that is covered by the paint event's clipping region. If
	 * <code>event</code> is <code>null</code>, the model range covered by the visible editor
	 * area (viewport) is returned.
	 *
	 * @param event the paint event or <code>null</code> to use the entire viewport
	 * @param isClearing tells whether the clipping is need for clearing an annotation
	 * @return the model region comprised by either the paint event's clipping region or the
	 *         viewport
	 * @since 3.2
	 */
	private IRegion computeClippingRegion(PaintEvent event, boolean isClearing) {
		if (event == null) {

			if (!isClearing && fCurrentDrawRange != null)
				return new Region(fCurrentDrawRange.offset, fCurrentDrawRange.length);

			// trigger a repaint of the entire viewport
			int vOffset= getInclusiveTopIndexStartOffset();
			if (vOffset == -1)
				return null;

			// http://bugs.eclipse.org/bugs/show_bug.cgi?id=17147
			int vLength= getExclusiveBottomIndexEndOffset() - vOffset;

			return new Region(vOffset, vLength);
		}

		int widgetOffset;
		try {
			int widgetClippingStartOffset= fTextWidget.getOffsetAtLocation(new Point(0, event.y));
			int firstWidgetLine= fTextWidget.getLineAtOffset(widgetClippingStartOffset);
			widgetOffset= fTextWidget.getOffsetAtLine(firstWidgetLine);
		} catch (IllegalArgumentException ex1) {
			try {
				int firstVisibleLine= JFaceTextUtil.getPartialTopIndex(fTextWidget);
				widgetOffset= fTextWidget.getOffsetAtLine(firstVisibleLine);
			} catch (IllegalArgumentException ex2) { // above try code might fail too
				widgetOffset= 0;
			}
		}

		int widgetEndOffset;
		try {
			int widgetClippingEndOffset= fTextWidget.getOffsetAtLocation(new Point(0, event.y + event.height));
			int lastWidgetLine= fTextWidget.getLineAtOffset(widgetClippingEndOffset);
			widgetEndOffset= fTextWidget.getOffsetAtLine(lastWidgetLine + 1);
		} catch (IllegalArgumentException ex1) {
			// happens if the editor is not "full", e.g. the last line of the document is visible in the editor
			try {
				int lastVisibleLine= JFaceTextUtil.getPartialBottomIndex(fTextWidget);
				if (lastVisibleLine == fTextWidget.getLineCount() - 1)
					// last line
					widgetEndOffset= fTextWidget.getCharCount();
				else
					widgetEndOffset= fTextWidget.getOffsetAtLine(lastVisibleLine + 1) - 1;
			} catch (IllegalArgumentException ex2) { // above try code might fail too
				widgetEndOffset= fTextWidget.getCharCount();
			}
		}

		IRegion clippingRegion= getModelRange(widgetOffset, widgetEndOffset - widgetOffset);

		return clippingRegion;
	}

	/**
	 * Should the given annotation be skipped when handling draw requests?
	 *
	 * @param annotation the annotation
	 * @return <code>true</code> iff the given annotation should be
	 *         skipped when handling draw requests
	 * @since 3.0
	 */
	protected boolean skip(Annotation annotation) {
		return false;
	}

	/**
	 * Returns the widget region that corresponds to the
	 * given offset and length in the viewer's document.
	 * 
	 * The returned object can be the fReusableRegion and may used
	 * only to read the return values and must not used to store
	 * the region.
	 *
	 * @param modelOffset the model offset
	 * @param modelLength the model length
	 * @return the corresponding widget region
	 */
	private IRegion getWidgetRange(int modelOffset, int modelLength) {
		if (modelOffset == Integer.MAX_VALUE)
			return null;

		if (fSourceViewer instanceof ITextViewerExtension5) {
			ITextViewerExtension5 extension= (ITextViewerExtension5) fSourceViewer;
			fReusableRegion.setOffset(modelOffset);
			fReusableRegion.setLength(modelLength);
			return extension.modelRange2WidgetRange(fReusableRegion);
		}

		IRegion region= fSourceViewer.getVisibleRegion();
		int offset= region.getOffset();
		int length= region.getLength();

		if (regionsTouchOrOverlap(modelOffset, modelLength, offset, length)) {
			int p1= Math.max(offset, modelOffset);
			int p2= Math.min(offset + length, modelOffset + modelLength);
			fReusableRegion.setOffset(p1 - offset);
			fReusableRegion.setLength(p2 - p1);
			return fReusableRegion;
		}
		return null;
	}

	/**
	 * Returns the model region that corresponds to the given region in the
	 * viewer's text widget.
	 *
	 * @param offset the offset in the viewer's widget
	 * @param length the length in the viewer's widget
	 * @return the corresponding document region
	 * @since 3.2
	 */
	private IRegion getModelRange(int offset, int length) {
		if (offset == Integer.MAX_VALUE)
			return null;

		if (fSourceViewer instanceof ITextViewerExtension5) {
			ITextViewerExtension5 extension= (ITextViewerExtension5) fSourceViewer;
			return extension.widgetRange2ModelRange(new Region(offset, length));
		}

		IRegion region= fSourceViewer.getVisibleRegion();
		return new Region(region.getOffset() + offset, length);
	}

	/**
	 * Checks whether the two given text regions touch or overlap each other.
	 *
	 * @param offset1 offset of the first region
	 * @param length1 length of the first region
	 * @param offset2 offset of the second region
	 * @param length2 length of the second region
	 * @return <code>true</code> if the regions touch or overlap
	 */
	private boolean regionsTouchOrOverlap(int offset1, int length1, int offset2, int length2) {
		return (offset1 <= offset2+length2) && (offset2 <= offset1+length1);
	}

	@Override
	public void deactivate(boolean redraw) {
		if (fIsActive) {
			fIsActive= false;
			disablePainting(redraw);
			setModel(null);
			catchupWithModel(null);
		}
	}

	/**
	 * Returns whether the given reason causes a repaint.
	 *
	 * @param reason the reason
	 * @return <code>true</code> if repaint reason, <code>false</code> otherwise
	 * @since 3.0
	 */
	protected boolean isRepaintReason(int reason) {
		return CONFIGURATION == reason || INTERNAL == reason;
	}

	/**
     * Retrieves the annotation model from the given source viewer.
     *
     * @param sourceViewer the source viewer
     * @return the source viewer's annotation model or <code>null</code> if none can be found
	 * @since 3.0
	 */
	protected IAnnotationModel findAnnotationModel(ISourceViewer sourceViewer) {
		if(sourceViewer != null)
			return sourceViewer.getAnnotationModel();
		return null;
	}

	@Override
	public void paint(int reason) {
		if (fSourceViewer.getDocument() == null) {
			deactivate(false);
			return;
		}

		if (!fIsActive) {
			IAnnotationModel model= findAnnotationModel(fSourceViewer);
			if (model != null) {
				fIsActive= true;
				setModel(model);
			}
		} else if (isRepaintReason(reason))
			updatePainting(null);
	}

	@Override
	public void setPositionManager(IPaintPositionManager manager) {
	}
}
