<commit_before>/*******************************************************************************
 * Copyright (c) 2010-2014 ITER Organization.
 * 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
 ******************************************************************************/
package org.csstudio.swt.widgets.symbol;

import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;

import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
import org.apache.batik.util.XMLResourceDescriptor;
import org.csstudio.swt.widgets.Activator;
import org.csstudio.swt.widgets.util.AbstractInputStreamRunnable;
import org.csstudio.swt.widgets.util.IJobErrorHandler;
import org.csstudio.swt.widgets.util.ResourceUtil;
import org.csstudio.utility.batik.SVGUtils;
import org.csstudio.utility.batik.SimpleImageTranscoder;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.w3c.dom.Document;

public class SVGSymbolImage extends AbstractSymbolImage {

	private Dimension imgDimension = null;

	private boolean loadingImage = false;
	private boolean failedToLoadDocument = false;
	private SimpleImageTranscoder transcoder;
	private Document svgDocument;

	public SVGSymbolImage(SymbolImageProperties sip, boolean runMode) {
		super(sip, runMode);
	}

	// ************************************************************
	// Image color & paint
	// ************************************************************

	public synchronized void paintFigure(final Graphics gfx) {
		if (loadingImage || originalImageData == null)
			return;
		// Generate Data
		if (imageData == null) {
			dispose();
			generateSVGData();
		}
		// Create image
		if (image == null) {
			if (imageData == null)
				return;
			image = new Image(Display.getDefault(), imageData);
		}
		// Calculate areas
		if (bounds == null || imgDimension == null)
			return;
		int cropedWidth = imageData.width - (int) Math.round(scale * (leftCrop + rightCrop));
		int cropedHeight = imageData.height - (int) Math.round(scale * (bottomCrop + topCrop));
		Rectangle srcArea = new Rectangle(leftCrop, topCrop, cropedWidth, cropedHeight);
		Rectangle destArea = new Rectangle(bounds.x, bounds.y, imgDimension.width, imgDimension.height);
		if (backgroundColor != null) {
			gfx.setBackgroundColor(backgroundColor);
			gfx.fillRectangle(destArea);
		}
		// Draw graphic image
		if (image != null) {
			gfx.drawImage(image, srcArea, destArea);
		}
	}

	@Override
	public void resetData() {
		imageData = null;
	}

	private void generateSVGData() {
		// Load document if do not exist
		Document document = getDocument();
		if (document == null) {
			return;
		}
		transcoder.setColorToChange(colorToChange);
		if (!isEditMode() && !colorToChange.equals(currentColor))
			transcoder.setColor(currentColor);
		if (permutationMatrix != null)
			transcoder.setTransformMatrix(permutationMatrix.getMatrix());

		// Scale image
		java.awt.Dimension dims = transcoder.getDocumentSize();
		int imgWidth = dims.width;
		int imgHeight = dims.height;
		if (stretch) {
			if (bounds != null && !bounds.equals(0, 0, 0, 0)) {
				imgWidth = bounds.width;
				imgHeight = bounds.height;
			}
		}
		// Avoid negative number
		topCrop = topCrop > imgHeight ? 0 : topCrop;
		leftCrop = leftCrop > imgWidth ? 0 : leftCrop;
		bottomCrop = (imgHeight - topCrop - bottomCrop) < 0 ? 0 : bottomCrop;
		rightCrop = (imgWidth - leftCrop - rightCrop) < 0 ? 0 : rightCrop;
		imgWidth = (int) Math.round(scale * (imgWidth + leftCrop + rightCrop));
		imgHeight = (int) Math.round(scale * (imgHeight + bottomCrop + topCrop));
		transcoder.setCanvasSize(imgWidth, imgHeight);

		BufferedImage awtImage = transcoder.getBufferedImage();
		if (awtImage != null) {
			imageData = SVGUtils.toSWT(Display.getCurrent(), awtImage);
		}

		// Calculate areas
		int cropedWidth = imgWidth - (int) Math.round(scale * (leftCrop + rightCrop));
		int cropedHeight = imgHeight - (int) Math.round(scale * (bottomCrop + topCrop));

		Dimension newImgDimension = new Dimension((int) Math.round(cropedWidth / scale), 
				(int) Math.round(cropedHeight / scale));
		if (imgDimension == null || newImgDimension.width != imgDimension.width
				|| newImgDimension.height != imgDimension.height)
			fireSizeChanged();
		imgDimension = newImgDimension;
	}

	// ************************************************************
	// Image size calculation
	// ************************************************************

	@Override
	public void setAbsoluteScale(double newScale) {
		super.setAbsoluteScale(newScale);
		resizeImage();
	}

