1 /*
   2  *
   3  * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  *
   9  *   - Redistributions of source code must retain the above copyright
  10  *     notice, this list of conditions and the following disclaimer.
  11  *
  12  *   - Redistributions in binary form must reproduce the above copyright
  13  *     notice, this list of conditions and the following disclaimer in the
  14  *     documentation and/or other materials provided with the distribution.
  15  *
  16  *   - Neither the name of Oracle nor the names of its
  17  *     contributors may be used to endorse or promote products derived
  18  *     from this software without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  21  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31  */
  32 package java2d.demos.Fonts;
  33 
  34 
  35 import static java.awt.Color.BLACK;
  36 import static java.awt.Color.CYAN;
  37 import static java.awt.Color.LIGHT_GRAY;
  38 import static java.awt.Color.WHITE;
  39 import java.awt.Color;
  40 import java.awt.Font;
  41 import java.awt.Graphics2D;
  42 import java.awt.Shape;
  43 import java.awt.font.FontRenderContext;
  44 import java.awt.font.TextHitInfo;
  45 import java.awt.font.TextLayout;
  46 import java.awt.geom.AffineTransform;
  47 import java.awt.geom.Rectangle2D;
  48 import java2d.AnimatingSurface;
  49 
  50 
  51 /**
  52  * Highlighting of text showing the caret, the highlight & the character
  53  * advances.
  54  */
  55 @SuppressWarnings("serial")
  56 public class Highlighting extends AnimatingSurface {
  57 
  58     private static String[] text = { "HIGHLIGHTING", "OpenJDK" };
  59     private static Color[] colors = { CYAN, LIGHT_GRAY };
  60     private static Font smallF = new Font("Monospaced", Font.PLAIN, 8);
  61     private int[] curPos;
  62     private TextLayout[] layouts;
  63     private Font[] fonts;
  64 
  65     public Highlighting() {
  66         setBackground(WHITE);
  67         fonts = new Font[2];
  68         layouts = new TextLayout[fonts.length];
  69         curPos = new int[fonts.length];
  70     }
  71 
  72     @Override
  73     public void reset(int w, int h) {
  74         fonts[0] = new Font("Monospaced", Font.PLAIN, w / text[0].length() + 8);
  75         fonts[1] = new Font("Serif", Font.BOLD, w / text[1].length());
  76         for (int i = 0; i < layouts.length; i++) {
  77             curPos[i] = 0;
  78         }
  79     }
  80 
  81     @Override
  82     public void step(int w, int h) {
  83         setSleepAmount(900);
  84         for (int i = 0; i < 2; i++) {
  85             if (layouts[i] == null) {
  86                 continue;
  87             }
  88             if (curPos[i]++ == layouts[i].getCharacterCount()) {
  89                 curPos[i] = 0;
  90             }
  91         }
  92     }
  93 
  94     @Override
  95     public void render(int w, int h, Graphics2D g2) {
  96         FontRenderContext frc = g2.getFontRenderContext();
  97         for (int i = 0; i < 2; i++) {
  98             layouts[i] = new TextLayout(text[i], fonts[i], frc);
  99             float rw = layouts[i].getAdvance();
 100             float rx = ((w - rw) / 2);
 101             float ry = ((i == 0) ? h / 3 : h * 0.75f);
 102 
 103             // draw highlighted shape
 104             Shape hilite = layouts[i].getLogicalHighlightShape(0, curPos[i]);
 105             AffineTransform at = AffineTransform.getTranslateInstance(rx, ry);
 106             hilite = at.createTransformedShape(hilite);
 107             float hy = (float) hilite.getBounds2D().getY();
 108             float hh = (float) hilite.getBounds2D().getHeight();
 109             g2.setColor(colors[i]);
 110             g2.fill(hilite);
 111 
 112             // get caret shape
 113             Shape[] shapes = layouts[i].getCaretShapes(curPos[i]);
 114             Shape caret = at.createTransformedShape(shapes[0]);
 115 
 116             g2.setColor(BLACK);
 117             layouts[i].draw(g2, rx, ry);
 118             g2.draw(caret);
 119             g2.draw(new Rectangle2D.Float(rx, hy, rw, hh));
 120 
 121             // Display character advances.
 122             for (int j = 0; j <= layouts[i].getCharacterCount(); j++) {
 123                 float[] cInfo = layouts[i].getCaretInfo(TextHitInfo.leading(j));
 124                 String str = String.valueOf((int) cInfo[0]);
 125                 TextLayout tl = new TextLayout(str, smallF, frc);
 126                 tl.draw(g2, rx + cInfo[0] - tl.getAdvance() / 2, hy + hh + tl.
 127                         getAscent() + 1.0f);
 128             }
 129         }
 130     }
 131 
 132     public static void main(String[] argv) {
 133         createDemoFrame(new Highlighting());
 134     }
 135 }