use of java.awt.font.GlyphVector in project android_frameworks_base by ResurrectionRemix.
the class BidiRenderer method render.
/**
* Renders the text to the right of the bounds with the given font.
* @param font The font to render the text with.
*/
private void render(int start, int limit, Font font, int flag, float[] advances, int advancesIndex, boolean draw) {
FontRenderContext frc;
if (mGraphics != null) {
frc = mGraphics.getFontRenderContext();
} else {
frc = Toolkit.getDefaultToolkit().getFontMetrics(font).getFontRenderContext();
// Metrics obtained this way don't have anti-aliasing set. So,
// we create a new FontRenderContext with anti-aliasing set.
frc = new FontRenderContext(font.getTransform(), mPaint.isAntiAliased(), frc.usesFractionalMetrics());
}
GlyphVector gv = font.layoutGlyphVector(frc, mText, start, limit, flag);
int ng = gv.getNumGlyphs();
int[] ci = gv.getGlyphCharIndices(0, ng, null);
if (advances != null) {
for (int i = 0; i < ng; i++) {
int adv_idx = advancesIndex + ci[i];
advances[adv_idx] += gv.getGlyphMetrics(i).getAdvanceX();
}
}
if (draw && mGraphics != null) {
mGraphics.drawGlyphVector(gv, mBounds.right, mBaseline);
}
// Update the bounds.
Rectangle2D awtBounds = gv.getLogicalBounds();
RectF bounds = awtRectToAndroidRect(awtBounds, mBounds.right, mBaseline);
// coordinates from the bounds as an offset.
if (Math.abs(mBounds.right - mBounds.left) == 0) {
mBounds = bounds;
} else {
mBounds.union(bounds);
}
}
use of java.awt.font.GlyphVector in project jdk8u_jdk by JetBrains.
the class WPathGraphics method textOut.
private void textOut(String str, Font font, PhysicalFont font2D, FontRenderContext frc, float deviceSize, int rotation, float awScale, double scaleFactorX, double scaleFactorY, float userx, float usery, float devx, float devy, float targetW) {
String family = font2D.getFamilyName(null);
int style = font.getStyle() | font2D.getStyle();
WPrinterJob wPrinterJob = (WPrinterJob) getPrinterJob();
boolean setFont = wPrinterJob.setFont(family, deviceSize, style, rotation, awScale);
if (!setFont) {
super.drawString(str, userx, usery, font, frc, targetW);
return;
}
float[] glyphPos = null;
if (!okGDIMetrics(str, font, frc, scaleFactorX)) {
/* If there is a 1:1 char->glyph mapping then char positions
* are the same as glyph positions and we can tell GDI
* where to place the glyphs.
* On drawing we remove control chars so these need to be
* removed now so the string and positions are the same length.
* For other cases we need to pass glyph codes to GDI.
*/
str = wPrinterJob.removeControlChars(str);
char[] chars = str.toCharArray();
int len = chars.length;
GlyphVector gv = null;
if (!FontUtilities.isComplexText(chars, 0, len)) {
gv = font.createGlyphVector(frc, str);
}
if (gv == null) {
super.drawString(str, userx, usery, font, frc, targetW);
return;
}
glyphPos = gv.getGlyphPositions(0, len, null);
Point2D gvAdvPt = gv.getGlyphPosition(gv.getNumGlyphs());
/* GDI advances must not include device space rotation.
* See earlier comment in printGlyphVector() for details.
*/
AffineTransform advanceTransform = AffineTransform.getScaleInstance(scaleFactorX, scaleFactorY);
float[] glyphAdvPos = new float[glyphPos.length];
//source
advanceTransform.transform(//source
glyphPos, //source
0, //destination
glyphAdvPos, //destination
0, //num points
glyphPos.length / 2);
glyphPos = glyphAdvPos;
}
wPrinterJob.textOut(str, devx, devy, glyphPos);
}
use of java.awt.font.GlyphVector in project jdk8u_jdk by JetBrains.
the class PathGraphics method printedSimpleGlyphVector.
/* GlyphVectors are usually encountered because TextLayout is in use.
* Some times TextLayout is needed to handle complex text or some
* rendering attributes trigger it.
* We try to print GlyphVectors by reconstituting into a String,
* as that is most recoverable for applications that export to formats
* such as Postscript or PDF. In some cases (eg where its not complex
* text and its just that positions aren't what we'd expect) we print
* one character at a time. positioning individually.
* Failing that, if we can directly send glyph codes to the printer
* then we do that (printGlyphVector).
* As a last resort we return false and let the caller print as filled
* shapes.
*/
boolean printedSimpleGlyphVector(GlyphVector g, float x, float y) {
int flags = g.getLayoutFlags();
/* We can't handle RTL, re-ordering, complex glyphs etc by
* reconstituting glyphs into a String. So if any flags besides
* position adjustments are set, see if we can directly
* print the GlyphVector as glyph codes, using the positions
* layout has assigned. If that fails return false;
*/
if (flags != 0 && flags != GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS) {
return printGlyphVector(g, x, y);
}
Font font = g.getFont();
Font2D font2D = FontUtilities.getFont2D(font);
if (font2D.handle.font2D != font2D) {
/* suspicious, may be a bad font. lets bail */
return false;
}
Hashtable<Font2DHandle, Object> fontMap;
synchronized (PathGraphics.class) {
fontMap = fontMapRef.get();
if (fontMap == null) {
fontMap = new Hashtable<Font2DHandle, Object>();
fontMapRef = new SoftReference<Hashtable<Font2DHandle, Object>>(fontMap);
}
}
int numGlyphs = g.getNumGlyphs();
int[] glyphCodes = g.getGlyphCodes(0, numGlyphs, null);
char[] glyphToCharMap = null;
char[][] mapArray = null;
CompositeFont cf = null;
/* Build the needed maps for this font in a synchronized block */
synchronized (fontMap) {
if (font2D instanceof CompositeFont) {
cf = (CompositeFont) font2D;
int numSlots = cf.getNumSlots();
mapArray = (char[][]) fontMap.get(font2D.handle);
if (mapArray == null) {
mapArray = new char[numSlots][];
fontMap.put(font2D.handle, mapArray);
}
for (int i = 0; i < numGlyphs; i++) {
int slot = glyphCodes[i] >>> 24;
if (slot >= numSlots) {
/* shouldn't happen */
return false;
}
if (mapArray[slot] == null) {
Font2D slotFont = cf.getSlotFont(slot);
char[] map = (char[]) fontMap.get(slotFont.handle);
if (map == null) {
map = getGlyphToCharMapForFont(slotFont);
}
mapArray[slot] = map;
}
}
} else {
glyphToCharMap = (char[]) fontMap.get(font2D.handle);
if (glyphToCharMap == null) {
glyphToCharMap = getGlyphToCharMapForFont(font2D);
fontMap.put(font2D.handle, glyphToCharMap);
}
}
}
char[] chars = new char[numGlyphs];
if (cf != null) {
for (int i = 0; i < numGlyphs; i++) {
int gc = glyphCodes[i];
char[] map = mapArray[gc >>> 24];
gc = gc & 0xffffff;
if (map == null) {
return false;
}
/* X11 symbol & dingbats fonts used only for global metrics,
* so the glyph codes we have really refer to Lucida Sans
* Regular.
* So its possible the glyph code may appear out of range.
* Note that later on we double-check the glyph codes that
* we get from re-creating the GV from the string are the
* same as those we started with.
*
* If the glyphcode is INVISIBLE_GLYPH_ID then this may
* be \t, \n or \r which are mapped to that by layout.
* This is a case we can handle. It doesn't matter what
* character we use (we use \n) so long as layout maps it
* back to this in the verification, since the invisible
* glyph isn't visible :)
*/
char ch;
if (gc == CharToGlyphMapper.INVISIBLE_GLYPH_ID) {
ch = '\n';
} else if (gc < 0 || gc >= map.length) {
return false;
} else {
ch = map[gc];
}
if (ch != CharToGlyphMapper.INVISIBLE_GLYPH_ID) {
chars[i] = ch;
} else {
return false;
}
}
} else {
for (int i = 0; i < numGlyphs; i++) {
int gc = glyphCodes[i];
char ch;
if (gc == CharToGlyphMapper.INVISIBLE_GLYPH_ID) {
ch = '\n';
} else if (gc < 0 || gc >= glyphToCharMap.length) {
return false;
} else {
ch = glyphToCharMap[gc];
}
if (ch != CharToGlyphMapper.INVISIBLE_GLYPH_ID) {
chars[i] = ch;
} else {
return false;
}
}
}
FontRenderContext gvFrc = g.getFontRenderContext();
GlyphVector gv2 = font.createGlyphVector(gvFrc, chars);
if (gv2.getNumGlyphs() != numGlyphs) {
return printGlyphVector(g, x, y);
}
int[] glyphCodes2 = gv2.getGlyphCodes(0, numGlyphs, null);
/*
* Needed to double-check remapping of X11 symbol & dingbats.
*/
for (int i = 0; i < numGlyphs; i++) {
if (glyphCodes[i] != glyphCodes2[i]) {
return printGlyphVector(g, x, y);
}
}
FontRenderContext g2dFrc = getFontRenderContext();
boolean compatibleFRC = gvFrc.equals(g2dFrc);
/* If differ only in specifying A-A or a translation, these are
* also compatible FRC's, and we can do one drawString call.
*/
if (!compatibleFRC && gvFrc.usesFractionalMetrics() == g2dFrc.usesFractionalMetrics()) {
AffineTransform gvAT = gvFrc.getTransform();
AffineTransform g2dAT = getTransform();
double[] gvMatrix = new double[4];
double[] g2dMatrix = new double[4];
gvAT.getMatrix(gvMatrix);
g2dAT.getMatrix(g2dMatrix);
compatibleFRC = true;
for (int i = 0; i < 4; i++) {
if (gvMatrix[i] != g2dMatrix[i]) {
compatibleFRC = false;
break;
}
}
}
String str = new String(chars, 0, numGlyphs);
int numFonts = platformFontCount(font, str);
if (numFonts == 0) {
return false;
}
float[] positions = g.getGlyphPositions(0, numGlyphs, null);
boolean noPositionAdjustments = ((flags & GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS) == 0) || samePositions(gv2, glyphCodes2, glyphCodes, positions);
/* We have to consider that the application may be directly
* creating a GlyphVector, rather than one being created by
* TextLayout or indirectly from drawString. In such a case, if the
* font has layout attributes, the text may measure differently
* when we reconstitute it into a String and ask for the length that
* drawString would use. For example, KERNING will be applied in such
* a case but that Font attribute is not applied when the application
* directly created a GlyphVector. So in this case we need to verify
* that the text measures the same in both cases - ie that the
* layout attribute has no effect. If it does we can't always
* use the drawString call unless we can coerce the drawString call
* into measuring and displaying the string to the same length.
* That is the case where there is only one font used and we can
* specify the overall advance of the string. (See below).
*/
Point2D gvAdvancePt = g.getGlyphPosition(numGlyphs);
float gvAdvanceX = (float) gvAdvancePt.getX();
boolean layoutAffectsAdvance = false;
if (font.hasLayoutAttributes() && printingGlyphVector && noPositionAdjustments) {
/* If TRACKING is in use then the glyph vector will report
* position adjustments, then that ought to be sufficient to
* tell us we can't just ask native to do "drawString". But layout
* always sets the position adjustment flag, so we don't believe
* it and verify the positions are really different than
* createGlyphVector() (with no layout) would create. However
* inconsistently, TRACKING is applied when creating a GlyphVector,
* since it doesn't actually require "layout" (even though its
* considered a layout attribute), it just requires a fractional
* tweak to the[default]advances. So we need to specifically
* check for tracking until such time as as we can trust
* the GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS bit.
*/
Map<TextAttribute, ?> map = font.getAttributes();
Object o = map.get(TextAttribute.TRACKING);
boolean tracking = o != null && (o instanceof Number) && (((Number) o).floatValue() != 0f);
if (tracking) {
noPositionAdjustments = false;
} else {
Rectangle2D bounds = font.getStringBounds(str, gvFrc);
float strAdvanceX = (float) bounds.getWidth();
if (Math.abs(strAdvanceX - gvAdvanceX) > 0.00001) {
layoutAffectsAdvance = true;
}
}
}
if (compatibleFRC && noPositionAdjustments && !layoutAffectsAdvance) {
drawString(str, x, y, font, gvFrc, 0f);
return true;
}
/* If positions have not been explicitly assigned, we can
* ask the string to be drawn adjusted to this width.
* This call is supported only in the PS generator.
* GDI has API to specify the advance for each glyph in a
* string which could be used here too, but that is not yet
* implemented, and we'd need to update the signature of the
* drawString method to take the advances (ie relative positions)
* and use that instead of the width.
*/
if (numFonts == 1 && canDrawStringToWidth() && noPositionAdjustments) {
drawString(str, x, y, font, gvFrc, gvAdvanceX);
return true;
}
/* In some scripts chars drawn individually do not have the
* same representation (glyphs) as when combined with other chars.
* The logic here is erring on the side of caution, in particular
* in including supplementary characters.
*/
if (FontUtilities.isComplexText(chars, 0, chars.length)) {
return printGlyphVector(g, x, y);
}
/* If we reach here we have mapped all the glyphs back
* one-to-one to simple unicode chars that we know are in the font.
* We can call "drawChars" on each one of them in turn, setting
* the position based on the glyph positions.
* There's typically overhead in this. If numGlyphs is 'large',
* it may even be better to try printGlyphVector() in this case.
* This may be less recoverable for apps, but sophisticated apps
* should be able to recover the text from simple glyph vectors
* and we can avoid penalising the more common case - although
* this is already a minority case.
*/
if (numGlyphs > 10 && printGlyphVector(g, x, y)) {
return true;
}
for (int i = 0; i < numGlyphs; i++) {
String s = new String(chars, i, 1);
drawString(s, x + positions[i * 2], y + positions[i * 2 + 1], font, gvFrc, 0f);
}
return true;
}
use of java.awt.font.GlyphVector in project jdk8u_jdk by JetBrains.
the class StyledFontLayoutTest method runTest.
private static void runTest() {
im = new BufferedImage(W, H, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = im.createGraphics();
g2d.setColor(Color.white);
g2d.fillRect(0, 0, W, H);
g2d.setColor(Color.black);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
char[] chs = "Sample Text.".toCharArray();
int len = chs.length;
int x = 50, y = 100;
FontRenderContext frc = g2d.getFontRenderContext();
Font plain = new Font("Serif", Font.PLAIN, 48);
GlyphVector pgv = plain.layoutGlyphVector(frc, chs, 0, len, 0);
g2d.setFont(plain);
g2d.drawChars(chs, 0, len, x, y);
y += 50;
g2d.drawGlyphVector(pgv, x, y);
y += 50;
Rectangle2D plainStrBounds = plain.getStringBounds(chs, 0, len, frc);
Rectangle2D plainGVBounds = pgv.getLogicalBounds();
Font bold = new Font("Serif", Font.BOLD, 48);
GlyphVector bgv = bold.layoutGlyphVector(frc, chs, 0, len, 0);
Rectangle2D boldStrBounds = bold.getStringBounds(chs, 0, len, frc);
Rectangle2D boldGVBounds = bgv.getLogicalBounds();
g2d.setFont(bold);
g2d.drawChars(chs, 0, len, x, y);
y += 50;
g2d.drawGlyphVector(bgv, x, y);
System.out.println("Plain String Bounds = " + plainStrBounds);
System.out.println("Bold String Bounds = " + boldStrBounds);
System.out.println("Plain GlyphVector Bounds = " + plainGVBounds);
System.out.println("Bold GlyphVector Bounds = " + boldGVBounds);
if (!plainStrBounds.equals(boldStrBounds) && plainGVBounds.equals(boldGVBounds)) {
System.out.println("Test failed: Plain GV bounds same as Bold");
if (!interactive) {
throw new RuntimeException("Plain GV bounds same as Bold");
}
}
}
use of java.awt.font.GlyphVector in project jdk8u_jdk by JetBrains.
the class HelvLtOblTest method paintComponent.
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
FontRenderContext frc = new FontRenderContext(null, true, true);
Font f = helvFont.deriveFont(Font.PLAIN, 40);
System.out.println("font = " + f.getFontName());
GlyphVector gv = f.createGlyphVector(frc, codes);
g.setFont(f);
g.setColor(Color.white);
g.fillRect(0, 0, 400, 400);
g.setColor(Color.black);
g2.drawGlyphVector(gv, 5, 200);
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2.drawString(str, 5, 250);
}
Aggregations