	public synchronized Dimension getAutoSizedDimension() {
		// if (imgDimension == null)
		// generateSVGData();
		return imgDimension;
	}
<commit_msg>Bugfix: Do not rescale the image on every paint attempt. It consumes a lot of CPU cycles and memory.<commit_after>/*******************************************************************************
 * Copyright (c) 2010-2014 ITER Organization.
 * 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
 ******************************************************************************/
package org.csstudio.swt.widgets.symbol;

import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;

import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
import org.apache.batik.util.XMLResourceDescriptor;
import org.csstudio.swt.widgets.Activator;
import org.csstudio.swt.widgets.util.AbstractInputStreamRunnable;
import org.csstudio.swt.widgets.util.IJobErrorHandler;
import org.csstudio.swt.widgets.util.ResourceUtil;
import org.csstudio.utility.batik.SVGUtils;
import org.csstudio.utility.batik.SimpleImageTranscoder;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.w3c.dom.Document;

public class SVGSymbolImage extends AbstractSymbolImage {

	private Dimension imgDimension = null;

	private boolean loadingImage = false;
	private boolean failedToLoadDocument = false;
	private SimpleImageTranscoder transcoder;
	private Document svgDocument;

	public SVGSymbolImage(SymbolImageProperties sip, boolean runMode) {
		super(sip, runMode);
	}

	// ************************************************************
	// Image color & paint
	// ************************************************************

	public synchronized void paintFigure(final Graphics gfx) {
		if (loadingImage || originalImageData == null)
			return;
		// Generate Data
		if (imageData == null) {
			dispose();
			generateSVGData();
		}
		// Create image
		if (image == null) {
			if (imageData == null)
				return;
			image = new Image(Display.getDefault(), imageData);
		}
		// Calculate areas
		if (bounds == null || imgDimension == null)
			return;
		int cropedWidth = imageData.width - (int) Math.round(scale * (leftCrop + rightCrop));
		int cropedHeight = imageData.height - (int) Math.round(scale * (bottomCrop + topCrop));
		Rectangle srcArea = new Rectangle(leftCrop, topCrop, cropedWidth, cropedHeight);
		Rectangle destArea = new Rectangle(bounds.x, bounds.y, imgDimension.width, imgDimension.height);
		if (backgroundColor != null) {
			gfx.setBackgroundColor(backgroundColor);
			gfx.fillRectangle(destArea);
		}
		// Draw graphic image
		if (image != null) {
			gfx.drawImage(image, srcArea, destArea);
		}
	}

	@Override
	public void resetData() {
		imageData = null;
	}

	private void generateSVGData() {
		// Load document if do not exist
		Document document = getDocument();
		if (document == null) {
			return;
		}
		transcoder.setColorToChange(colorToChange);
		if (!isEditMode() && !colorToChange.equals(currentColor))
			transcoder.setColor(currentColor);
		if (permutationMatrix != null)
			transcoder.setTransformMatrix(permutationMatrix.getMatrix());

		// Scale image
		java.awt.Dimension dims = transcoder.getDocumentSize();
		int imgWidth = dims.width;
		int imgHeight = dims.height;
		if (stretch) {
			if (bounds != null && !bounds.equals(0, 0, 0, 0)) {
				imgWidth = bounds.width;
				imgHeight = bounds.height;
			}
		}
		// Avoid negative number
		topCrop = topCrop > imgHeight ? 0 : topCrop;
		leftCrop = leftCrop > imgWidth ? 0 : leftCrop;
		bottomCrop = (imgHeight - topCrop - bottomCrop) < 0 ? 0 : bottomCrop;
		rightCrop = (imgWidth - leftCrop - rightCrop) < 0 ? 0 : rightCrop;
		imgWidth = (int) Math.round(scale * (imgWidth + leftCrop + rightCrop));
		imgHeight = (int) Math.round(scale * (imgHeight + bottomCrop + topCrop));
		transcoder.setCanvasSize(imgWidth, imgHeight);

		BufferedImage awtImage = transcoder.getBufferedImage();
		if (awtImage != null) {
			imageData = SVGUtils.toSWT(Display.getCurrent(), awtImage);
		}

		// Calculate areas
		int cropedWidth = imgWidth - (int) Math.round(scale * (leftCrop + rightCrop));
		int cropedHeight = imgHeight - (int) Math.round(scale * (bottomCrop + topCrop));

		Dimension newImgDimension = new Dimension((int) Math.round(cropedWidth / scale), 
				(int) Math.round(cropedHeight / scale));
		if (imgDimension == null || newImgDimension.width != imgDimension.width
				|| newImgDimension.height != imgDimension.height)
			fireSizeChanged();
		imgDimension = newImgDimension;
	}

	// ************************************************************
	// Image size calculation
	// ************************************************************

	@Override
	public void setAbsoluteScale(double newScale) {
		double oldScale = scale;
		super.setAbsoluteScale(newScale);
		if (oldScale != newScale) 
		    resizeImage();
	}

	public synchronized Dimension getAutoSizedDimension() {
		// if (imgDimension == null)
		// generateSVGData();
		return imgDimension;
	}

{'fraction_non_alphanumeric': 0.18193057536852117, 'fraction_numerical': 0.004945316214931051, 'mean_word_length': 4.721436343852013, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7064966', 'n_tokens_mistral': 3434, 'n_tokens_neox': 3162, 'n_words': 732}