当前位置:   article > 正文

IDEA编译JDK1.8源码及运行测试_idea配置jdk1.8

idea配置jdk1.8

————————————————
版权声明:本文为CSDN博主「神韵499」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41055045/article/details/112002440
————————————————

目录

一、JDK源码源码导入IDEA前资源准备

1.在自己安装好的JDK1.8版本目录下,找到src.zip,这个就是源码(没有JDK1.8的自行去官网下载,我的版本是jdk1.8.0_271)

2.在自己电脑磁盘新建项目目录JDK1.8.0_271_source,将src解压到项目目录下,然后删掉src.zip

二、导入IDEA并配置

1.File-Open,找到自己项目导入

2.导进入后,你打开一个java文件会发现这个不可识别。此时需要将src标记为资源目录即可

3.设置编译内存,由原来的700改成1000或者更高,防止后面编译内存不足而失败

4.新建sun包,awt包和UNIXToolkit类,font包和FontConfigManager。类的具体内容文章最后面会给出

5.打开项目配置,将Jdk的lib目录下的tools.jar导入项目,编译所需要它

6.配置一个新的JDK,然后改名称,并配置源码为自己的代码 待会debug可以切换进来

三、编写测试类

1.在src目录下编写一个测试类MainTest.java并运行,便会自动编译(确保上面每一步做到位,编译才不会出错)

2.编译成功后,在自己源码HashMap构造函数加断点并加注释

3.debug运行MainTest.java进入源码

四、JDK缺少的类内容

1.sun.awt.UNIXToolkit

2.sun.font.FontConfigManager

一、JDK源码源码导入IDEA前资源准备
1.在自己安装好的JDK1.8版本目录下,找到src.zip,这个就是源码(没有JDK1.8的自行去官网下载,我的版本是jdk1.8.0_271)

2.在自己电脑磁盘新建项目目录JDK1.8.0_271_source,将src解压到项目目录下,然后删掉src.zip

二、导入IDEA并配置
1.File-Open,找到自己项目导入

最终项目目录效果
 

2.导进入后,你打开一个java文件会发现这个不可识别。此时需要将src标记为资源目录即可

 

3.设置编译内存,由原来的700改成1000或者更高,防止后面编译内存不足而失败

4.新建sun包,awt包和UNIXToolkit类,font包和FontConfigManager。类的具体内容文章最后面会给出

添加缺少内容

5.打开项目配置,将Jdk的lib目录下的tools.jar导入项目,编译所需要它

引入tools.jar

tools.jar

最终效果
 

6.配置一个新的JDK,然后改名称,并配置源码为自己的代码 待会debug可以切换进来

配置一个新的JDK

 

 

改名称

这一步是关键,设置了后,待会debug就可以切换成自己源码目录了


替换源码目录
Apply 保存以上所有配置,IDEA配置结束!

三、编写测试类
1.在src目录下编写一个测试类MainTest.java并运行,便会自动编译(确保上面每一步做到位,编译才不会出错)


提示设置输出class目录

 

点击OK,跳出目录,先在源码路径下建立文件夹out,然后设置在项目路径下out目录下即可

运行编译中

 

编译成功,用了差不多2分钟

2.编译成功后,在自己源码HashMap构造函数加断点并加注释
双击shift搜索HashMap,确保是进入本项目源码构造函数,而不是jdk自带的源码那


本项目下搜索​​​​
加断点和注释

 


给自己项目源码加断点加注释
 
3.debug运行MainTest.java进入源码


