double widthsquared; if ((transform.getType() & NON_UNIFORM_SCALE_MASK) == 0) { /* sqrt omitted, compare to squared limits below. */ widthsquared = Math.abs(transform.getDeterminant()); } else { /* First calculate the "maximum scale" of this transform. */ double A = transform.getScaleX(); // m00 double C = transform.getShearX(); // m01 double B = transform.getShearY(); // m10 double D = transform.getScaleY(); // m11 /* * Given a 2 x 2 affine matrix [ A B ] such that * [ C D ] * v' = [x' y'] = [Ax + Cy, Bx + Dy], we want to * find the maximum magnitude (norm) of the vector v' * with the constraint (x^2 + y^2 = 1). * The equation to maximize is * |v'| = sqrt((Ax+Cy)^2+(Bx+Dy)^2) * or |v'| = sqrt((AA+BB)x^2 + 2(AC+BD)xy + (CC+DD)y^2). * Since sqrt is monotonic we can maximize |v'|^2 * instead and plug in the substitution y = sqrt(1 - x^2). * Trigonometric equalities can then be used to get * rid of most of the sqrt terms. */ double EA = A*A + B*B; // x^2 coefficient double EB = 2*(A*C + B*D); // xy coefficient double EC = C*C + D*D; // y^2 coefficient /* * There is a lot of calculus omitted here. * * Conceptually, in the interests of understanding the * terms that the calculus produced we can consider * that EA and EC end up providing the lengths along * the major axes and the hypot term ends up being an * adjustment for the additional length along the off-axis * angle of rotated or sheared ellipses as well as an * adjustment for the fact that the equation below * averages the two major axis lengths. (Notice that * the hypot term contains a part which resolves to the * difference of these two axis lengths in the absence * of rotation.) * * In the calculus, the ratio of the EB and (EA-EC) terms * ends up being the tangent of 2*theta where theta is * the angle that the long axis of the ellipse makes * with the horizontal axis. Thus, this equation is * calculating the length of the hypotenuse of a triangle * along that axis. */ double hypot = Math.sqrt(EB*EB + (EA-EC)*(EA-EC)); /* sqrt omitted, compare to squared limits below. */ widthsquared = ((EA + EC + hypot)/2.0); } if (bs != defaultStroke) { widthsquared *= bs.getLineWidth() * bs.getLineWidth(); } if (widthsquared <= (aa ? MinPenSizeAASquared : MinPenSizeSquared)) { if (bs.getDashArray() == null) { strokeState = STROKE_THIN; } else { strokeState = STROKE_THINDASHED; } } else { strokeState = STROKE_WIDE; } } } /* * Sets the Stroke in the current graphics state. * @param s The Stroke object to be used to stroke a Path in * the rendering process. * @see BasicStroke */ public void setStroke(Stroke s) { if (s == null) { throw new IllegalArgumentException("null Stroke"); } int saveStrokeState = strokeState; stroke = s; if (s instanceof BasicStroke) { validateBasicStroke((BasicStroke) s); } else { strokeState = STROKE_CUSTOM; } if (strokeState != saveStrokeState) { invalidatePipe(); } } /** * Sets the preferences for the rendering algorithms. * Hint categories include controls for rendering quality and * overall time/quality trade-off in the rendering process. * @param hintKey The key of hint to be set. The strings are * defined in the RenderingHints class. * @param hintValue The value indicating preferences for the specified * hint category. These strings are defined in the RenderingHints * class. * @see RenderingHints */ public void setRenderingHint(Key hintKey, Object hintValue) { // If we recognize the key, we must recognize the value // otherwise throw an IllegalArgumentException // and do not change the Hints object // If we do not recognize the key, just pass it through // to the Hints object untouched if (!hintKey.isCompatibleValue(hintValue)) { throw new IllegalArgumentException (hintValue+" is not compatible with "+hintKey); } if (hintKey instanceof SunHints.Key) { boolean stateChanged; boolean textStateChanged = false; boolean recognized = true; SunHints.Key sunKey = (SunHints.Key) hintKey; int newHint; if (sunKey == SunHints.KEY_TEXT_ANTIALIAS_LCD_CONTRAST) { newHint = ((Integer)hintValue).intValue(); } else { newHint = ((SunHints.Value) hintValue).getIndex(); } switch (sunKey.getIndex()) { case SunHints.INTKEY_RENDERING: stateChanged = (renderHint != newHint); if (stateChanged) { renderHint = newHint; if (interpolationHint == -1) { interpolationType = (newHint == SunHints.INTVAL_RENDER_QUALITY ? AffineTransformOp.TYPE_BILINEAR : AffineTransformOp.TYPE_NEAREST_NEIGHBOR); } } break; case SunHints.INTKEY_ANTIALIASING: stateChanged = (antialiasHint != newHint); antialiasHint = newHint; if (stateChanged) { textStateChanged = (textAntialiasHint == SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT); if (strokeState != STROKE_CUSTOM) { validateBasicStroke((BasicStroke) stroke); } } break; case SunHints.INTKEY_TEXT_ANTIALIASING: stateChanged = (textAntialiasHint != newHint); textStateChanged = stateChanged; textAntialiasHint = newHint; break; case SunHints.INTKEY_FRACTIONALMETRICS: stateChanged = (fractionalMetricsHint != newHint); textStateChanged = stateChanged; fractionalMetricsHint = newHint; break; case SunHints.INTKEY_AATEXT_LCD_CONTRAST: stateChanged = false; /* Already have validated it is an int 100 <= newHint <= 250 */ lcdTextContrast = newHint; break; case SunHints.INTKEY_INTERPOLATION: interpolationHint = newHint; switch (newHint) { case SunHints.INTVAL_INTERPOLATION_BICUBIC: newHint = AffineTransformOp.TYPE_BICUBIC; break; case SunHints.INTVAL_INTERPOLATION_BILINEAR: newHint = AffineTransformOp.TYPE_BILINEAR; break; default: case SunHints.INTVAL_INTERPOLATION_NEAREST_NEIGHBOR: newHint = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; break; } stateChanged = (interpolationType != newHint); interpolationType = newHint; break; case SunHints.INTKEY_STROKE_CONTROL: stateChanged = (strokeHint != newHint); strokeHint = newHint; break; default: recognized = false; stateChanged = false; break; } if (recognized) { if (stateChanged) { invalidatePipe(); if (textStateChanged) { fontMetrics = null; this.cachedFRC = null; validFontInfo = false; this.glyphVectorFontInfo = null; } } if (hints != null) { hints.put(hintKey, hintValue); } return; } } // Nothing we recognize so none of "our state" has changed if (hints == null) { hints = makeHints(null); } hints.put(hintKey, hintValue); } /** * Returns the preferences for the rendering algorithms. * @param hintCategory The category of hint to be set. The strings * are defined in the RenderingHints class. * @return The preferences for rendering algorithms. The strings * are defined in the RenderingHints class. * @see RenderingHints */ public Object getRenderingHint(Key hintKey) { if (hints != null) { return hints.get(hintKey); } if (!(hintKey instanceof SunHints.Key)) { return null; } int keyindex = ((SunHints.Key)hintKey).getIndex(); switch (keyindex) { case SunHints.INTKEY_RENDERING: return SunHints.Value.get(SunHints.INTKEY_RENDERING, renderHint); case SunHints.INTKEY_ANTIALIASING: return SunHints.Value.get(SunHints.INTKEY_ANTIALIASING, antialiasHint); case SunHints.INTKEY_TEXT_ANTIALIASING: return SunHints.Value.get(SunHints.INTKEY_TEXT_ANTIALIASING, textAntialiasHint); case SunHints.INTKEY_FRACTIONALMETRICS: return SunHints.Value.get(SunHints.INTKEY_FRACTIONALMETRICS, fractionalMetricsHint); case SunHints.INTKEY_AATEXT_LCD_CONTRAST: return new Integer(lcdTextContrast); case SunHints.INTKEY_INTERPOLATION: switch (interpolationHint) { case SunHints.INTVAL_INTERPOLATION_NEAREST_NEIGHBOR: return SunHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; case SunHints.INTVAL_INTERPOLATION_BILINEAR: return SunHints.VALUE_INTERPOLATION_BILINEAR; case SunHints.INTVAL_INTERPOLATION_BICUBIC: return SunHints.VALUE_INTERPOLATION_BICUBIC; } return null; case SunHints.INTKEY_STROKE_CONTROL: return SunHints.Value.get(SunHints.INTKEY_STROKE_CONTROL, strokeHint); } return null; } /** * Sets the preferences for the rendering algorithms. * Hint categories include controls for rendering quality and * overall time/quality trade-off in the rendering process. * @param hints The rendering hints to be set * @see RenderingHints */ public void setRenderingHints(Map<?,?> hints) { this.hints = null; renderHint = SunHints.INTVAL_RENDER_DEFAULT; antialiasHint = SunHints.INTVAL_ANTIALIAS_OFF; textAntialiasHint = SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT; fractionalMetricsHint = SunHints.INTVAL_FRACTIONALMETRICS_OFF; lcdTextContrast = lcdTextContrastDefaultValue; interpolationHint = -1; interpolationType = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; boolean customHintPresent = false; Iterator iter = hints.keySet().iterator(); while (iter.hasNext()) { Object key = iter.next(); if (key == SunHints.KEY_RENDERING || key == SunHints.KEY_ANTIALIASING || key == SunHints.KEY_TEXT_ANTIALIASING || key == SunHints.KEY_FRACTIONALMETRICS || key == SunHints.KEY_TEXT_ANTIALIAS_LCD_CONTRAST || key == SunHints.KEY_STROKE_CONTROL || key == SunHints.KEY_INTERPOLATION) { setRenderingHint((Key) key, hints.get(key)); } else { customHintPresent = true; } } if (customHintPresent) { this.hints = makeHints(hints); } invalidatePipe(); } /** * Adds a number of preferences for the rendering algorithms. * Hint categories include controls for rendering quality and * overall time/quality trade-off in the rendering process. * @param hints The rendering hints to be set * @see RenderingHints */ public void addRenderingHints(Map<?,?> hints) { boolean customHintPresent = false; Iterator iter = hints.keySet().iterator(); while (iter.hasNext()) { Object key = iter.next(); if (key == SunHints.KEY_RENDERING || key == SunHints.KEY_ANTIALIASING || key == SunHints.KEY_TEXT_ANTIALIASING || key == SunHints.KEY_FRACTIONALMETRICS || key == SunHints.KEY_TEXT_ANTIALIAS_LCD_CONTRAST || key == SunHints.KEY_STROKE_CONTROL || key == SunHints.KEY_INTERPOLATION) { setRenderingHint((Key) key, hints.get(key)); } else { customHintPresent = true; } } if (customHintPresent) { if (this.hints == null) { this.hints = makeHints(hints); } else { this.hints.putAll(hints); } } } /** * Gets the preferences for the rendering algorithms. * Hint categories include controls for rendering quality and * overall time/quality trade-off in the rendering process. * @see RenderingHints */ public RenderingHints getRenderingHints() { if (hints == null) { return makeHints(null); } else { return (RenderingHints) hints.clone(); } } RenderingHints makeHints(Map hints) { RenderingHints model = new RenderingHints(hints); model.put(SunHints.KEY_RENDERING, SunHints.Value.get(SunHints.INTKEY_RENDERING, renderHint)); model.put(SunHints.KEY_ANTIALIASING, SunHints.Value.get(SunHints.INTKEY_ANTIALIASING, antialiasHint)); model.put(SunHints.KEY_TEXT_ANTIALIASING, SunHints.Value.get(SunHints.INTKEY_TEXT_ANTIALIASING, textAntialiasHint)); model.put(SunHints.KEY_FRACTIONALMETRICS, SunHints.Value.get(SunHints.INTKEY_FRACTIONALMETRICS, fractionalMetricsHint)); model.put(SunHints.KEY_TEXT_ANTIALIAS_LCD_CONTRAST, Integer.valueOf(lcdTextContrast)); Object value; switch (interpolationHint) { case SunHints.INTVAL_INTERPOLATION_NEAREST_NEIGHBOR: value = SunHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; break; case SunHints.INTVAL_INTERPOLATION_BILINEAR: value = SunHints.VALUE_INTERPOLATION_BILINEAR; break; case SunHints.INTVAL_INTERPOLATION_BICUBIC: value = SunHints.VALUE_INTERPOLATION_BICUBIC; break; default: value = null; break; } if (value != null) { model.put(SunHints.KEY_INTERPOLATION, value); } model.put(SunHints.KEY_STROKE_CONTROL, SunHints.Value.get(SunHints.INTKEY_STROKE_CONTROL, strokeHint)); return model; } /** * Concatenates the current transform of this Graphics2D with a * translation transformation. * This is equivalent to calling transform(T), where T is an * AffineTransform represented by the following matrix: * <pre> * [ 1 0 tx ] * [ 0 1 ty ] * [ 0 0 1 ] * </pre> */ public void translate(double tx, double ty) { transform.translate(tx, ty); invalidateTransform(); } /** * Concatenates the current transform of this Graphics2D with a * rotation transformation. * This is equivalent to calling transform(R), where R is an * AffineTransform represented by the following matrix: * <pre> * [ cos(theta) -sin(theta) 0 ] * [ sin(theta) cos(theta) 0 ] * [ 0 0 1 ] * </pre> * Rotating with a positive angle theta rotates points on the positive * x axis toward the positive y axis. * @param theta The angle of rotation in radians. */ public void rotate(double theta) { transform.rotate(theta); invalidateTransform(); } /** * Concatenates the current transform of this Graphics2D with a * translated rotation transformation. * This is equivalent to the following sequence of calls: * <pre> * translate(x, y); * rotate(theta); * translate(-x, -y); * </pre> * Rotating with a positive angle theta rotates points on the positive * x axis toward the positive y axis. * @param theta The angle of rotation in radians. * @param x The x coordinate of the origin of the rotation * @param y The x coordinate of the origin of the rotation */ public void rotate(double theta, double x, double y) { transform.rotate(theta, x, y); invalidateTransform(); } /** * Concatenates the current transform of this Graphics2D with a * scaling transformation. * This is equivalent to calling transform(S), where S is an * AffineTransform represented by the following matrix: * <pre> * [ sx 0 0 ] * [ 0 sy 0 ] * [ 0 0 1 ] * </pre> */ public void scale(double sx, double sy) { transform.scale(sx, sy); invalidateTransform(); } /** * Concatenates the current transform of this Graphics2D with a * shearing transformation. * This is equivalent to calling transform(SH), where SH is an * AffineTransform represented by the following matrix: * <pre> * [ 1 shx 0 ] * [ shy 1 0 ] * [ 0 0 1 ] * </pre> * @param shx The factor by which coordinates are shifted towards the * positive X axis direction according to their Y coordinate * @param shy The factor by which coordinates are shifted towards the * positive Y axis direction according to their X coordinate */ public void shear(double shx, double shy) { transform.shear(shx, shy); invalidateTransform(); } /** * Composes a Transform object with the transform in this * Graphics2D according to the rule last-specified-first-applied. * If the currrent transform is Cx, the result of composition * with Tx is a new transform Cx'. Cx' becomes the current * transform for this Graphics2D. * Transforming a point p by the updated transform Cx' is * equivalent to first transforming p by Tx and then transforming * the result by the original transform Cx. In other words, * Cx'(p) = Cx(Tx(p)). * A copy of the Tx is made, if necessary, so further * modifications to Tx do not affect rendering. * @param Tx The Transform object to be composed with the current * transform. * @see #setTransform * @see AffineTransform */Lines 1001–1500 of 3310. Previous lines Load more
double widthsquared; if ((transform.getType() & NON_UNIFORM_SCALE_MASK) == 0) { /* sqrt omitted, compare to squared limits below. */ widthsquared = Math.abs(transform.getDeterminant()); } else { /* First calculate the "maximum scale" of this transform. */ double A = transform.getScaleX(); // m00 double C = transform.getShearX(); // m01 double B = transform.getShearY(); // m10 double D = transform.getScaleY(); // m11 /* * Given a 2 x 2 affine matrix [ A B ] such that * [ C D ] * v' = [x' y'] = [Ax + Cy, Bx + Dy], we want to * find the maximum magnitude (norm) of the vector v' * with the constraint (x^2 + y^2 = 1). * The equation to maximize is * |v'| = sqrt((Ax+Cy)^2+(Bx+Dy)^2) * or |v'| = sqrt((AA+BB)x^2 + 2(AC+BD)xy + (CC+DD)y^2). * Since sqrt is monotonic we can maximize |v'|^2 * instead and plug in the substitution y = sqrt(1 - x^2). * Trigonometric equalities can then be used to get * rid of most of the sqrt terms. */ double EA = A*A + B*B; // x^2 coefficient double EB = 2*(A*C + B*D); // xy coefficient double EC = C*C + D*D; // y^2 coefficient /* * There is a lot of calculus omitted here. * * Conceptually, in the interests of understanding the * terms that the calculus produced we can consider * that EA and EC end up providing the lengths along * the major axes and the hypot term ends up being an * adjustment for the additional length along the off-axis * angle of rotated or sheared ellipses as well as an * adjustment for the fact that the equation below * averages the two major axis lengths. (Notice that * the hypot term contains a part which resolves to the * difference of these two axis lengths in the absence * of rotation.) * * In the calculus, the ratio of the EB and (EA-EC) terms * ends up being the tangent of 2*theta where theta is * the angle that the long axis of the ellipse makes * with the horizontal axis. Thus, this equation is * calculating the length of the hypotenuse of a triangle * along that axis. */ double hypot = Math.sqrt(EB*EB + (EA-EC)*(EA-EC)); /* sqrt omitted, compare to squared limits below. */ widthsquared = ((EA + EC + hypot)/2.0); } if (bs != defaultStroke) { widthsquared *= bs.getLineWidth() * bs.getLineWidth(); } if (widthsquared <= (aa ? MinPenSizeAASquared : MinPenSizeSquared)) { if (bs.getDashArray() == null) { strokeState = STROKE_THIN; } else { strokeState = STROKE_THINDASHED; } } else { strokeState = STROKE_WIDE; } } } /* * Sets the Stroke in the current graphics state. * @param s The Stroke object to be used to stroke a Path in * the rendering process. * @see BasicStroke */ public void setStroke(Stroke s) { if (s == null) { throw new IllegalArgumentException("null Stroke"); } int saveStrokeState = strokeState; stroke = s; if (s instanceof BasicStroke) { validateBasicStroke((BasicStroke) s); } else { strokeState = STROKE_CUSTOM; } if (strokeState != saveStrokeState) { invalidatePipe(); } } /** * Sets the preferences for the rendering algorithms. * Hint categories include controls for rendering quality and * overall time/quality trade-off in the rendering process. * @param hintKey The key of hint to be set. The strings are * defined in the RenderingHints class. * @param hintValue The value indicating preferences for the specified * hint category. These strings are defined in the RenderingHints * class. * @see RenderingHints */ public void setRenderingHint(Key hintKey, Object hintValue) { // If we recognize the key, we must recognize the value // otherwise throw an IllegalArgumentException // and do not change the Hints object // If we do not recognize the key, just pass it through // to the Hints object untouched if (!hintKey.isCompatibleValue(hintValue)) { throw new IllegalArgumentException (hintValue+" is not compatible with "+hintKey); } if (hintKey instanceof SunHints.Key) { boolean stateChanged; boolean textStateChanged = false; boolean recognized = true; SunHints.Key sunKey = (SunHints.Key) hintKey; int newHint; if (sunKey == SunHints.KEY_TEXT_ANTIALIAS_LCD_CONTRAST) { newHint = ((Integer)hintValue).intValue(); } else { newHint = ((SunHints.Value) hintValue).getIndex(); } switch (sunKey.getIndex()) { case SunHints.INTKEY_RENDERING: stateChanged = (renderHint != newHint); if (stateChanged) { renderHint = newHint; if (interpolationHint == -1) { interpolationType = (newHint == SunHints.INTVAL_RENDER_QUALITY ? AffineTransformOp.TYPE_BILINEAR : AffineTransformOp.TYPE_NEAREST_NEIGHBOR); } } break; case SunHints.INTKEY_ANTIALIASING: stateChanged = (antialiasHint != newHint); antialiasHint = newHint; if (stateChanged) { textStateChanged = (textAntialiasHint == SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT); if (strokeState != STROKE_CUSTOM) { validateBasicStroke((BasicStroke) stroke); } } break; case SunHints.INTKEY_TEXT_ANTIALIASING: stateChanged = (textAntialiasHint != newHint); textStateChanged = stateChanged; textAntialiasHint = newHint; break; case SunHints.INTKEY_FRACTIONALMETRICS: stateChanged = (fractionalMetricsHint != newHint); textStateChanged = stateChanged; fractionalMetricsHint = newHint; break; case SunHints.INTKEY_AATEXT_LCD_CONTRAST: stateChanged = false; /* Already have validated it is an int 100 <= newHint <= 250 */ lcdTextContrast = newHint; break; case SunHints.INTKEY_INTERPOLATION: interpolationHint = newHint; switch (newHint) { case SunHints.INTVAL_INTERPOLATION_BICUBIC: newHint = AffineTransformOp.TYPE_BICUBIC; break; case SunHints.INTVAL_INTERPOLATION_BILINEAR: newHint = AffineTransformOp.TYPE_BILINEAR; break; default: case SunHints.INTVAL_INTERPOLATION_NEAREST_NEIGHBOR: newHint = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; break; } stateChanged = (interpolationType != newHint); interpolationType = newHint; break; case SunHints.INTKEY_STROKE_CONTROL: stateChanged = (strokeHint != newHint); strokeHint = newHint; break; default: recognized = false; stateChanged = false; break; } if (recognized) { if (stateChanged) { invalidatePipe(); if (textStateChanged) { fontMetrics = null; this.cachedFRC = null; validFontInfo = false; this.glyphVectorFontInfo = null; } } if (hints != null) { hints.put(hintKey, hintValue); } return; } } // Nothing we recognize so none of "our state" has changed if (hints == null) { hints = makeHints(null); } hints.put(hintKey, hintValue); } /** * Returns the preferences for the rendering algorithms. * @param hintCategory The category of hint to be set. The strings * are defined in the RenderingHints class. * @return The preferences for rendering algorithms. The strings * are defined in the RenderingHints class. * @see RenderingHints */ public Object getRenderingHint(Key hintKey) { if (hints != null) { return hints.get(hintKey); } if (!(hintKey instanceof SunHints.Key)) { return null; } int keyindex = ((SunHints.Key)hintKey).getIndex(); switch (keyindex) { case SunHints.INTKEY_RENDERING: return SunHints.Value.get(SunHints.INTKEY_RENDERING, renderHint); case SunHints.INTKEY_ANTIALIASING: return SunHints.Value.get(SunHints.INTKEY_ANTIALIASING, antialiasHint); case SunHints.INTKEY_TEXT_ANTIALIASING: return SunHints.Value.get(SunHints.INTKEY_TEXT_ANTIALIASING, textAntialiasHint); case SunHints.INTKEY_FRACTIONALMETRICS: return SunHints.Value.get(SunHints.INTKEY_FRACTIONALMETRICS, fractionalMetricsHint); case SunHints.INTKEY_AATEXT_LCD_CONTRAST: return new Integer(lcdTextContrast); case SunHints.INTKEY_INTERPOLATION: switch (interpolationHint) { case SunHints.INTVAL_INTERPOLATION_NEAREST_NEIGHBOR: return SunHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; case SunHints.INTVAL_INTERPOLATION_BILINEAR: return SunHints.VALUE_INTERPOLATION_BILINEAR; case SunHints.INTVAL_INTERPOLATION_BICUBIC: return SunHints.VALUE_INTERPOLATION_BICUBIC; } return null; case SunHints.INTKEY_STROKE_CONTROL: return SunHints.Value.get(SunHints.INTKEY_STROKE_CONTROL, strokeHint); } return null; } /** * Sets the preferences for the rendering algorithms. * Hint categories include controls for rendering quality and * overall time/quality trade-off in the rendering process. * @param hints The rendering hints to be set * @see RenderingHints */ public void setRenderingHints(Map<?,?> hints) { this.hints = null; renderHint = SunHints.INTVAL_RENDER_DEFAULT; antialiasHint = SunHints.INTVAL_ANTIALIAS_OFF; textAntialiasHint = SunHints.INTVAL_TEXT_ANTIALIAS_DEFAULT; fractionalMetricsHint = SunHints.INTVAL_FRACTIONALMETRICS_OFF; lcdTextContrast = lcdTextContrastDefaultValue; interpolationHint = -1; interpolationType = AffineTransformOp.TYPE_NEAREST_NEIGHBOR; boolean customHintPresent = false; Iterator iter = hints.keySet().iterator(); while (iter.hasNext()) { Object key = iter.next(); if (key == SunHints.KEY_RENDERING || key == SunHints.KEY_ANTIALIASING || key == SunHints.KEY_TEXT_ANTIALIASING || key == SunHints.KEY_FRACTIONALMETRICS || key == SunHints.KEY_TEXT_ANTIALIAS_LCD_CONTRAST || key == SunHints.KEY_STROKE_CONTROL || key == SunHints.KEY_INTERPOLATION) { setRenderingHint((Key) key, hints.get(key)); } else { customHintPresent = true; } } if (customHintPresent) { this.hints = makeHints(hints); } invalidatePipe(); } /** * Adds a number of preferences for the rendering algorithms. * Hint categories include controls for rendering quality and * overall time/quality trade-off in the rendering process. * @param hints The rendering hints to be set * @see RenderingHints */ public void addRenderingHints(Map<?,?> hints) { boolean customHintPresent = false; Iterator iter = hints.keySet().iterator(); while (iter.hasNext()) { Object key = iter.next(); if (key == SunHints.KEY_RENDERING || key == SunHints.KEY_ANTIALIASING || key == SunHints.KEY_TEXT_ANTIALIASING || key == SunHints.KEY_FRACTIONALMETRICS || key == SunHints.KEY_TEXT_ANTIALIAS_LCD_CONTRAST || key == SunHints.KEY_STROKE_CONTROL || key == SunHints.KEY_INTERPOLATION) { setRenderingHint((Key) key, hints.get(key)); } else { customHintPresent = true; } } if (customHintPresent) { if (this.hints == null) { this.hints = makeHints(hints); } else { this.hints.putAll(hints); } } } /** * Gets the preferences for the rendering algorithms. * Hint categories include controls for rendering quality and * overall time/quality trade-off in the rendering process. * @see RenderingHints */ public RenderingHints getRenderingHints() { if (hints == null) { return makeHints(null); } else { return (RenderingHints) hints.clone(); } } RenderingHints makeHints(Map hints) { RenderingHints model = new RenderingHints(hints); model.put(SunHints.KEY_RENDERING, SunHints.Value.get(SunHints.INTKEY_RENDERING, renderHint)); model.put(SunHints.KEY_ANTIALIASING, SunHints.Value.get(SunHints.INTKEY_ANTIALIASING, antialiasHint)); model.put(SunHints.KEY_TEXT_ANTIALIASING, SunHints.Value.get(SunHints.INTKEY_TEXT_ANTIALIASING, textAntialiasHint)); model.put(SunHints.KEY_FRACTIONALMETRICS, SunHints.Value.get(SunHints.INTKEY_FRACTIONALMETRICS, fractionalMetricsHint)); model.put(SunHints.KEY_TEXT_ANTIALIAS_LCD_CONTRAST, Integer.valueOf(lcdTextContrast)); Object value; switch (interpolationHint) { case SunHints.INTVAL_INTERPOLATION_NEAREST_NEIGHBOR: value = SunHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR; break; case SunHints.INTVAL_INTERPOLATION_BILINEAR: value = SunHints.VALUE_INTERPOLATION_BILINEAR; break; case SunHints.INTVAL_INTERPOLATION_BICUBIC: value = SunHints.VALUE_INTERPOLATION_BICUBIC; break; default: value = null; break; } if (value != null) { model.put(SunHints.KEY_INTERPOLATION, value); } model.put(SunHints.KEY_STROKE_CONTROL, SunHints.Value.get(SunHints.INTKEY_STROKE_CONTROL, strokeHint)); return model; } /** * Concatenates the current transform of this Graphics2D with a * translation transformation. * This is equivalent to calling transform(T), where T is an * AffineTransform represented by the following matrix: * <pre> * [ 1 0 tx ] * [ 0 1 ty ] * [ 0 0 1 ] * </pre> */ public void translate(double tx, double ty) { transform.translate(tx, ty); invalidateTransform(); } /** * Concatenates the current transform of this Graphics2D with a * rotation transformation. * This is equivalent to calling transform(R), where R is an * AffineTransform represented by the following matrix: * <pre> * [ cos(theta) -sin(theta) 0 ] * [ sin(theta) cos(theta) 0 ] * [ 0 0 1 ] * </pre> * Rotating with a positive angle theta rotates points on the positive * x axis toward the positive y axis. * @param theta The angle of rotation in radians. */ public void rotate(double theta) { transform.rotate(theta); invalidateTransform(); } /** * Concatenates the current transform of this Graphics2D with a * translated rotation transformation. * This is equivalent to the following sequence of calls: * <pre> * translate(x, y); * rotate(theta); * translate(-x, -y); * </pre> * Rotating with a positive angle theta rotates points on the positive * x axis toward the positive y axis. * @param theta The angle of rotation in radians. * @param x The x coordinate of the origin of the rotation * @param y The x coordinate of the origin of the rotation */ public void rotate(double theta, double x, double y) { transform.rotate(theta, x, y); invalidateTransform(); } /** * Concatenates the current transform of this Graphics2D with a * scaling transformation. * This is equivalent to calling transform(S), where S is an * AffineTransform represented by the following matrix: * <pre> * [ sx 0 0 ] * [ 0 sy 0 ] * [ 0 0 1 ] * </pre> */ public void scale(double sx, double sy) { transform.scale(sx, sy); invalidateTransform(); } /** * Concatenates the current transform of this Graphics2D with a * shearing transformation. * This is equivalent to calling transform(SH), where SH is an * AffineTransform represented by the following matrix: * <pre> * [ 1 shx 0 ] * [ shy 1 0 ] * [ 0 0 1 ] * </pre> * @param shx The factor by which coordinates are shifted towards the * positive X axis direction according to their Y coordinate * @param shy The factor by which coordinates are shifted towards the * positive Y axis direction according to their X coordinate */ public void shear(double shx, double shy) { transform.shear(shx, shy); invalidateTransform(); } /** * Composes a Transform object with the transform in this * Graphics2D according to the rule last-specified-first-applied. * If the currrent transform is Cx, the result of composition * with Tx is a new transform Cx'. Cx' becomes the current * transform for this Graphics2D. * Transforming a point p by the updated transform Cx' is * equivalent to first transforming p by Tx and then transforming * the result by the original transform Cx. In other words, * Cx'(p) = Cx(Tx(p)). * A copy of the Tx is made, if necessary, so further * modifications to Tx do not affect rendering. * @param Tx The Transform object to be composed with the current * transform. * @see #setTransform * @see AffineTransform */