1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.graphics.fonts; 18 19 import com.android.ide.common.rendering.api.LayoutLog; 20 import com.android.layoutlib.bridge.Bridge; 21 import com.android.layoutlib.bridge.impl.DelegateManager; 22 import com.android.tools.layoutlib.annotations.LayoutlibDelegate; 23 24 import android.annotation.NonNull; 25 import android.content.res.AssetManager; 26 27 import java.io.IOException; 28 import java.io.InputStream; 29 import java.nio.ByteBuffer; 30 import java.nio.ByteOrder; 31 import java.nio.channels.Channels; 32 import java.nio.channels.ReadableByteChannel; 33 34 import libcore.util.NativeAllocationRegistry_Delegate; 35 36 /** 37 * Delegate implementing the native methods of android.graphics.fonts.Font$Builder 38 * <p> 39 * Through the layoutlib_create tool, the original native methods of Font$Builder have been 40 * replaced by calls to methods of the same name in this delegate class. 41 * <p> 42 * This class behaves like the original native implementation, but in Java, keeping previously 43 * native data into its own objects and mapping them to int that are sent back and forth between it 44 * and the original Font$Builder class. 45 * 46 * @see DelegateManager 47 */ 48 public class Font_Builder_Delegate { 49 protected static final DelegateManager<Font_Builder_Delegate> sBuilderManager = 50 new DelegateManager<>(Font_Builder_Delegate.class); 51 private static long sFontFinalizer = -1; 52 53 protected ByteBuffer mBuffer; 54 protected int mWeight; 55 protected boolean mItalic; 56 protected int mTtcIndex; 57 protected String filePath; 58 59 @LayoutlibDelegate nInitBuilder()60 /*package*/ static long nInitBuilder() { 61 return sBuilderManager.addNewDelegate(new Font_Builder_Delegate()); 62 } 63 64 @LayoutlibDelegate createBuffer(@onNull AssetManager am, @NonNull String path, boolean isAsset, int cookie)65 /*package*/ static ByteBuffer createBuffer(@NonNull AssetManager am, @NonNull String path, 66 boolean isAsset, int cookie) throws IOException { 67 try (InputStream assetStream = isAsset ? am.open(path, AssetManager.ACCESS_BUFFER) 68 : am.openNonAsset(cookie, path, AssetManager.ACCESS_BUFFER)) { 69 70 int capacity = assetStream.available(); 71 ByteBuffer buffer = ByteBuffer.allocateDirect(capacity); 72 buffer.order(ByteOrder.nativeOrder()); 73 ReadableByteChannel channel = Channels.newChannel(assetStream); 74 channel.read(buffer); 75 76 if (assetStream.read() != -1) { 77 throw new IOException("Unable to access full contents of " + path); 78 } 79 80 return buffer; 81 } 82 } 83 84 @LayoutlibDelegate nAddAxis(long builderPtr, int tag, float value)85 /*package*/ static void nAddAxis(long builderPtr, int tag, float value) { 86 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, 87 "Font$Builder.nAddAxis is not supported.", null, null, null); 88 } 89 90 @LayoutlibDelegate nBuild(long builderPtr, ByteBuffer buffer, String filePath, int weight, boolean italic, int ttcIndex)91 /*package*/ static long nBuild(long builderPtr, ByteBuffer buffer, String filePath, int weight, 92 boolean italic, int ttcIndex) { 93 Font_Builder_Delegate font = sBuilderManager.getDelegate(builderPtr); 94 if (font != null) { 95 font.mBuffer = buffer; 96 font.mWeight = weight; 97 font.mItalic = italic; 98 font.mTtcIndex = ttcIndex; 99 font.filePath = filePath; 100 } 101 return builderPtr; 102 } 103 104 @LayoutlibDelegate nGetReleaseNativeFont()105 /*package*/ static long nGetReleaseNativeFont() { 106 synchronized (Font_Builder_Delegate.class) { 107 if (sFontFinalizer == -1) { 108 sFontFinalizer = NativeAllocationRegistry_Delegate.createFinalizer( 109 sBuilderManager::removeJavaReferenceFor); 110 } 111 } 112 return sFontFinalizer; 113 } 114 } 115