进自己源码还需要自行去切换,有些如果没有disable这个弹出,需要自己搜索去配置(https://blog.csdn.net/qq_28455613/article/details/81382484)

 

切换,进来了

最终完成编译与测试。

事后补充(重重重!!!)

这里有三个注意点

第一个是尽量不要将debug断点打在构造函数上,上面打在构造函数上是我的过失(上面会初始化很多HashMap容器,你应该打在已经初始化完成后的地方)

第二个是如果debug不能一步一步点进去,则需要将IDEA默认不支持JDK调试的开关打开,如下图

第三个是尽量不要新起注释行,否则导致和源码行号对不上,debug错位(其实我也不喜欢行尾注释,难...,还有解决方法,参考:写Java这么久,JDK源码编译过没?编译JDK源码踩坑纪实)

 

 四、JDK缺少的类内容

1.sun.awt.UNIXToolkit

  1. package sun.awt;
  2. /**
  3. * @author :HUANG ZHI XUE
  4. * @date :Create in 2020-12-31
  5. */
  6. import com.sun.java.swing.plaf.gtk.GTKConstants.TextDirection;
  7. import sun.java2d.opengl.OGLRenderQueue;
  8. import sun.security.action.GetIntegerAction;
  9. import sun.security.action.GetPropertyAction;
  10. import java.awt.*;
  11. import java.awt.color.ColorSpace;
  12. import java.awt.image.*;
  13. import java.security.AccessController;
  14. import java.security.PrivilegedAction;
  15. import static java.awt.RenderingHints.*;
  16. public abstract class UNIXToolkit extends SunToolkit
  17. {
  18. /** All calls into GTK should be synchronized on this lock */
  19. public static final Object GTK_LOCK = new Object();
  20. private static final int[] BAND_OFFSETS = { 0, 1, 2 };
  21. private static final int[] BAND_OFFSETS_ALPHA = { 0, 1, 2, 3 };
  22. private static final int DEFAULT_DATATRANSFER_TIMEOUT = 10000;
  23. // Allowed GTK versions
  24. public enum GtkVersions {
  25. ANY(0),
  26. GTK2(Constants.GTK2_MAJOR_NUMBER),
  27. GTK3(Constants.GTK3_MAJOR_NUMBER);
  28. static class Constants {
  29. static final int GTK2_MAJOR_NUMBER = 2;
  30. static final int GTK3_MAJOR_NUMBER = 3;
  31. }
  32. final int number;
  33. GtkVersions(int number) {
  34. this.number = number;
  35. }
  36. public static GtkVersions getVersion(int number) {
  37. switch (number) {
  38. case Constants.GTK2_MAJOR_NUMBER:
  39. return GTK2;
  40. case Constants.GTK3_MAJOR_NUMBER:
  41. return GTK3;
  42. default:
  43. return ANY;
  44. }
  45. }
  46. // major GTK version number
  47. public int getNumber() {
  48. return number;
  49. }
  50. };
  51. private Boolean nativeGTKAvailable;
  52. private Boolean nativeGTKLoaded;
  53. private BufferedImage tmpImage = null;
  54. public static int getDatatransferTimeout() {
  55. Integer dt = (Integer)AccessController.doPrivileged(
  56. new GetIntegerAction("sun.awt.datatransfer.timeout"));
  57. if (dt == null || dt <= 0) {
  58. return DEFAULT_DATATRANSFER_TIMEOUT;
  59. } else {
  60. return dt;
  61. }
  62. }
  63. /**
  64. * Returns true if the native GTK libraries are capable of being
  65. * loaded and are expected to work properly, false otherwise. Note
  66. * that this method will not leave the native GTK libraries loaded if
  67. * they haven't already been loaded. This allows, for example, Swing's
  68. * GTK L&F to test for the presence of native GTK support without
  69. * leaving the native libraries loaded. To attempt long-term loading
  70. * of the native GTK libraries, use the loadGTK() method instead.
  71. */
  72. @Override
  73. public boolean isNativeGTKAvailable() {
  74. synchronized (GTK_LOCK) {
  75. if (nativeGTKLoaded != null) {
  76. // We've already attempted to load GTK, so just return the
  77. // status of that attempt.
  78. return nativeGTKLoaded;
  79. } else if (nativeGTKAvailable != null) {
  80. // We've already checked the availability of the native GTK
  81. // libraries, so just return the status of that attempt.
  82. return nativeGTKAvailable;
  83. } else {
  84. boolean success = check_gtk(getEnabledGtkVersion().getNumber());
  85. nativeGTKAvailable = success;
  86. return success;
  87. }
  88. }
  89. }
  90. /**
  91. * Loads the GTK libraries, if necessary. The first time this method
  92. * is called, it will attempt to load the native GTK library. If
  93. * successful, it leaves the library open and returns true; otherwise,
  94. * the library is left closed and returns false. On future calls to
  95. * this method, the status of the first attempt is returned (a simple
  96. * lightweight boolean check, no native calls required).
  97. */
  98. public boolean loadGTK() {
  99. synchronized (GTK_LOCK) {
  100. if (nativeGTKLoaded == null) {
  101. nativeGTKLoaded = load_gtk(getEnabledGtkVersion().getNumber(),
  102. isGtkVerbose());
  103. }
  104. }
  105. return nativeGTKLoaded;
  106. }
  107. /**
  108. * Overridden to handle GTK icon loading
  109. */
  110. protected Object lazilyLoadDesktopProperty(String name) {
  111. if (name.startsWith("gtk.icon.")) {
  112. return lazilyLoadGTKIcon(name);
  113. }
  114. return super.lazilyLoadDesktopProperty(name);
  115. }
  116. /**
  117. * Load a native Gtk stock icon.
  118. *
  119. * @param longname a desktop property name. This contains icon name, size
  120. * and orientation, e.g. <code>"gtk.icon.gtk-add.4.rtl"</code>
  121. * @return an <code>Image</code> for the icon, or <code>null</code> if the
  122. * icon could not be loaded
  123. */
  124. protected Object lazilyLoadGTKIcon(String longname) {
  125. // Check if we have already loaded it.
  126. Object result = desktopProperties.get(longname);
  127. if (result != null) {
  128. return result;
  129. }
  130. // We need to have at least gtk.icon.<stock_id>.<size>.<orientation>
  131. String str[] = longname.split("\\.");
  132. if (str.length != 5) {
  133. return null;
  134. }
  135. // Parse out the stock icon size we are looking for.
  136. int size = 0;
  137. try {
  138. size = Integer.parseInt(str[3]);
  139. } catch (NumberFormatException nfe) {
  140. return null;
  141. }
  142. // Direction.
  143. TextDirection dir = ("ltr".equals(str[4]) ? TextDirection.LTR :
  144. TextDirection.RTL);
  145. // Load the stock icon.
  146. BufferedImage img = getStockIcon(-1, str[2], size, dir.ordinal(), null);
  147. if (img != null) {
  148. // Create the desktop property for the icon.
  149. setDesktopProperty(longname, img);
  150. }
  151. return img;
  152. }
  153. /**
  154. * Returns a BufferedImage which contains the Gtk icon requested. If no
  155. * such icon exists or an error occurs loading the icon the result will
  156. * be null.
  157. *
  158. * @param filename
  159. * @return The icon or null if it was not found or loaded.
  160. */
  161. public BufferedImage getGTKIcon(final String filename) {
  162. if (!loadGTK()) {
  163. return null;
  164. } else {
  165. // Call the native method to load the icon.
  166. synchronized (GTK_LOCK) {
  167. if (!load_gtk_icon(filename)) {
  168. tmpImage = null;
  169. }
  170. }
  171. }
  172. // Return local image the callback loaded the icon into.
  173. return tmpImage;
  174. }
  175. /**
  176. * Returns a BufferedImage which contains the Gtk stock icon requested.
  177. * If no such stock icon exists the result will be null.
  178. *
  179. * @param widgetType one of WidgetType values defined in GTKNativeEngine or
  180. * -1 for system default stock icon.
  181. * @param stockId String which defines the stock id of the gtk item.
  182. * For a complete list reference the API at www.gtk.org for StockItems.
  183. * @param iconSize One of the GtkIconSize values defined in GTKConstants
  184. * @param textDirection One of the TextDirection values defined in
  185. * GTKConstants
  186. * @param detail Render detail that is passed to the native engine (feel
  187. * free to pass null)
  188. * @return The stock icon or null if it was not found or loaded.
  189. */
  190. public BufferedImage getStockIcon(final int widgetType, final String stockId,
  191. final int iconSize, final int direction,
  192. final String detail) {
  193. if (!loadGTK()) {
  194. return null;
  195. } else {
  196. // Call the native method to load the icon.
  197. synchronized (GTK_LOCK) {
  198. if (!load_stock_icon(widgetType, stockId, iconSize, direction, detail)) {
  199. tmpImage = null;
  200. }
  201. }
  202. }
  203. // Return local image the callback loaded the icon into.
  204. return tmpImage; // set by loadIconCallback
  205. }
  206. /**
  207. * This method is used by JNI as a callback from load_stock_icon.
  208. * Image data is passed back to us via this method and loaded into the
  209. * local BufferedImage and then returned via getStockIcon.
  210. *
  211. * Do NOT call this method directly.
  212. */
  213. public void loadIconCallback(byte[] data, int width, int height,
  214. int rowStride, int bps, int channels, boolean alpha) {
  215. // Reset the stock image to null.
  216. tmpImage = null;
  217. // Create a new BufferedImage based on the data returned from the
  218. // JNI call.
  219. DataBuffer dataBuf = new DataBufferByte(data, (rowStride * height));
  220. // Maybe test # channels to determine band offsets?
  221. WritableRaster raster = Raster.createInterleavedRaster(dataBuf,
  222. width, height, rowStride, channels,
  223. (alpha ? BAND_OFFSETS_ALPHA : BAND_OFFSETS), null);
  224. ColorModel colorModel = new ComponentColorModel(
  225. ColorSpace.getInstance(ColorSpace.CS_sRGB), alpha, false,
  226. ColorModel.TRANSLUCENT, DataBuffer.TYPE_BYTE);
  227. // Set the local image so we can return it later from
  228. // getStockIcon().
  229. tmpImage = new BufferedImage(colorModel, raster, false, null);
  230. }
  231. private static native boolean check_gtk(int version);
  232. private static native boolean load_gtk(int version, boolean verbose);
  233. private static native boolean unload_gtk();
  234. private native boolean load_gtk_icon(String filename);
  235. private native boolean load_stock_icon(int widget_type, String stock_id,
  236. int iconSize, int textDirection, String detail);
  237. private native void nativeSync();
  238. private static native int get_gtk_version();
  239. @Override
  240. public void sync() {
  241. // flush the X11 buffer
  242. nativeSync();
  243. // now flush the OGL pipeline (this is a no-op if OGL is not enabled)
  244. OGLRenderQueue.sync();
  245. }
  246. /*
  247. * This returns the value for the desktop property "awt.font.desktophints"
  248. * It builds this by querying the Gnome desktop properties to return
  249. * them as platform independent hints.
  250. * This requires that the Gnome properties have already been gathered.
  251. */
  252. public static final String FONTCONFIGAAHINT = "fontconfig/Antialias";
  253. @Override
  254. protected RenderingHints getDesktopAAHints() {
  255. Object aaValue = getDesktopProperty("gnome.Xft/Antialias");
  256. if (aaValue == null) {
  257. /* On a KDE desktop running KWin the rendering hint will
  258. * have been set as property "fontconfig/Antialias".
  259. * No need to parse further in this case.
  260. */
  261. aaValue = getDesktopProperty(FONTCONFIGAAHINT);
  262. if (aaValue != null) {
  263. return new RenderingHints(KEY_TEXT_ANTIALIASING, aaValue);
  264. } else {
  265. return null; // no Gnome or KDE Desktop properties available.
  266. }
  267. }
  268. /* 0 means off, 1 means some ON. What would any other value mean?
  269. * If we require "1" to enable AA then some new value would cause
  270. * us to default to "OFF". I don't think that's the best guess.
  271. * So if its !=0 then lets assume AA.
  272. */
  273. boolean aa = ((aaValue instanceof Number)
  274. && ((Number) aaValue).intValue() != 0);
  275. Object aaHint;
  276. if (aa) {
  277. String subpixOrder =
  278. (String)getDesktopProperty("gnome.Xft/RGBA");
  279. if (subpixOrder == null || subpixOrder.equals("none")) {
  280. aaHint = VALUE_TEXT_ANTIALIAS_ON;
  281. } else if (subpixOrder.equals("rgb")) {
  282. aaHint = VALUE_TEXT_ANTIALIAS_LCD_HRGB;
  283. } else if (subpixOrder.equals("bgr")) {
  284. aaHint = VALUE_TEXT_ANTIALIAS_LCD_HBGR;
  285. } else if (subpixOrder.equals("vrgb")) {
  286. aaHint = VALUE_TEXT_ANTIALIAS_LCD_VRGB;
  287. } else if (subpixOrder.equals("vbgr")) {
  288. aaHint = VALUE_TEXT_ANTIALIAS_LCD_VBGR;
  289. } else {
  290. /* didn't recognise the string, but AA is requested */
  291. aaHint = VALUE_TEXT_ANTIALIAS_ON;
  292. }
  293. } else {
  294. aaHint = VALUE_TEXT_ANTIALIAS_DEFAULT;
  295. }
  296. return new RenderingHints(KEY_TEXT_ANTIALIASING, aaHint);
  297. }
  298. private native boolean gtkCheckVersionImpl(int major, int minor,
  299. int micro);
  300. /**
  301. * Returns {@code true} if the GTK+ library is compatible with the given
  302. * version.
  303. *
  304. * @param major
  305. * The required major version.
  306. * @param minor
  307. * The required minor version.
  308. * @param micro
  309. * The required micro version.
  310. * @return {@code true} if the GTK+ library is compatible with the given
  311. * version.
  312. */
  313. public boolean checkGtkVersion(int major, int minor, int micro) {
  314. if (loadGTK()) {
  315. return gtkCheckVersionImpl(major, minor, micro);
  316. }
  317. return false;
  318. }
  319. public static GtkVersions getEnabledGtkVersion() {
  320. String version = AccessController.doPrivileged(
  321. new GetPropertyAction("jdk.gtk.version"));
  322. if (version == null) {
  323. return GtkVersions.ANY;
  324. } else if (version.startsWith("2")) {
  325. return GtkVersions.GTK2;
  326. } else if("3".equals(version) ){
  327. return GtkVersions.GTK3;
  328. }
  329. return GtkVersions.ANY;
  330. }
  331. public static GtkVersions getGtkVersion() {
  332. return GtkVersions.getVersion(get_gtk_version());
  333. }
  334. public static boolean isGtkVerbose() {
  335. return AccessController.doPrivileged((PrivilegedAction<Boolean>)()
  336. -> Boolean.getBoolean("jdk.gtk.verbose"));
  337. }
  338. }

2.sun.font.FontConfigManager

  1. package sun.font;
  2. /**
  3. * @author :HUANG ZHI XUE
  4. * @date :Create in 2020-12-31
  5. */
  6. import sun.awt.SunHints;
  7. import sun.awt.SunToolkit;
  8. import sun.util.logging.PlatformLogger;
  9. import java.util.Locale;
  10. /**
  11. * Small utility class to manage FontConfig.
  12. */
  13. public class FontConfigManager {
  14. static boolean fontConfigFailed = false;
  15. /* This is populated by native */
  16. private static final FontConfigInfo fcInfo = new FontConfigInfo();
  17. /* Begin support for GTK Look and Feel - query libfontconfig and
  18. * return a composite Font to Swing that uses the desktop font(s).
  19. */
  20. /* These next three classes are just data structures.
  21. */
  22. public static class FontConfigFont {
  23. public String familyName; // eg Bitstream Vera Sans
  24. public String styleStr; // eg Bold
  25. public String fullName; // eg Bitstream Vera Sans Bold
  26. public String fontFile; // eg /usr/X11/lib/fonts/foo.ttf
  27. }
  28. public static class FcCompFont {
  29. public String fcName; // eg sans
  30. public String fcFamily; // eg sans
  31. public String jdkName; // eg sansserif
  32. public int style; // eg 0=PLAIN
  33. public FontConfigFont firstFont;
  34. public FontConfigFont[] allFonts;
  35. //boolean preferBitmaps; // if embedded bitmaps preferred over AA
  36. public CompositeFont compFont; // null if not yet created/known.
  37. }
  38. public static class FontConfigInfo {
  39. public int fcVersion;
  40. public String[] cacheDirs = new String[4];
  41. }
  42. /* fontconfig recognises slants roman, italic, as well as oblique,
  43. * and a slew of weights, where the ones that matter here are
  44. * regular and bold.
  45. * To fully qualify what we want, we can for example ask for (eg)
  46. * Font.PLAIN : "serif:regular:roman"
  47. * Font.BOLD : "serif:bold:roman"
  48. * Font.ITALIC : "serif:regular:italic"
  49. * Font.BOLD|Font.ITALIC : "serif:bold:italic"
  50. */
  51. private static String[] fontConfigNames = {
  52. "sans:regular:roman",
  53. "sans:bold:roman",
  54. "sans:regular:italic",
  55. "sans:bold:italic",
  56. "serif:regular:roman",
  57. "serif:bold:roman",
  58. "serif:regular:italic",
  59. "serif:bold:italic",
  60. "monospace:regular:roman",
  61. "monospace:bold:roman",
  62. "monospace:regular:italic",
  63. "monospace:bold:italic",
  64. };
  65. /* This array has the array elements created in Java code and is
  66. * passed down to native to be filled in.
  67. */
  68. private FcCompFont[] fontConfigFonts;
  69. /**
  70. * Instantiates a new FontConfigManager getting the default instance
  71. * of FontManager from the FontManagerFactory.
  72. */
  73. public FontConfigManager() {
  74. }
  75. /* Called from code that needs to know what are the AA settings
  76. * that apps using FC would pick up for the default desktop font.
  77. * Note apps can change the default desktop font. etc, so this
  78. * isn't certain to be right but its going to correct for most cases.
  79. * Native return values map to the text aa values in sun.awt.SunHints.
  80. * which is used to look up the renderinghint value object.
  81. */
  82. public static Object getFontConfigAAHint() {
  83. return getFontConfigAAHint("sans");
  84. }
  85. /* This is public solely so that for debugging purposes it can be called
  86. * with other names, which might (eg) include a size, eg "sans-24"
  87. * The return value is a text aa rendering hint value.
  88. * Normally we should call the no-args version.
  89. */
  90. public static Object getFontConfigAAHint(String fcFamily) {
  91. if (FontUtilities.isWindows) {
  92. return null;
  93. } else {
  94. int hint = getFontConfigAASettings(getFCLocaleStr(), fcFamily);
  95. if (hint < 0) {
  96. return null;
  97. } else {
  98. return SunHints.Value.get(SunHints.INTKEY_TEXT_ANTIALIASING,
  99. hint);
  100. }
  101. }
  102. }
  103. private static String getFCLocaleStr() {
  104. Locale l = SunToolkit.getStartupLocale();
  105. String localeStr = l.getLanguage();
  106. String country = l.getCountry();
  107. if (!country.equals("")) {
  108. localeStr = localeStr + "-" + country;
  109. }
  110. return localeStr;
  111. }
  112. /* This does cause the native libfontconfig to be loaded and unloaded,
  113. * but it does not incur the overhead of initialisation of its
  114. * data structures, so shouldn't have a measurable impact.
  115. */
  116. public static native int getFontConfigVersion();
  117. /* This can be made public if it's needed to force a re-read
  118. * rather than using the cached values. The re-read would be needed
  119. * only if some event signalled that the fontconfig has changed.
  120. * In that event this method would need to return directly the array
  121. * to be used by the caller in case it subsequently changed.
  122. */
  123. public synchronized void initFontConfigFonts(boolean includeFallbacks) {
  124. if (fontConfigFonts != null) {
  125. if (!includeFallbacks || (fontConfigFonts[0].allFonts != null)) {
  126. return;
  127. }
  128. }
  129. if (FontUtilities.isWindows || fontConfigFailed) {
  130. return;
  131. }
  132. long t0 = 0;
  133. if (FontUtilities.isLogging()) {
  134. t0 = System.nanoTime();
  135. }
  136. FcCompFont[] fontArr = new FcCompFont[fontConfigNames.length];
  137. for (int i = 0; i< fontArr.length; i++) {
  138. fontArr[i] = new FcCompFont();
  139. fontArr[i].fcName = fontConfigNames[i];
  140. int colonPos = fontArr[i].fcName.indexOf(':');
  141. fontArr[i].fcFamily = fontArr[i].fcName.substring(0, colonPos);
  142. fontArr[i].jdkName = FontUtilities.mapFcName(fontArr[i].fcFamily);
  143. fontArr[i].style = i % 4; // depends on array order.
  144. }
  145. getFontConfig(getFCLocaleStr(), fcInfo, fontArr, includeFallbacks);
  146. FontConfigFont anyFont = null;
  147. /* If don't find anything (eg no libfontconfig), then just return */
  148. for (int i = 0; i< fontArr.length; i++) {
  149. FcCompFont fci = fontArr[i];
  150. if (fci.firstFont == null) {
  151. if (FontUtilities.isLogging()) {
  152. PlatformLogger logger = FontUtilities.getLogger();
  153. logger.info("Fontconfig returned no font for " +
  154. fontArr[i].fcName);
  155. }
  156. fontConfigFailed = true;
  157. } else if (anyFont == null) {
  158. anyFont = fci.firstFont;
  159. }
  160. }
  161. if (anyFont == null) {
  162. if (FontUtilities.isLogging()) {
  163. PlatformLogger logger = FontUtilities.getLogger();
  164. logger.info("Fontconfig returned no fonts at all.");
  165. }
  166. fontConfigFailed = true;
  167. return;
  168. } else if (fontConfigFailed) {
  169. for (int i = 0; i< fontArr.length; i++) {
  170. if (fontArr[i].firstFont == null) {
  171. fontArr[i].firstFont = anyFont;
  172. }
  173. }
  174. }
  175. fontConfigFonts = fontArr;
  176. if (FontUtilities.isLogging()) {
  177. PlatformLogger logger = FontUtilities.getLogger();
  178. long t1 = System.nanoTime();
  179. logger.info("Time spent accessing fontconfig="
  180. + ((t1 - t0) / 1000000) + "ms.");
  181. for (int i = 0; i< fontConfigFonts.length; i++) {
  182. FcCompFont fci = fontConfigFonts[i];
  183. logger.info("FC font " + fci.fcName+" maps to family " +
  184. fci.firstFont.familyName +
  185. " in file " + fci.firstFont.fontFile);
  186. if (fci.allFonts != null) {
  187. for (int f=0;f<fci.allFonts.length;f++) {
  188. FontConfigFont fcf = fci.allFonts[f];
  189. logger.info("Family=" + fcf.familyName +
  190. " Style="+ fcf.styleStr +
  191. " Fullname="+fcf.fullName +
  192. " File="+fcf.fontFile);
  193. }
  194. }
  195. }
  196. }
  197. }
  198. public PhysicalFont registerFromFcInfo(FcCompFont fcInfo) {
  199. SunFontManager fm = SunFontManager.getInstance();
  200. /* If it's a TTC file we need to know that as we will need to
  201. * make sure we return the right font */
  202. String fontFile = fcInfo.firstFont.fontFile;
  203. int offset = fontFile.length()-4;
  204. if (offset <= 0) {
  205. return null;
  206. }
  207. String ext = fontFile.substring(offset).toLowerCase();
  208. boolean isTTC = ext.equals(".ttc");
  209. /* If this file is already registered, can just return its font.
  210. * However we do need to check in case it's a TTC as we need
  211. * a specific font, so rather than directly returning it, let
  212. * findFont2D resolve that.
  213. */
  214. PhysicalFont physFont = fm.getRegisteredFontFile(fontFile);
  215. if (physFont != null) {
  216. if (isTTC) {
  217. Font2D f2d = fm.findFont2D(fcInfo.firstFont.familyName,
  218. fcInfo.style,
  219. FontManager.NO_FALLBACK);
  220. if (f2d instanceof PhysicalFont) { /* paranoia */
  221. return (PhysicalFont)f2d;
  222. } else {
  223. return null;
  224. }
  225. } else {
  226. return physFont;
  227. }
  228. }
  229. /* If the font may hide a JRE font (eg fontconfig says it is
  230. * Lucida Sans), we want to use the JRE version, so make it
  231. * point to the JRE font.
  232. */
  233. physFont = fm.findJREDeferredFont(fcInfo.firstFont.familyName,
  234. fcInfo.style);
  235. /* It is also possible the font file is on the "deferred" list,
  236. * in which case we can just initialise it now.
  237. */
  238. if (physFont == null &&
  239. fm.isDeferredFont(fontFile) == true) {
  240. physFont = fm.initialiseDeferredFont(fcInfo.firstFont.fontFile);
  241. /* use findFont2D to get the right font from TTC's */
  242. if (physFont != null) {
  243. if (isTTC) {
  244. Font2D f2d = fm.findFont2D(fcInfo.firstFont.familyName,
  245. fcInfo.style,
  246. FontManager.NO_FALLBACK);
  247. if (f2d instanceof PhysicalFont) { /* paranoia */
  248. return (PhysicalFont)f2d;
  249. } else {
  250. return null;
  251. }
  252. } else {
  253. return physFont;
  254. }
  255. }
  256. }
  257. /* In the majority of cases we reach here, and need to determine
  258. * the type and rank to register the font.
  259. */
  260. if (physFont == null) {
  261. int fontFormat = SunFontManager.FONTFORMAT_NONE;
  262. int fontRank = Font2D.UNKNOWN_RANK;
  263. if (ext.equals(".ttf") || isTTC) {
  264. fontFormat = SunFontManager.FONTFORMAT_TRUETYPE;
  265. fontRank = Font2D.TTF_RANK;
  266. } else if (ext.equals(".pfa") || ext.equals(".pfb")) {
  267. fontFormat = SunFontManager.FONTFORMAT_TYPE1;
  268. fontRank = Font2D.TYPE1_RANK;
  269. }
  270. physFont = fm.registerFontFile(fcInfo.firstFont.fontFile, null,
  271. fontFormat, true, fontRank);
  272. }
  273. return physFont;
  274. }
  275. /*
  276. * We need to return a Composite font which has as the font in
  277. * its first slot one obtained from fontconfig.
  278. */
  279. public CompositeFont getFontConfigFont(String name, int style) {
  280. name = name.toLowerCase();
  281. initFontConfigFonts(false);
  282. if (fontConfigFonts == null) {
  283. // This avoids an immediate NPE if fontconfig look up failed
  284. // but doesn't guarantee this is a recoverable situation.
  285. return null;
  286. }
  287. FcCompFont fcInfo = null;
  288. for (int i=0; i<fontConfigFonts.length; i++) {
  289. if (name.equals(fontConfigFonts[i].fcFamily) &&
  290. style == fontConfigFonts[i].style) {
  291. fcInfo = fontConfigFonts[i];
  292. break;
  293. }
  294. }
  295. if (fcInfo == null) {
  296. fcInfo = fontConfigFonts[0];
  297. }
  298. if (FontUtilities.isLogging()) {
  299. FontUtilities.getLogger()
  300. .info("FC name=" + name + " style=" + style +
  301. " uses " + fcInfo.firstFont.familyName +
  302. " in file: " + fcInfo.firstFont.fontFile);
  303. }
  304. if (fcInfo.compFont != null) {
  305. return fcInfo.compFont;
  306. }
  307. /* jdkFont is going to be used for slots 1..N and as a fallback.
  308. * Slot 0 will be the physical font from fontconfig.
  309. */
  310. FontManager fm = FontManagerFactory.getInstance();
  311. CompositeFont jdkFont = (CompositeFont)
  312. fm.findFont2D(fcInfo.jdkName, style, FontManager.LOGICAL_FALLBACK);
  313. if (fcInfo.firstFont.familyName == null ||
  314. fcInfo.firstFont.fontFile == null) {
  315. return (fcInfo.compFont = jdkFont);
  316. }
  317. /* First, see if the family and exact style is already registered.
  318. * If it is, use it. If it's not, then try to register it.
  319. * If that registration fails (signalled by null) just return the
  320. * regular JDK composite.
  321. * Algorithmically styled fonts won't match on exact style, so
  322. * will fall through this code, but the regisration code will
  323. * find that file already registered and return its font.
  324. */
  325. FontFamily family = FontFamily.getFamily(fcInfo.firstFont.familyName);
  326. PhysicalFont physFont = null;
  327. if (family != null) {
  328. Font2D f2D = family.getFontWithExactStyleMatch(fcInfo.style);
  329. if (f2D instanceof PhysicalFont) {
  330. physFont = (PhysicalFont)f2D;
  331. }
  332. }
  333. if (physFont == null ||
  334. !fcInfo.firstFont.fontFile.equals(physFont.platName)) {
  335. physFont = registerFromFcInfo(fcInfo);
  336. if (physFont == null) {
  337. return (fcInfo.compFont = jdkFont);
  338. }
  339. family = FontFamily.getFamily(physFont.getFamilyName(null));
  340. }
  341. /* Now register the fonts in the family (the other styles) after
  342. * checking that they aren't already registered and are actually in
  343. * a different file. They may be the same file in CJK cases.
  344. * For cases where they are different font files - eg as is common for
  345. * Latin fonts, then we rely on fontconfig to report these correctly.
  346. * Assume that all styles of this font are found by fontconfig,
  347. * so we can find all the family members which must be registered
  348. * together to prevent synthetic styling.
  349. */
  350. for (int i=0; i<fontConfigFonts.length; i++) {
  351. FcCompFont fc = fontConfigFonts[i];
  352. if (fc != fcInfo &&
  353. physFont.getFamilyName(null).equals(fc.firstFont.familyName) &&
  354. !fc.firstFont.fontFile.equals(physFont.platName) &&
  355. family.getFontWithExactStyleMatch(fc.style) == null) {
  356. registerFromFcInfo(fontConfigFonts[i]);
  357. }
  358. }
  359. /* Now we have a physical font. We will back this up with the JDK
  360. * logical font (sansserif, serif, or monospaced) that corresponds
  361. * to the Pango/GTK/FC logical font name.
  362. */
  363. return (fcInfo.compFont = new CompositeFont(physFont, jdkFont));
  364. }
  365. /**
  366. *
  367. * @param locale
  368. * @param fcFamily
  369. * @return
  370. */
  371. public FcCompFont[] getFontConfigFonts() {
  372. return fontConfigFonts;
  373. }
  374. /* Return an array of FcCompFont structs describing the primary
  375. * font located for each of fontconfig/GTK/Pango's logical font names.
  376. */
  377. private static native void getFontConfig(String locale,
  378. FontConfigInfo fcInfo,
  379. FcCompFont[] fonts,
  380. boolean includeFallbacks);
  381. void populateFontConfig(FcCompFont[] fcInfo) {
  382. fontConfigFonts = fcInfo;
  383. }
  384. FcCompFont[] loadFontConfig() {
  385. initFontConfigFonts(true);
  386. return fontConfigFonts;
  387. }
  388. FontConfigInfo getFontConfigInfo() {
  389. initFontConfigFonts(true);
  390. return fcInfo;
  391. }
  392. private static native int
  393. getFontConfigAASettings(String locale, String fcFamily);
  394. }


————————————————
版权声明:本文为CSDN博主「神韵499」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41055045/article/details/112002440

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/442199
推荐阅读
相关标签
  

闽ICP备14008679号