use of sun.font.PhysicalFont in project jdk8u_jdk by JetBrains.
the class WPathGraphics method drawString.
/**
* Renders the text specified by the specified <code>String</code>,
* using the current <code>Font</code> and <code>Paint</code> attributes
* in the <code>Graphics2D</code> context.
* The baseline of the first character is at position
* (<i>x</i>, <i>y</i>) in the User Space.
* The rendering attributes applied include the <code>Clip</code>,
* <code>Transform</code>, <code>Paint</code>, <code>Font</code> and
* <code>Composite</code> attributes. For characters in script systems
* such as Hebrew and Arabic, the glyphs can be rendered from right to
* left, in which case the coordinate supplied is the location of the
* leftmost character on the baseline.
* @param s the <code>String</code> to be rendered
* @param x, y the coordinates where the <code>String</code>
* should be rendered
* @see #setPaint
* @see java.awt.Graphics#setColor
* @see java.awt.Graphics#setFont
* @see #setTransform
* @see #setComposite
* @see #setClip
*/
@Override
public void drawString(String str, float x, float y, Font font, FontRenderContext frc, float targetW) {
if (str.length() == 0) {
return;
}
if (WPrinterJob.shapeTextProp) {
super.drawString(str, x, y, font, frc, targetW);
return;
}
/* If the Font has layout attributes we need to delegate to TextLayout.
* TextLayout renders text as GlyphVectors. We try to print those
* using printer fonts - ie using Postscript text operators so
* we may be reinvoked. In that case the "!printingGlyphVector" test
* prevents us recursing and instead sends us into the body of the
* method where we can safely ignore layout attributes as those
* are already handled by TextLayout.
* Similarly if layout is needed based on the text, then we
* delegate to TextLayout if possible, or failing that we delegate
* upwards to filled shapes.
*/
boolean layoutNeeded = strNeedsTextLayout(str, font);
if ((font.hasLayoutAttributes() || layoutNeeded) && !printingGlyphVector) {
TextLayout layout = new TextLayout(str, font, frc);
layout.draw(this, x, y);
return;
} else if (layoutNeeded) {
super.drawString(str, x, y, font, frc, targetW);
return;
}
AffineTransform deviceTransform = getTransform();
AffineTransform fontTransform = new AffineTransform(deviceTransform);
fontTransform.concatenate(font.getTransform());
int transformType = fontTransform.getType();
/* Use GDI for the text if the graphics transform is something
* for which we can obtain a suitable GDI font.
* A flip or shearing transform on the graphics or a transform
* on the font force us to decompose the text into a shape.
*/
boolean directToGDI = ((transformType != AffineTransform.TYPE_GENERAL_TRANSFORM) && ((transformType & AffineTransform.TYPE_FLIP) == 0));
WPrinterJob wPrinterJob = (WPrinterJob) getPrinterJob();
try {
wPrinterJob.setTextColor((Color) getPaint());
} catch (ClassCastException e) {
// peek should detect such paints.
directToGDI = false;
}
if (!directToGDI) {
super.drawString(str, x, y, font, frc, targetW);
return;
}
/* Now we have checked everything is OK to go through GDI as text
* with the exception of testing GDI can find and use the font. That
* is handled in the textOut() call.
*/
/* Compute the starting position of the string in
* device space.
*/
Point2D.Float userpos = new Point2D.Float(x, y);
Point2D.Float devpos = new Point2D.Float();
/* Already have the translate from the deviceTransform,
* but the font may have a translation component too.
*/
if (font.isTransformed()) {
AffineTransform fontTx = font.getTransform();
float translateX = (float) (fontTx.getTranslateX());
float translateY = (float) (fontTx.getTranslateY());
if (Math.abs(translateX) < 0.00001)
translateX = 0f;
if (Math.abs(translateY) < 0.00001)
translateY = 0f;
userpos.x += translateX;
userpos.y += translateY;
}
deviceTransform.transform(userpos, devpos);
if (getClip() != null) {
deviceClip(getClip().getPathIterator(deviceTransform));
}
/* Get the font size in device coordinates.
* The size needed is the font height scaled to device space.
* Although we have already tested that there is no shear,
* there may be a non-uniform scale, so the width of the font
* does not scale equally with the height. That is handled
* by specifying an 'average width' scale to GDI.
*/
float fontSize = font.getSize2D();
double devResX = wPrinterJob.getXRes();
double devResY = wPrinterJob.getYRes();
double fontDevScaleY = devResY / DEFAULT_USER_RES;
int orient = getPageFormat().getOrientation();
if (orient == PageFormat.LANDSCAPE || orient == PageFormat.REVERSE_LANDSCAPE) {
double tmp = devResX;
devResX = devResY;
devResY = tmp;
}
double devScaleX = devResX / DEFAULT_USER_RES;
double devScaleY = devResY / DEFAULT_USER_RES;
fontTransform.scale(1.0 / devScaleX, 1.0 / devScaleY);
Point2D.Double pty = new Point2D.Double(0.0, 1.0);
fontTransform.deltaTransform(pty, pty);
double scaleFactorY = Math.sqrt(pty.x * pty.x + pty.y * pty.y);
float scaledFontSizeY = (float) (fontSize * scaleFactorY * fontDevScaleY);
Point2D.Double ptx = new Point2D.Double(1.0, 0.0);
fontTransform.deltaTransform(ptx, ptx);
double scaleFactorX = Math.sqrt(ptx.x * ptx.x + ptx.y * ptx.y);
float awScale = getAwScale(scaleFactorX, scaleFactorY);
int iangle = getAngle(ptx);
ptx = new Point2D.Double(1.0, 0.0);
deviceTransform.deltaTransform(ptx, ptx);
double advanceScaleX = Math.sqrt(ptx.x * ptx.x + ptx.y * ptx.y);
pty = new Point2D.Double(0.0, 1.0);
deviceTransform.deltaTransform(pty, pty);
double advanceScaleY = Math.sqrt(pty.x * pty.x + pty.y * pty.y);
Font2D font2D = FontUtilities.getFont2D(font);
if (font2D instanceof TrueTypeFont) {
textOut(str, font, (TrueTypeFont) font2D, frc, scaledFontSizeY, iangle, awScale, advanceScaleX, advanceScaleY, x, y, devpos.x, devpos.y, targetW);
} else if (font2D instanceof CompositeFont) {
/* Composite fonts are made up of multiple fonts and each
* substring that uses a particular component font needs to
* be separately sent to GDI.
* This works for standard composite fonts, alternate ones,
* Fonts that are a physical font backed by a standard composite,
* and with fallback fonts.
*/
CompositeFont compFont = (CompositeFont) font2D;
float userx = x, usery = y;
float devx = devpos.x, devy = devpos.y;
char[] chars = str.toCharArray();
int len = chars.length;
int[] glyphs = new int[len];
compFont.getMapper().charsToGlyphs(len, chars, glyphs);
int startChar = 0, endChar = 0, slot = 0;
while (endChar < len) {
startChar = endChar;
slot = glyphs[startChar] >>> 24;
while (endChar < len && ((glyphs[endChar] >>> 24) == slot)) {
endChar++;
}
String substr = new String(chars, startChar, endChar - startChar);
PhysicalFont slotFont = compFont.getSlotFont(slot);
textOut(substr, font, slotFont, frc, scaledFontSizeY, iangle, awScale, advanceScaleX, advanceScaleY, userx, usery, devx, devy, 0f);
Rectangle2D bds = font.getStringBounds(substr, frc);
float xAdvance = (float) bds.getWidth();
userx += xAdvance;
userpos.x += xAdvance;
deviceTransform.transform(userpos, devpos);
devx = devpos.x;
devy = devpos.y;
}
} else {
super.drawString(str, x, y, font, frc, targetW);
}
}
use of sun.font.PhysicalFont in project jdk8u_jdk by JetBrains.
the class WPathGraphics method printGlyphVector.
/** return true if the Graphics instance can directly print
* this glyphvector
*/
@Override
protected boolean printGlyphVector(GlyphVector gv, float x, float y) {
/* We don't want to try to handle per-glyph transforms. GDI can't
* handle per-glyph rotations, etc. There's no way to express it
* in a single call, so just bail for this uncommon case.
*/
if ((gv.getLayoutFlags() & GlyphVector.FLAG_HAS_TRANSFORMS) != 0) {
return false;
}
if (gv.getNumGlyphs() == 0) {
// nothing to do.
return true;
}
AffineTransform deviceTransform = getTransform();
AffineTransform fontTransform = new AffineTransform(deviceTransform);
Font font = gv.getFont();
fontTransform.concatenate(font.getTransform());
int transformType = fontTransform.getType();
/* Use GDI for the text if the graphics transform is something
* for which we can obtain a suitable GDI font.
* A flip or shearing transform on the graphics or a transform
* on the font force us to decompose the text into a shape.
*/
boolean directToGDI = ((transformType != AffineTransform.TYPE_GENERAL_TRANSFORM) && ((transformType & AffineTransform.TYPE_FLIP) == 0));
WPrinterJob wPrinterJob = (WPrinterJob) getPrinterJob();
try {
wPrinterJob.setTextColor((Color) getPaint());
} catch (ClassCastException e) {
// peek should detect such paints.
directToGDI = false;
}
if (WPrinterJob.shapeTextProp || !directToGDI) {
return false;
}
/* Compute the starting position of the string in
* device space.
*/
Point2D.Float userpos = new Point2D.Float(x, y);
/* Add the position of the first glyph - its not always 0,0 */
Point2D g0pos = gv.getGlyphPosition(0);
userpos.x += (float) g0pos.getX();
userpos.y += (float) g0pos.getY();
Point2D.Float devpos = new Point2D.Float();
/* Already have the translate from the deviceTransform,
* but the font may have a translation component too.
*/
if (font.isTransformed()) {
AffineTransform fontTx = font.getTransform();
float translateX = (float) (fontTx.getTranslateX());
float translateY = (float) (fontTx.getTranslateY());
if (Math.abs(translateX) < 0.00001)
translateX = 0f;
if (Math.abs(translateY) < 0.00001)
translateY = 0f;
userpos.x += translateX;
userpos.y += translateY;
}
deviceTransform.transform(userpos, devpos);
if (getClip() != null) {
deviceClip(getClip().getPathIterator(deviceTransform));
}
/* Get the font size in device coordinates.
* The size needed is the font height scaled to device space.
* Although we have already tested that there is no shear,
* there may be a non-uniform scale, so the width of the font
* does not scale equally with the height. That is handled
* by specifying an 'average width' scale to GDI.
*/
float fontSize = font.getSize2D();
double devResX = wPrinterJob.getXRes();
double devResY = wPrinterJob.getYRes();
double fontDevScaleY = devResY / DEFAULT_USER_RES;
int orient = getPageFormat().getOrientation();
if (orient == PageFormat.LANDSCAPE || orient == PageFormat.REVERSE_LANDSCAPE) {
double tmp = devResX;
devResX = devResY;
devResY = tmp;
}
double devScaleX = devResX / DEFAULT_USER_RES;
double devScaleY = devResY / DEFAULT_USER_RES;
fontTransform.scale(1.0 / devScaleX, 1.0 / devScaleY);
Point2D.Double pty = new Point2D.Double(0.0, 1.0);
fontTransform.deltaTransform(pty, pty);
double scaleFactorY = Math.sqrt(pty.x * pty.x + pty.y * pty.y);
float scaledFontSizeY = (float) (fontSize * scaleFactorY * fontDevScaleY);
Point2D.Double ptx = new Point2D.Double(1.0, 0.0);
fontTransform.deltaTransform(ptx, ptx);
double scaleFactorX = Math.sqrt(ptx.x * ptx.x + ptx.y * ptx.y);
float awScale = getAwScale(scaleFactorX, scaleFactorY);
int iangle = getAngle(ptx);
ptx = new Point2D.Double(1.0, 0.0);
deviceTransform.deltaTransform(ptx, ptx);
double advanceScaleX = Math.sqrt(ptx.x * ptx.x + ptx.y * ptx.y);
pty = new Point2D.Double(0.0, 1.0);
deviceTransform.deltaTransform(pty, pty);
double advanceScaleY = Math.sqrt(pty.x * pty.x + pty.y * pty.y);
int numGlyphs = gv.getNumGlyphs();
int[] glyphCodes = gv.getGlyphCodes(0, numGlyphs, null);
float[] glyphPos = gv.getGlyphPositions(0, numGlyphs, null);
/* layout replaces glyphs which have been combined away
* with 0xfffe or 0xffff. These are supposed to be invisible
* and we need to handle this here as GDI will interpret it
* as a missing glyph. We'll do it here by compacting the
* glyph codes array, but we have to do it in conjunction with
* compacting the positions/advances arrays too AND updating
* the number of glyphs ..
* Note that since the slot number for composites is in the
* significant byte we need to mask out that for comparison of
* the invisible glyph.
*/
int invisibleGlyphCnt = 0;
for (int gc = 0; gc < numGlyphs; gc++) {
if ((glyphCodes[gc] & 0xffff) >= CharToGlyphMapper.INVISIBLE_GLYPHS) {
invisibleGlyphCnt++;
}
}
if (invisibleGlyphCnt > 0) {
int visibleGlyphCnt = numGlyphs - invisibleGlyphCnt;
int[] visibleGlyphCodes = new int[visibleGlyphCnt];
float[] visiblePositions = new float[visibleGlyphCnt * 2];
int index = 0;
for (int i = 0; i < numGlyphs; i++) {
if ((glyphCodes[i] & 0xffff) < CharToGlyphMapper.INVISIBLE_GLYPHS) {
visibleGlyphCodes[index] = glyphCodes[i];
visiblePositions[index * 2] = glyphPos[i * 2];
visiblePositions[index * 2 + 1] = glyphPos[i * 2 + 1];
index++;
}
}
numGlyphs = visibleGlyphCnt;
glyphCodes = visibleGlyphCodes;
glyphPos = visiblePositions;
}
/* To get GDI to rotate glyphs we need to specify the angle
* of rotation to GDI when creating the HFONT. This implicitly
* also rotates the baseline, and this adjusts the X & Y advances
* of the glyphs accordingly.
* When we specify the advances, they are in device space, so
* we don't want any further interpretation applied by GDI, but
* since as noted the advances are interpreted in the HFONT's
* coordinate space, our advances would be rotated again.
* We don't have any way to tell GDI to rotate only the glyphs and
* not the advances, so we need to account for this in the advances
* we supply, by supplying unrotated advances.
* Note that "iangle" is in the opposite direction to 2D's normal
* direction of rotation, so this rotation inverts the
* rotation element of the deviceTransform.
*/
AffineTransform advanceTransform = AffineTransform.getScaleInstance(advanceScaleX, advanceScaleY);
float[] glyphAdvPos = new float[glyphPos.length];
//source
advanceTransform.transform(//source
glyphPos, //source
0, //destination
glyphAdvPos, //destination
0, //num points
glyphPos.length / 2);
Font2D font2D = FontUtilities.getFont2D(font);
if (font2D instanceof TrueTypeFont) {
String family = font2D.getFamilyName(null);
int style = font.getStyle() | font2D.getStyle();
if (!wPrinterJob.setFont(family, scaledFontSizeY, style, iangle, awScale)) {
return false;
}
wPrinterJob.glyphsOut(glyphCodes, devpos.x, devpos.y, glyphAdvPos);
} else if (font2D instanceof CompositeFont) {
/* Composite fonts are made up of multiple fonts and each
* substring that uses a particular component font needs to
* be separately sent to GDI.
* This works for standard composite fonts, alternate ones,
* Fonts that are a physical font backed by a standard composite,
* and with fallback fonts.
*/
CompositeFont compFont = (CompositeFont) font2D;
float userx = x, usery = y;
float devx = devpos.x, devy = devpos.y;
int start = 0, end = 0, slot = 0;
while (end < numGlyphs) {
start = end;
slot = glyphCodes[start] >>> 24;
while (end < numGlyphs && ((glyphCodes[end] >>> 24) == slot)) {
end++;
}
/* If we can't get the font, bail to outlines.
* But we should always be able to get all fonts for
* Composites, so this is unlikely, so any overstriking
* if only one slot is unavailable is not worth worrying
* about.
*/
PhysicalFont slotFont = compFont.getSlotFont(slot);
if (!(slotFont instanceof TrueTypeFont)) {
return false;
}
String family = slotFont.getFamilyName(null);
int style = font.getStyle() | slotFont.getStyle();
if (!wPrinterJob.setFont(family, scaledFontSizeY, style, iangle, awScale)) {
return false;
}
int[] glyphs = Arrays.copyOfRange(glyphCodes, start, end);
float[] posns = Arrays.copyOfRange(glyphAdvPos, start * 2, end * 2);
if (start != 0) {
Point2D.Float p = new Point2D.Float(x + glyphPos[start * 2], y + glyphPos[start * 2 + 1]);
deviceTransform.transform(p, p);
devx = p.x;
devy = p.y;
}
wPrinterJob.glyphsOut(glyphs, devx, devy, posns);
}
} else {
return false;
}
return true;
}
Aggregations