1 /*
   2  * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test
  26  * @key headful
  27  * @bug 8015556
  28  * @summary Surrogate pairs do not render properly on MacOS X.
  29  */
  30 
  31 import java.util.Locale;
  32 import java.awt.*;
  33 import java.awt.font.*;
  34 import javax.swing.*;
  35 
  36 public class SuppCharTest {
  37 
  38    static String str = "ABC\uD840\uDC01\uD840\uDC00AB";
  39    static String EXTB_FONT = "MingLiU-ExtB";
  40 
  41    public static void main(String args[]) throws Exception {
  42 
  43       final Font font = new Font(EXTB_FONT, Font.PLAIN, 36);
  44       if (!EXTB_FONT.equalsIgnoreCase(font.getFamily(Locale.ENGLISH))) {
  45          return;
  46       }
  47 
  48       SwingUtilities.invokeLater(new Runnable(){
  49         @Override
  50         public void run(){
  51             JFrame f = new JFrame("Test Supplementary Char Support");
  52             Component c = new SuppCharComp(font, str);
  53             f.add("Center", c);
  54             JButton b = new JButton(str);
  55             b.setFont(font);
  56             f.add("South", b);
  57             f.pack();
  58             f.setVisible(true);
  59         }
  60       });
  61 
  62       /* If a supplementary character was found, 'invisible glyphs'
  63        * with value 65535 will be inserted in the place of the 2nd (low)
  64        * char index. So we are looking here to make sure such substitutions
  65        * took place.
  66        */
  67       FontRenderContext frc = new FontRenderContext(null, false, false);
  68       GlyphVector gv = font.createGlyphVector(frc, str);
  69       int numGlyphs = gv.getNumGlyphs();
  70       int[] codes = gv.getGlyphCodes(0, numGlyphs, null);
  71       boolean foundInvisibleGlyph = false;
  72       for (int i=0; i<numGlyphs;i++) {
  73            if (codes[i] == 65535) {
  74                foundInvisibleGlyph = true;
  75                break;
  76            }
  77       }
  78 
  79       if (!foundInvisibleGlyph) {
  80            throw new RuntimeException("No invisible glyphs");
  81       }
  82 
  83       if (font.canDisplayUpTo(str) != -1) {
  84           throw new RuntimeException("Font can't display all chars");
  85       }
  86 
  87    }
  88 }
  89 
  90 class SuppCharComp extends Component {
  91 
  92   static final int w=400, h=250;
  93   public Dimension preferredSize() {
  94      return new Dimension(w,h);
  95   }
  96 
  97   String str = null;
  98   Font font = null;
  99   public SuppCharComp(Font font, String str) {
 100     this.font = font;
 101     this.str = str;
 102   }
 103   public void paint(Graphics g) {
 104      Graphics2D g2d = (Graphics2D)g.create();
 105      g2d.setColor(Color.white);
 106      g2d.fillRect(0,0,w,h);
 107      g2d.setColor(Color.black);
 108      int y = 0;
 109      g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
 110                           RenderingHints.VALUE_FRACTIONALMETRICS_ON);
 111      g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
 112                           RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
 113 
 114      g2d.setFont(font);
 115      g2d.drawString(str, 10, 50);
 116 
 117      FontRenderContext frc = g2d.getFontRenderContext();
 118      GlyphVector gv = font.createGlyphVector(frc, str);
 119      g2d.drawGlyphVector(gv, 10, 100);
 120      TextLayout tl = new TextLayout(str, font, frc);
 121      tl.draw(g2d, 10, 150);
 122      char[] ca = str.toCharArray();
 123      g2d.drawChars(ca, 0, ca.length, 10, 200);
 124 
 125   }
 126 
 127 }
 128