1978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung/* 2978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * Copyright (C) 2015 The Android Open Source Project 3978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 4978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * Licensed under the Apache License, Version 2.0 (the "License"); 5978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * you may not use this file except in compliance with the License. 6978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * You may obtain a copy of the License at 7978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 8978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * http://www.apache.org/licenses/LICENSE-2.0 9978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 10978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * Unless required by applicable law or agreed to in writing, software 11978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * distributed under the License is distributed on an "AS IS" BASIS, 12978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * See the License for the specific language governing permissions and 14978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * limitations under the License. 15978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 16978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 17978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungpackage android.media; 18978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 19978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.content.Context; 20978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.graphics.Canvas; 21978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.graphics.Color; 22978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.graphics.Paint; 23978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.graphics.Rect; 24978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.graphics.Typeface; 25978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.os.Handler; 26978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.os.Message; 27978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.text.SpannableStringBuilder; 28978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.text.Spanned; 29978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.text.style.CharacterStyle; 30978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.text.style.RelativeSizeSpan; 31978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.text.style.StyleSpan; 32978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.text.style.SubscriptSpan; 33978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.text.style.SuperscriptSpan; 34978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.text.style.UnderlineSpan; 35978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.util.AttributeSet; 36978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.text.Layout.Alignment; 37978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.util.Log; 38978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.text.TextUtils; 39978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.view.Gravity; 40978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.view.View; 41978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.view.ViewGroup; 42978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.view.accessibility.CaptioningManager; 43978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.view.accessibility.CaptioningManager.CaptionStyle; 44978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.widget.RelativeLayout; 45978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport android.widget.TextView; 46978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 47978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport java.io.UnsupportedEncodingException; 48978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport java.nio.charset.Charset; 49978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport java.nio.charset.StandardCharsets; 50978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport java.util.ArrayList; 51978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport java.util.Arrays; 52978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport java.util.Comparator; 53978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport java.util.List; 54978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport java.util.Vector; 55978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 56978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungimport com.android.internal.widget.SubtitleView; 57978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 58978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung/** @hide */ 59978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungpublic class Cea708CaptionRenderer extends SubtitleController.Renderer { 60978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private final Context mContext; 61978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private Cea708CCWidget mCCWidget; 62978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 63978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public Cea708CaptionRenderer(Context context) { 64978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mContext = context; 65978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 66978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 67978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 68978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public boolean supports(MediaFormat format) { 69978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (format.containsKey(MediaFormat.KEY_MIME)) { 70978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung String mimeType = format.getString(MediaFormat.KEY_MIME); 71978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return MediaPlayer.MEDIA_MIMETYPE_TEXT_CEA_708.equals(mimeType); 72978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 73978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return false; 74978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 75978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 76978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 77978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public SubtitleTrack createTrack(MediaFormat format) { 78978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung String mimeType = format.getString(MediaFormat.KEY_MIME); 79978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (MediaPlayer.MEDIA_MIMETYPE_TEXT_CEA_708.equals(mimeType)) { 80978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCCWidget == null) { 81978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCWidget = new Cea708CCWidget(mContext); 82978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 83978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return new Cea708CaptionTrack(mCCWidget, format); 84978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 85978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung throw new RuntimeException("No matching format: " + format.toString()); 86978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 87978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung} 88978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 89978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung/** @hide */ 90978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungclass Cea708CaptionTrack extends SubtitleTrack { 91978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private final Cea708CCParser mCCParser; 92978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private final Cea708CCWidget mRenderingWidget; 93978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 94978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Cea708CaptionTrack(Cea708CCWidget renderingWidget, MediaFormat format) { 95978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung super(format); 96978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 97978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mRenderingWidget = renderingWidget; 98978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCParser = new Cea708CCParser(mRenderingWidget); 99978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 100978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 101978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 102978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void onData(byte[] data, boolean eos, long runID) { 103978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCParser.parse(data); 104978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 105978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 106978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 107978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public RenderingWidget getRenderingWidget() { 108978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return mRenderingWidget; 109978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 110978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 111978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 112978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void updateView(Vector<Cue> activeCues) { 113978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Overriding with NO-OP, CC rendering by-passes this 114978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 115978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung} 116978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 117978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung/** 118978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @hide 119978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 120978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * A class for parsing CEA-708, which is the standard for closed captioning for ATSC DTV. 121978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 122978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p>ATSC DTV closed caption data are carried on picture user data of video streams. 123978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * This class starts to parse from picture user data payload, so extraction process of user_data 124978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * from video streams is up to outside of this code. 125978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 126978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p>There are 4 steps to decode user_data to provide closed caption services. Step 1 and 2 are 127978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * done in NuPlayer and libstagefright. 128978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 129978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <h3>Step 1. user_data -> CcPacket</h3> 130978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 131978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p>First, user_data consists of cc_data packets, which are 3-byte segments. Here, CcPacket is a 132978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * collection of cc_data packets in a frame along with same presentation timestamp. Because cc_data 133978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * packets must be reassembled in the frame display order, CcPackets are reordered. 134978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 135978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <h3>Step 2. CcPacket -> DTVCC packet</h3> 136978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 137978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p>Each cc_data packet has a one byte for declaring a type of itself and data validity, and the 138978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * subsequent two bytes for input data of a DTVCC packet. There are 4 types for cc_data packet. 139978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * We're interested in DTVCC_PACKET_START(type 3) and DTVCC_PACKET_DATA(type 2). Each DTVCC packet 140978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * begins with DTVCC_PACKET_START(type 3) and the following cc_data packets which has 141978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * DTVCC_PACKET_DATA(type 2) are appended into the DTVCC packet being assembled. 142978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 143978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <h3>Step 3. DTVCC packet -> Service Blocks</h3> 144978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 145978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p>A DTVCC packet consists of multiple service blocks. Each service block represents a caption 146978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * track and has a service number, which ranges from 1 to 63, that denotes caption track identity. 147978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * In here, we listen at most one chosen caption track by service number. Otherwise, just skip the 148978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * other service blocks. 149978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 150978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <h3>Step 4. Interpreting Service Block Data ({@link #parseServiceBlockData}, {@code parseXX}, 151978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * and {@link #parseExt1} methods)</h3> 152978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 153978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p>Service block data is actual caption stream. it looks similar to telnet. It uses most parts of 154978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * ASCII table and consists of specially defined commands and some ASCII control codes which work 155978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * in a behavior slightly different from their original purpose. ASCII control codes and caption 156978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * commands are explicit instructions that control the state of a closed caption service and the 157978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * other ASCII and text codes are implicit instructions that send their characters to buffer. 158978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 159978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p>There are 4 main code groups and 4 extended code groups. Both the range of code groups are the 160978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * same as the range of a byte. 161978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 162978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p>4 main code groups: C0, C1, G0, G1 163978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <br>4 extended code groups: C2, C3, G2, G3 164978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 165978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p>Each code group has its own handle method. For example, {@link #parseC0} handles C0 code group 166978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * and so on. And {@link #parseServiceBlockData} method maps a stream on the main code groups while 167978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * {@link #parseExt1} method maps on the extended code groups. 168978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 169978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p>The main code groups: 170978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <ul> 171978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <li>C0 - contains modified ASCII control codes. It is not intended by CEA-708 but Korea TTA 172978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * standard for ATSC CC uses P16 character heavily, which is unclear entity in CEA-708 doc, 173978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * even for the alphanumeric characters instead of ASCII characters.</li> 174978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <li>C1 - contains the caption commands. There are 3 categories of a caption command.</li> 175978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <ul> 176978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <li>Window commands: The window commands control a caption window which is addressable area being 177978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * with in the Safe title area. (CWX, CLW, DSW, HDW, TGW, DLW, SWA, DFX)</li> 178978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <li>Pen commands: Th pen commands control text style and location. (SPA, SPC, SPL)</li> 179978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <li>Job commands: The job commands make a delay and recover from the delay. (DLY, DLC, RST)</li> 180978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * </ul> 181978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <li>G0 - same as printable ASCII character set except music note character.</li> 182978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <li>G1 - same as ISO 8859-1 Latin 1 character set.</li> 183978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * </ul> 184978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p>Most of the extended code groups are being skipped. 185978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 186978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 187978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungclass Cea708CCParser { 188978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final String TAG = "Cea708CCParser"; 189978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final boolean DEBUG = false; 190978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 191978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final String MUSIC_NOTE_CHAR = new String( 192978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung "\u266B".getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8); 193978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 194978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private final StringBuffer mBuffer = new StringBuffer(); 195978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int mCommand = 0; 196978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 197978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Assign a dummy listener in order to avoid null checks. 198978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private DisplayListener mListener = new DisplayListener() { 199978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 200978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void emitEvent(CaptionEvent event) { 201978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // do nothing 202978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 203978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung }; 204978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 205978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** 206978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * {@link Cea708Parser} emits caption event of three different types. 207978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * {@link DisplayListener#emitEvent} is invoked with the parameter 208978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * {@link CaptionEvent} to pass all the results to an observer of the decoding process . 209978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 210978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p>{@link CaptionEvent#type} determines the type of the result and 211978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * {@link CaptionEvent#obj} contains the output value of a caption event. 212978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * The observer must do the casting to the corresponding type. 213978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 214978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <ul><li>{@code CAPTION_EMIT_TYPE_BUFFER}: Passes a caption text buffer to a observer. 215978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * {@code obj} must be of {@link String}.</li> 216978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 217978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <li>{@code CAPTION_EMIT_TYPE_CONTROL}: Passes a caption character control code to a observer. 218978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * {@code obj} must be of {@link Character}.</li> 219978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 220978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <li>{@code CAPTION_EMIT_TYPE_CLEAR_COMMAND}: Passes a clear command to a observer. 221978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * {@code obj} must be {@code NULL}.</li></ul> 222978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 223978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_BUFFER = 1; 224978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_CONTROL = 2; 225978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_COMMAND_CWX = 3; 226978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_COMMAND_CLW = 4; 227978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_COMMAND_DSW = 5; 228978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_COMMAND_HDW = 6; 229978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_COMMAND_TGW = 7; 230978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_COMMAND_DLW = 8; 231978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_COMMAND_DLY = 9; 232978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_COMMAND_DLC = 10; 233978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_COMMAND_RST = 11; 234978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_COMMAND_SPA = 12; 235978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_COMMAND_SPC = 13; 236978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_COMMAND_SPL = 14; 237978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_COMMAND_SWA = 15; 238978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CAPTION_EMIT_TYPE_COMMAND_DFX = 16; 239978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 240978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Cea708CCParser(DisplayListener listener) { 241978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (listener != null) { 242978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mListener = listener; 243978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 244978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 245978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 246978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung interface DisplayListener { 247978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung void emitEvent(CaptionEvent event); 248978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 249978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 250978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void emitCaptionEvent(CaptionEvent captionEvent) { 251978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Emit the existing string buffer before a new event is arrived. 252978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionBuffer(); 253978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mListener.emitEvent(captionEvent); 254978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 255978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 256978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void emitCaptionBuffer() { 257978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mBuffer.length() > 0) { 258978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mListener.emitEvent(new CaptionEvent(CAPTION_EMIT_TYPE_BUFFER, mBuffer.toString())); 259978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mBuffer.setLength(0); 260978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 261978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 262978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 263978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Step 3. DTVCC packet -> Service Blocks (parseDtvCcPacket method) 264978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void parse(byte[] data) { 265978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // From this point, starts to read DTVCC coding layer. 266978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // First, identify code groups, which is defined in CEA-708B Section 7.1. 267978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int pos = 0; 268978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung while (pos < data.length) { 269978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos = parseServiceBlockData(data, pos); 270978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 271978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 272978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Emit the buffer after reading codes. 273978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionBuffer(); 274978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 275978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 276978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Step 4. Main code groups 277978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int parseServiceBlockData(byte[] data, int pos) { 278978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // For the details of the ranges of DTVCC code groups, see CEA-708B Table 6. 279978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCommand = data[pos] & 0xff; 280978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ++pos; 281978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCommand == Const.CODE_C0_EXT1) { 282978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 283978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format("parseServiceBlockData EXT1 %x", mCommand)); 284978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 285978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos = parseExt1(data, pos); 286978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else if (mCommand >= Const.CODE_C0_RANGE_START 287978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_C0_RANGE_END) { 288978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 289978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format("parseServiceBlockData C0 %x", mCommand)); 290978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 291978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos = parseC0(data, pos); 292978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else if (mCommand >= Const.CODE_C1_RANGE_START 293978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_C1_RANGE_END) { 294978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 295978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format("parseServiceBlockData C1 %x", mCommand)); 296978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 297978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos = parseC1(data, pos); 298978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else if (mCommand >= Const.CODE_G0_RANGE_START 299978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_G0_RANGE_END) { 300978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 301978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format("parseServiceBlockData G0 %x", mCommand)); 302978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 303978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos = parseG0(data, pos); 304978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else if (mCommand >= Const.CODE_G1_RANGE_START 305978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_G1_RANGE_END) { 306978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 307978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format("parseServiceBlockData G1 %x", mCommand)); 308978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 309978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos = parseG1(data, pos); 310978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 311978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return pos; 312978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 313978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 314978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int parseC0(byte[] data, int pos) { 315978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // For the details of C0 code group, see CEA-708B Section 7.4.1. 316978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // CL Group: C0 Subset of ASCII Control codes 317978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCommand >= Const.CODE_C0_SKIP2_RANGE_START 318978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_C0_SKIP2_RANGE_END) { 319978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCommand == Const.CODE_C0_P16) { 320978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // P16 escapes next two bytes for the large character maps.(no standard rule) 321978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // For Korea broadcasting, express whole letters by using this. 322978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung try { 323978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (data[pos] == 0) { 324978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mBuffer.append((char) data[pos + 1]); 325978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else { 326978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung String value = new String(Arrays.copyOfRange(data, pos, pos + 2), "EUC-KR"); 327978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mBuffer.append(value); 328978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 329978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } catch (UnsupportedEncodingException e) { 330978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.e(TAG, "P16 Code - Could not find supported encoding", e); 331978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 332978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 333978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos += 2; 334978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else if (mCommand >= Const.CODE_C0_SKIP1_RANGE_START 335978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_C0_SKIP1_RANGE_END) { 336978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ++pos; 337978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else { 338978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // NUL, BS, FF, CR interpreted as they are in ASCII control codes. 339978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // HCR moves the pen location to th beginning of the current line and deletes contents. 340978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // FF clears the screen and moves the pen location to (0,0). 341978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // ETX is the NULL command which is used to flush text to the current window when no 342978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // other command is pending. 343978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung switch (mCommand) { 344978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C0_NUL: 345978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 346978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C0_ETX: 347978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_CONTROL, (char) mCommand)); 348978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 349978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C0_BS: 350978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_CONTROL, (char) mCommand)); 351978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 352978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C0_FF: 353978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_CONTROL, (char) mCommand)); 354978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 355978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C0_CR: 356978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mBuffer.append('\n'); 357978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 358978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C0_HCR: 359978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_CONTROL, (char) mCommand)); 360978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 361978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung default: 362978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 363978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 364978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 365978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return pos; 366978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 367978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 368978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int parseC1(byte[] data, int pos) { 369978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // For the details of C1 code group, see CEA-708B Section 8.10. 370978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // CR Group: C1 Caption Control Codes 371978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung switch (mCommand) { 372978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_CW0: 373978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_CW1: 374978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_CW2: 375978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_CW3: 376978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_CW4: 377978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_CW5: 378978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_CW6: 379978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_CW7: { 380978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // SetCurrentWindow0-7 381978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int windowId = mCommand - Const.CODE_C1_CW0; 382978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_COMMAND_CWX, windowId)); 383978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 384978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format("CaptionCommand CWX windowId: %d", windowId)); 385978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 386978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 387978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 388978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 389978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_CLW: { 390978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // ClearWindows 391978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int windowBitmap = data[pos] & 0xff; 392978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ++pos; 393978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_COMMAND_CLW, windowBitmap)); 394978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 395978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format("CaptionCommand CLW windowBitmap: %d", windowBitmap)); 396978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 397978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 398978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 399978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 400978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_DSW: { 401978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // DisplayWindows 402978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int windowBitmap = data[pos] & 0xff; 403978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ++pos; 404978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_COMMAND_DSW, windowBitmap)); 405978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 406978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format("CaptionCommand DSW windowBitmap: %d", windowBitmap)); 407978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 408978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 409978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 410978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 411978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_HDW: { 412978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // HideWindows 413978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int windowBitmap = data[pos] & 0xff; 414978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ++pos; 415978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_COMMAND_HDW, windowBitmap)); 416978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 417978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format("CaptionCommand HDW windowBitmap: %d", windowBitmap)); 418978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 419978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 420978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 421978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 422978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_TGW: { 423978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // ToggleWindows 424978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int windowBitmap = data[pos] & 0xff; 425978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ++pos; 426978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_COMMAND_TGW, windowBitmap)); 427978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 428978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format("CaptionCommand TGW windowBitmap: %d", windowBitmap)); 429978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 430978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 431978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 432978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 433978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_DLW: { 434978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // DeleteWindows 435978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int windowBitmap = data[pos] & 0xff; 436978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ++pos; 437978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_COMMAND_DLW, windowBitmap)); 438978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 439978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format("CaptionCommand DLW windowBitmap: %d", windowBitmap)); 440978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 441978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 442978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 443978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 444978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_DLY: { 445978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Delay 446978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int tenthsOfSeconds = data[pos] & 0xff; 447978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ++pos; 448978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_COMMAND_DLY, tenthsOfSeconds)); 449978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 450978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format("CaptionCommand DLY %d tenths of seconds", 451978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung tenthsOfSeconds)); 452978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 453978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 454978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 455978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_DLC: { 456978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // DelayCancel 457978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_COMMAND_DLC, null)); 458978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 459978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, "CaptionCommand DLC"); 460978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 461978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 462978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 463978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 464978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_RST: { 465978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Reset 466978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_COMMAND_RST, null)); 467978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 468978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, "CaptionCommand RST"); 469978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 470978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 471978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 472978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 473978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_SPA: { 474978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // SetPenAttributes 475978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int textTag = (data[pos] & 0xf0) >> 4; 476978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int penSize = data[pos] & 0x03; 477978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int penOffset = (data[pos] & 0x0c) >> 2; 478978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung boolean italic = (data[pos + 1] & 0x80) != 0; 479978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung boolean underline = (data[pos + 1] & 0x40) != 0; 480978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int edgeType = (data[pos + 1] & 0x38) >> 3; 481978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int fontTag = data[pos + 1] & 0x7; 482978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos += 2; 483978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_COMMAND_SPA, 484978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung new CaptionPenAttr(penSize, penOffset, textTag, fontTag, edgeType, 485978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung underline, italic))); 486978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 487978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format( 488978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung "CaptionCommand SPA penSize: %d, penOffset: %d, textTag: %d, " 489978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung + "fontTag: %d, edgeType: %d, underline: %s, italic: %s", 490978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung penSize, penOffset, textTag, fontTag, edgeType, underline, italic)); 491978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 492978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 493978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 494978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 495978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_SPC: { 496978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // SetPenColor 497978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int opacity = (data[pos] & 0xc0) >> 6; 498978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int red = (data[pos] & 0x30) >> 4; 499978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int green = (data[pos] & 0x0c) >> 2; 500978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int blue = data[pos] & 0x03; 501978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung CaptionColor foregroundColor = new CaptionColor(opacity, red, green, blue); 502978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ++pos; 503978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung opacity = (data[pos] & 0xc0) >> 6; 504978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung red = (data[pos] & 0x30) >> 4; 505978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung green = (data[pos] & 0x0c) >> 2; 506978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung blue = data[pos] & 0x03; 507978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung CaptionColor backgroundColor = new CaptionColor(opacity, red, green, blue); 508978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ++pos; 509978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung red = (data[pos] & 0x30) >> 4; 510978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung green = (data[pos] & 0x0c) >> 2; 511978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung blue = data[pos] & 0x03; 512978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung CaptionColor edgeColor = new CaptionColor( 513978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung CaptionColor.OPACITY_SOLID, red, green, blue); 514978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ++pos; 515978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_COMMAND_SPC, 516978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung new CaptionPenColor(foregroundColor, backgroundColor, edgeColor))); 517978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 518978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format( 519978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung "CaptionCommand SPC foregroundColor %s backgroundColor %s edgeColor %s", 520978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung foregroundColor, backgroundColor, edgeColor)); 521978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 522978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 523978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 524978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 525978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_SPL: { 526978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // SetPenLocation 527978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // column is normally 0-31 for 4:3 formats, and 0-41 for 16:9 formats 528978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int row = data[pos] & 0x0f; 529978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int column = data[pos + 1] & 0x3f; 530978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos += 2; 531978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_COMMAND_SPL, 532978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung new CaptionPenLocation(row, column))); 533978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 534978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format("CaptionCommand SPL row: %d, column: %d", 535978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung row, column)); 536978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 537978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 538978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 539978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 540978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_SWA: { 541978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // SetWindowAttributes 542978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int opacity = (data[pos] & 0xc0) >> 6; 543978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int red = (data[pos] & 0x30) >> 4; 544978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int green = (data[pos] & 0x0c) >> 2; 545978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int blue = data[pos] & 0x03; 546978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung CaptionColor fillColor = new CaptionColor(opacity, red, green, blue); 547978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int borderType = (data[pos + 1] & 0xc0) >> 6 | (data[pos + 2] & 0x80) >> 5; 548978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung red = (data[pos + 1] & 0x30) >> 4; 549978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung green = (data[pos + 1] & 0x0c) >> 2; 550978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung blue = data[pos + 1] & 0x03; 551978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung CaptionColor borderColor = new CaptionColor( 552978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung CaptionColor.OPACITY_SOLID, red, green, blue); 553978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung boolean wordWrap = (data[pos + 2] & 0x40) != 0; 554978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int printDirection = (data[pos + 2] & 0x30) >> 4; 555978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int scrollDirection = (data[pos + 2] & 0x0c) >> 2; 556978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int justify = (data[pos + 2] & 0x03); 557978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int effectSpeed = (data[pos + 3] & 0xf0) >> 4; 558978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int effectDirection = (data[pos + 3] & 0x0c) >> 2; 559978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int displayEffect = data[pos + 3] & 0x3; 560978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos += 4; 561978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_COMMAND_SWA, 562978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung new CaptionWindowAttr(fillColor, borderColor, borderType, wordWrap, 563978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung printDirection, scrollDirection, justify, 564978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung effectDirection, effectSpeed, displayEffect))); 565978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 566978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format( 567978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung "CaptionCommand SWA fillColor: %s, borderColor: %s, borderType: %d" 568978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung + "wordWrap: %s, printDirection: %d, scrollDirection: %d, " 569978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung + "justify: %s, effectDirection: %d, effectSpeed: %d, " 570978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung + "displayEffect: %d", 571978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung fillColor, borderColor, borderType, wordWrap, printDirection, 572978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scrollDirection, justify, effectDirection, effectSpeed, displayEffect)); 573978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 574978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 575978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 576978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 577978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_DF0: 578978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_DF1: 579978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_DF2: 580978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_DF3: 581978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_DF4: 582978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_DF5: 583978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_DF6: 584978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_C1_DF7: { 585978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // DefineWindow0-7 586978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int windowId = mCommand - Const.CODE_C1_DF0; 587978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung boolean visible = (data[pos] & 0x20) != 0; 588978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung boolean rowLock = (data[pos] & 0x10) != 0; 589978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung boolean columnLock = (data[pos] & 0x08) != 0; 590978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int priority = data[pos] & 0x07; 591978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung boolean relativePositioning = (data[pos + 1] & 0x80) != 0; 592978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int anchorVertical = data[pos + 1] & 0x7f; 593978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int anchorHorizontal = data[pos + 2] & 0xff; 594978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int anchorId = (data[pos + 3] & 0xf0) >> 4; 595978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int rowCount = data[pos + 3] & 0x0f; 596978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int columnCount = data[pos + 4] & 0x3f; 597978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int windowStyle = (data[pos + 5] & 0x38) >> 3; 598978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int penStyle = data[pos + 5] & 0x07; 599978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos += 6; 600978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung emitCaptionEvent(new CaptionEvent(CAPTION_EMIT_TYPE_COMMAND_DFX, 601978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung new CaptionWindow(windowId, visible, rowLock, columnLock, priority, 602978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung relativePositioning, anchorVertical, anchorHorizontal, anchorId, 603978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung rowCount, columnCount, penStyle, windowStyle))); 604978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 605978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format( 606978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung "CaptionCommand DFx windowId: %d, priority: %d, columnLock: %s, " 607978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung + "rowLock: %s, visible: %s, anchorVertical: %d, " 608978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung + "relativePositioning: %s, anchorHorizontal: %d, " 609978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung + "rowCount: %d, anchorId: %d, columnCount: %d, penStyle: %d, " 610978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung + "windowStyle: %d", 611978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung windowId, priority, columnLock, rowLock, visible, anchorVertical, 612978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung relativePositioning, anchorHorizontal, rowCount, anchorId, columnCount, 613978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung penStyle, windowStyle)); 614978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 615978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 616978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 617978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 618978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung default: 619978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 620978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 621978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return pos; 622978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 623978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 624978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int parseG0(byte[] data, int pos) { 625978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // For the details of G0 code group, see CEA-708B Section 7.4.3. 626978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // GL Group: G0 Modified version of ANSI X3.4 Printable Character Set (ASCII) 627978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCommand == Const.CODE_G0_MUSICNOTE) { 628978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Music note. 629978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mBuffer.append(MUSIC_NOTE_CHAR); 630978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else { 631978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Put ASCII code into buffer. 632978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mBuffer.append((char) mCommand); 633978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 634978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return pos; 635978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 636978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 637978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int parseG1(byte[] data, int pos) { 638978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // For the details of G0 code group, see CEA-708B Section 7.4.4. 639978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // GR Group: G1 ISO 8859-1 Latin 1 Characters 640978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Put ASCII Extended character set into buffer. 641978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mBuffer.append((char) mCommand); 642978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return pos; 643978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 644978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 645978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Step 4. Extended code groups 646978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int parseExt1(byte[] data, int pos) { 647978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // For the details of EXT1 code group, see CEA-708B Section 7.2. 648978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCommand = data[pos] & 0xff; 649978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ++pos; 650978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCommand >= Const.CODE_C2_RANGE_START 651978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_C2_RANGE_END) { 652978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos = parseC2(data, pos); 653978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else if (mCommand >= Const.CODE_C3_RANGE_START 654978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_C3_RANGE_END) { 655978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos = parseC3(data, pos); 656978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else if (mCommand >= Const.CODE_G2_RANGE_START 657978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_G2_RANGE_END) { 658978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos = parseG2(data, pos); 659978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else if (mCommand >= Const.CODE_G3_RANGE_START 660978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_G3_RANGE_END) { 661978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos = parseG3(data ,pos); 662978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 663978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return pos; 664978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 665978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 666978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int parseC2(byte[] data, int pos) { 667978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // For the details of C2 code group, see CEA-708B Section 7.4.7. 668978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Extended Miscellaneous Control Codes 669978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // C2 Table : No commands as of CEA-708B. A decoder must skip. 670978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCommand >= Const.CODE_C2_SKIP0_RANGE_START 671978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_C2_SKIP0_RANGE_END) { 672978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Do nothing. 673978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else if (mCommand >= Const.CODE_C2_SKIP1_RANGE_START 674978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_C2_SKIP1_RANGE_END) { 675978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ++pos; 676978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else if (mCommand >= Const.CODE_C2_SKIP2_RANGE_START 677978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_C2_SKIP2_RANGE_END) { 678978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos += 2; 679978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else if (mCommand >= Const.CODE_C2_SKIP3_RANGE_START 680978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_C2_SKIP3_RANGE_END) { 681978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos += 3; 682978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 683978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return pos; 684978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 685978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 686978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int parseC3(byte[] data, int pos) { 687978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // For the details of C3 code group, see CEA-708B Section 7.4.8. 688978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Extended Control Code Set 2 689978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // C3 Table : No commands as of CEA-708B. A decoder must skip. 690978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCommand >= Const.CODE_C3_SKIP4_RANGE_START 691978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_C3_SKIP4_RANGE_END) { 692978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos += 4; 693978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else if (mCommand >= Const.CODE_C3_SKIP5_RANGE_START 694978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung && mCommand <= Const.CODE_C3_SKIP5_RANGE_END) { 695978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung pos += 5; 696978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 697978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return pos; 698978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 699978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 700978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int parseG2(byte[] data, int pos) { 701978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // For the details of C3 code group, see CEA-708B Section 7.4.5. 702978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Extended Control Code Set 1(G2 Table) 703978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung switch (mCommand) { 704978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_G2_TSP: 705978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // TODO : TSP is the Transparent space 706978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 707978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_G2_NBTSP: 708978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // TODO : NBTSP is Non-Breaking Transparent Space. 709978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 710978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Const.CODE_G2_BLK: 711978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // TODO : BLK indicates a solid block which fills the entire character block 712978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // TODO : with a solid foreground color. 713978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 714978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung default: 715978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 716978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 717978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return pos; 718978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 719978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 720978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int parseG3(byte[] data, int pos) { 721978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // For the details of C3 code group, see CEA-708B Section 7.4.6. 722978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Future characters and icons(G3 Table) 723978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCommand == Const.CODE_G3_CC) { 724978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // TODO : [CC] icon with square corners 725978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 726978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 727978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Do nothing 728978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return pos; 729978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 730978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 731978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** 732978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @hide 733978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 734978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * Collection of CEA-708 structures. 735978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 736978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static class Const { 737978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 738978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private Const() { 739978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 740978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 741978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // For the details of the ranges of DTVCC code groups, see CEA-708B Table 6. 742978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C0_RANGE_START = 0x00; 743978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C0_RANGE_END = 0x1f; 744978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_RANGE_START = 0x80; 745978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_RANGE_END = 0x9f; 746978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_G0_RANGE_START = 0x20; 747978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_G0_RANGE_END = 0x7f; 748978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_G1_RANGE_START = 0xa0; 749978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_G1_RANGE_END = 0xff; 750978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C2_RANGE_START = 0x00; 751978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C2_RANGE_END = 0x1f; 752978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C3_RANGE_START = 0x80; 753978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C3_RANGE_END = 0x9f; 754978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_G2_RANGE_START = 0x20; 755978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_G2_RANGE_END = 0x7f; 756978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_G3_RANGE_START = 0xa0; 757978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_G3_RANGE_END = 0xff; 758978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 759978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // The following ranges are defined in CEA-708B Section 7.4.1. 760978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C0_SKIP2_RANGE_START = 0x18; 761978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C0_SKIP2_RANGE_END = 0x1f; 762978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C0_SKIP1_RANGE_START = 0x10; 763978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C0_SKIP1_RANGE_END = 0x17; 764978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 765978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // The following ranges are defined in CEA-708B Section 7.4.7. 766978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C2_SKIP0_RANGE_START = 0x00; 767978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C2_SKIP0_RANGE_END = 0x07; 768978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C2_SKIP1_RANGE_START = 0x08; 769978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C2_SKIP1_RANGE_END = 0x0f; 770978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C2_SKIP2_RANGE_START = 0x10; 771978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C2_SKIP2_RANGE_END = 0x17; 772978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C2_SKIP3_RANGE_START = 0x18; 773978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C2_SKIP3_RANGE_END = 0x1f; 774978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 775978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // The following ranges are defined in CEA-708B Section 7.4.8. 776978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C3_SKIP4_RANGE_START = 0x80; 777978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C3_SKIP4_RANGE_END = 0x87; 778978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C3_SKIP5_RANGE_START = 0x88; 779978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C3_SKIP5_RANGE_END = 0x8f; 780978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 781978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // The following values are the special characters of CEA-708 spec. 782978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C0_NUL = 0x00; 783978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C0_ETX = 0x03; 784978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C0_BS = 0x08; 785978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C0_FF = 0x0c; 786978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C0_CR = 0x0d; 787978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C0_HCR = 0x0e; 788978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C0_EXT1 = 0x10; 789978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C0_P16 = 0x18; 790978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_G0_MUSICNOTE = 0x7f; 791978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_G2_TSP = 0x20; 792978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_G2_NBTSP = 0x21; 793978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_G2_BLK = 0x30; 794978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_G3_CC = 0xa0; 795978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 796978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // The following values are the command bits of CEA-708 spec. 797978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_CW0 = 0x80; 798978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_CW1 = 0x81; 799978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_CW2 = 0x82; 800978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_CW3 = 0x83; 801978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_CW4 = 0x84; 802978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_CW5 = 0x85; 803978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_CW6 = 0x86; 804978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_CW7 = 0x87; 805978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_CLW = 0x88; 806978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_DSW = 0x89; 807978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_HDW = 0x8a; 808978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_TGW = 0x8b; 809978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_DLW = 0x8c; 810978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_DLY = 0x8d; 811978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_DLC = 0x8e; 812978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_RST = 0x8f; 813978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_SPA = 0x90; 814978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_SPC = 0x91; 815978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_SPL = 0x92; 816978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_SWA = 0x97; 817978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_DF0 = 0x98; 818978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_DF1 = 0x99; 819978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_DF2 = 0x9a; 820978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_DF3 = 0x9b; 821978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_DF4 = 0x9c; 822978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_DF5 = 0x9d; 823978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_DF6 = 0x9e; 824978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int CODE_C1_DF7 = 0x9f; 825978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 826978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 827978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** 828978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @hide 829978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 830978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * CEA-708B-specific color. 831978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 832978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static class CaptionColor { 833978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int OPACITY_SOLID = 0; 834978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int OPACITY_FLASH = 1; 835978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int OPACITY_TRANSLUCENT = 2; 836978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int OPACITY_TRANSPARENT = 3; 837978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 838978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int[] COLOR_MAP = new int[] { 0x00, 0x0f, 0xf0, 0xff }; 839978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int[] OPACITY_MAP = new int[] { 0xff, 0xfe, 0x80, 0x00 }; 840978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 841978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int opacity; 842978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int red; 843978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int green; 844978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int blue; 845978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 846978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CaptionColor(int opacity, int red, int green, int blue) { 847978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.opacity = opacity; 848978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.red = red; 849978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.green = green; 850978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.blue = blue; 851978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 852978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 853978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public int getArgbValue() { 854978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return Color.argb( 855978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung OPACITY_MAP[opacity], COLOR_MAP[red], COLOR_MAP[green], COLOR_MAP[blue]); 856978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 857978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 858978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 859978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** 860978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @hide 861978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 862978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * Caption event generated by {@link Cea708CCParser}. 863978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 864978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static class CaptionEvent { 865978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int type; 866978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final Object obj; 867978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 868978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CaptionEvent(int type, Object obj) { 869978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.type = type; 870978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.obj = obj; 871978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 872978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 873978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 874978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** 875978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @hide 876978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 877978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * Pen style information. 878978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 879978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static class CaptionPenAttr { 880978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Pen sizes 881978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int PEN_SIZE_SMALL = 0; 882978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int PEN_SIZE_STANDARD = 1; 883978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int PEN_SIZE_LARGE = 2; 884978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 885978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Offsets 886978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int OFFSET_SUBSCRIPT = 0; 887978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int OFFSET_NORMAL = 1; 888978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final int OFFSET_SUPERSCRIPT = 2; 889978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 890978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int penSize; 891978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int penOffset; 892978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int textTag; 893978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int fontTag; 894978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int edgeType; 895978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final boolean underline; 896978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final boolean italic; 897978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 898978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CaptionPenAttr(int penSize, int penOffset, int textTag, int fontTag, int edgeType, 899978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung boolean underline, boolean italic) { 900978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.penSize = penSize; 901978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.penOffset = penOffset; 902978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.textTag = textTag; 903978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.fontTag = fontTag; 904978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.edgeType = edgeType; 905978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.underline = underline; 906978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.italic = italic; 907978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 908978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 909978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 910978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** 911978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @hide 912978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 913978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * {@link CaptionColor} objects that indicate the foreground, background, and edge color of a 914978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * pen. 915978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 916978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static class CaptionPenColor { 917978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final CaptionColor foregroundColor; 918978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final CaptionColor backgroundColor; 919978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final CaptionColor edgeColor; 920978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 921978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CaptionPenColor(CaptionColor foregroundColor, CaptionColor backgroundColor, 922978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung CaptionColor edgeColor) { 923978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.foregroundColor = foregroundColor; 924978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.backgroundColor = backgroundColor; 925978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.edgeColor = edgeColor; 926978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 927978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 928978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 929978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** 930978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @hide 931978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 932978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * Location information of a pen. 933978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 934978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static class CaptionPenLocation { 935978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int row; 936978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int column; 937978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 938978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CaptionPenLocation(int row, int column) { 939978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.row = row; 940978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.column = column; 941978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 942978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 943978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 944978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** 945978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @hide 946978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 947978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * Attributes of a caption window, which is defined in CEA-708B. 948978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 949978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static class CaptionWindowAttr { 950978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final CaptionColor fillColor; 951978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final CaptionColor borderColor; 952978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int borderType; 953978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final boolean wordWrap; 954978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int printDirection; 955978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int scrollDirection; 956978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int justify; 957978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int effectDirection; 958978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int effectSpeed; 959978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int displayEffect; 960978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 961978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CaptionWindowAttr(CaptionColor fillColor, CaptionColor borderColor, int borderType, 962978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung boolean wordWrap, int printDirection, int scrollDirection, int justify, 963978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int effectDirection, 964978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int effectSpeed, int displayEffect) { 965978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.fillColor = fillColor; 966978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.borderColor = borderColor; 967978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.borderType = borderType; 968978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.wordWrap = wordWrap; 969978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.printDirection = printDirection; 970978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.scrollDirection = scrollDirection; 971978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.justify = justify; 972978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.effectDirection = effectDirection; 973978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.effectSpeed = effectSpeed; 974978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.displayEffect = displayEffect; 975978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 976978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 977978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 978978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** 979978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @hide 980978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 981978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * Construction information of the caption window of CEA-708B. 982978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 983978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static class CaptionWindow { 984978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int id; 985978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final boolean visible; 986978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final boolean rowLock; 987978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final boolean columnLock; 988978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int priority; 989978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final boolean relativePositioning; 990978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int anchorVertical; 991978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int anchorHorizontal; 992978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int anchorId; 993978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int rowCount; 994978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int columnCount; 995978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int penStyle; 996978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public final int windowStyle; 997978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 998978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CaptionWindow(int id, boolean visible, 999978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung boolean rowLock, boolean columnLock, int priority, boolean relativePositioning, 1000978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int anchorVertical, int anchorHorizontal, int anchorId, 1001978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int rowCount, int columnCount, int penStyle, int windowStyle) { 1002978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.id = id; 1003978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.visible = visible; 1004978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.rowLock = rowLock; 1005978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.columnLock = columnLock; 1006978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.priority = priority; 1007978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.relativePositioning = relativePositioning; 1008978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.anchorVertical = anchorVertical; 1009978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.anchorHorizontal = anchorHorizontal; 1010978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.anchorId = anchorId; 1011978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.rowCount = rowCount; 1012978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.columnCount = columnCount; 1013978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.penStyle = penStyle; 1014978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.windowStyle = windowStyle; 1015978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1016978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1017978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung} 1018978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1019978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung/** 1020978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * Widget capable of rendering CEA-708 closed captions. 1021978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 1022978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @hide 1023978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 1024978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chungclass Cea708CCWidget extends ClosedCaptionWidget implements Cea708CCParser.DisplayListener { 1025978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private final CCHandler mCCHandler; 1026978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1027978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public Cea708CCWidget(Context context) { 1028978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this(context, null); 1029978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1030978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1031978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public Cea708CCWidget(Context context, AttributeSet attrs) { 1032978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this(context, attrs, 0); 1033978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1034978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1035978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public Cea708CCWidget(Context context, AttributeSet attrs, int defStyleAttr) { 1036978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this(context, attrs, defStyleAttr, 0); 1037978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1038978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1039978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public Cea708CCWidget(Context context, AttributeSet attrs, int defStyleAttr, 1040978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int defStyleRes) { 1041978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung super(context, attrs, defStyleAttr, defStyleRes); 1042978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1043978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCHandler = new CCHandler((CCLayout) mClosedCaptionLayout); 1044978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1045978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1046978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 1047978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public ClosedCaptionLayout createCaptionLayout(Context context) { 1048978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return new CCLayout(context); 1049978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1050978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1051978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 1052978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void emitEvent(Cea708CCParser.CaptionEvent event) { 1053978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCHandler.processCaptionEvent(event); 1054978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1055978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setSize(getWidth(), getHeight()); 1056978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1057978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mListener != null) { 1058978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mListener.onChanged(this); 1059978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1060978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1061978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1062978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 1063978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void onDraw(Canvas canvas) { 1064978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung super.onDraw(canvas); 1065978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ((ViewGroup) mClosedCaptionLayout).draw(canvas); 1066978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1067978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1068978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** 1069978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @hide 1070978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 1071978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * A layout that scales its children using the given percentage value. 1072978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 1073978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung static class ScaledLayout extends ViewGroup { 1074978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final String TAG = "ScaledLayout"; 1075978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final boolean DEBUG = false; 1076978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final Comparator<Rect> mRectTopLeftSorter = new Comparator<Rect>() { 1077978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 1078978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public int compare(Rect lhs, Rect rhs) { 1079978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (lhs.top != rhs.top) { 1080978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return lhs.top - rhs.top; 1081978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else { 1082978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return lhs.left - rhs.left; 1083978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1084978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1085978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung }; 1086978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1087978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private Rect[] mRectArray; 1088978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1089978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public ScaledLayout(Context context) { 1090978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung super(context); 1091978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1092978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1093978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** 1094978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @hide 1095978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 1096978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * ScaledLayoutParams stores the four scale factors. 1097978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <br> 1098978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * Vertical coordinate system: (scaleStartRow * 100) % ~ (scaleEndRow * 100) % 1099978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * Horizontal coordinate system: (scaleStartCol * 100) % ~ (scaleEndCol * 100) % 1100978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <br> 1101978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * In XML, for example, 1102978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <pre> 1103978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * {@code 1104978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <View 1105978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * app:layout_scaleStartRow="0.1" 1106978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * app:layout_scaleEndRow="0.5" 1107978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * app:layout_scaleStartCol="0.4" 1108978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * app:layout_scaleEndCol="1" /> 1109978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * } 1110978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * </pre> 1111978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 1112978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung static class ScaledLayoutParams extends ViewGroup.LayoutParams { 1113978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public static final float SCALE_UNSPECIFIED = -1; 1114978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public float scaleStartRow; 1115978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public float scaleEndRow; 1116978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public float scaleStartCol; 1117978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public float scaleEndCol; 1118978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1119978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public ScaledLayoutParams(float scaleStartRow, float scaleEndRow, 1120978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float scaleStartCol, float scaleEndCol) { 1121978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung super(MATCH_PARENT, MATCH_PARENT); 1122978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.scaleStartRow = scaleStartRow; 1123978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.scaleEndRow = scaleEndRow; 1124978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.scaleStartCol = scaleStartCol; 1125978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this.scaleEndCol = scaleEndCol; 1126978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1127978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1128978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public ScaledLayoutParams(Context context, AttributeSet attrs) { 1129978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung super(MATCH_PARENT, MATCH_PARENT); 1130978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1131978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1132978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1133978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 1134978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public LayoutParams generateLayoutParams(AttributeSet attrs) { 1135978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return new ScaledLayoutParams(getContext(), attrs); 1136978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1137978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1138978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 1139978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung protected boolean checkLayoutParams(LayoutParams p) { 1140978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return (p instanceof ScaledLayoutParams); 1141978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1142978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1143978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 1144978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 1145978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); 1146978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); 1147978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int width = widthSpecSize - getPaddingLeft() - getPaddingRight(); 1148978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int height = heightSpecSize - getPaddingTop() - getPaddingBottom(); 1149978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 1150978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format("onMeasure width: %d, height: %d", width, height)); 1151978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1152978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int count = getChildCount(); 1153978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mRectArray = new Rect[count]; 1154978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int i = 0; i < count; ++i) { 1155978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung View child = getChildAt(i); 1156978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ViewGroup.LayoutParams params = child.getLayoutParams(); 1157978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float scaleStartRow, scaleEndRow, scaleStartCol, scaleEndCol; 1158978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (!(params instanceof ScaledLayoutParams)) { 1159978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung throw new RuntimeException( 1160978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung "A child of ScaledLayout cannot have the UNSPECIFIED scale factors"); 1161978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1162978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleStartRow = ((ScaledLayoutParams) params).scaleStartRow; 1163978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleEndRow = ((ScaledLayoutParams) params).scaleEndRow; 1164978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleStartCol = ((ScaledLayoutParams) params).scaleStartCol; 1165978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleEndCol = ((ScaledLayoutParams) params).scaleEndCol; 1166978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (scaleStartRow < 0 || scaleStartRow > 1) { 1167978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung throw new RuntimeException("A child of ScaledLayout should have a range of " 1168978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung + "scaleStartRow between 0 and 1"); 1169978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1170978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (scaleEndRow < scaleStartRow || scaleStartRow > 1) { 1171978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung throw new RuntimeException("A child of ScaledLayout should have a range of " 1172978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung + "scaleEndRow between scaleStartRow and 1"); 1173978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1174978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (scaleEndCol < 0 || scaleEndCol > 1) { 1175978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung throw new RuntimeException("A child of ScaledLayout should have a range of " 1176978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung + "scaleStartCol between 0 and 1"); 1177978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1178978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (scaleEndCol < scaleStartCol || scaleEndCol > 1) { 1179978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung throw new RuntimeException("A child of ScaledLayout should have a range of " 1180978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung + "scaleEndCol between scaleStartCol and 1"); 1181978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1182978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 1183978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format("onMeasure child scaleStartRow: %f scaleEndRow: %f " 1184978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung + "scaleStartCol: %f scaleEndCol: %f", 1185978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleStartRow, scaleEndRow, scaleStartCol, scaleEndCol)); 1186978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1187978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mRectArray[i] = new Rect((int) (scaleStartCol * width), (int) (scaleStartRow 1188978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * height), (int) (scaleEndCol * width), (int) (scaleEndRow * height)); 1189978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int childWidthSpec = MeasureSpec.makeMeasureSpec( 1190978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung (int) (width * (scaleEndCol - scaleStartCol)), MeasureSpec.EXACTLY); 1191978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 1192978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung child.measure(childWidthSpec, childHeightSpec); 1193978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1194978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // If the height of the measured child view is bigger than the height of the 1195978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // calculated region by the given ScaleLayoutParams, the height of the region should 1196978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // be increased to fit the size of the child view. 1197978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (child.getMeasuredHeight() > mRectArray[i].height()) { 1198978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int overflowedHeight = child.getMeasuredHeight() - mRectArray[i].height(); 1199978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung overflowedHeight = (overflowedHeight + 1) / 2; 1200978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mRectArray[i].bottom += overflowedHeight; 1201978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mRectArray[i].top -= overflowedHeight; 1202978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mRectArray[i].top < 0) { 1203978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mRectArray[i].bottom -= mRectArray[i].top; 1204978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mRectArray[i].top = 0; 1205978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1206978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mRectArray[i].bottom > height) { 1207978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mRectArray[i].top -= mRectArray[i].bottom - height; 1208978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mRectArray[i].bottom = height; 1209978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1210978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1211978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung childHeightSpec = MeasureSpec.makeMeasureSpec( 1212978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung (int) (height * (scaleEndRow - scaleStartRow)), MeasureSpec.EXACTLY); 1213978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung child.measure(childWidthSpec, childHeightSpec); 1214978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1215978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1216978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Avoid overlapping rectangles. 1217978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Step 1. Sort rectangles by position (top-left). 1218978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int visibleRectCount = 0; 1219978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int[] visibleRectGroup = new int[count]; 1220978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Rect[] visibleRectArray = new Rect[count]; 1221978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int i = 0; i < count; ++i) { 1222978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (getChildAt(i).getVisibility() == View.VISIBLE) { 1223978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung visibleRectGroup[visibleRectCount] = visibleRectCount; 1224978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung visibleRectArray[visibleRectCount] = mRectArray[i]; 1225978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ++visibleRectCount; 1226978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1227978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1228978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Arrays.sort(visibleRectArray, 0, visibleRectCount, mRectTopLeftSorter); 1229978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1230978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Step 2. Move down if there are overlapping rectangles. 1231978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int i = 0; i < visibleRectCount - 1; ++i) { 1232978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int j = i + 1; j < visibleRectCount; ++j) { 1233978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (Rect.intersects(visibleRectArray[i], visibleRectArray[j])) { 1234978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung visibleRectGroup[j] = visibleRectGroup[i]; 1235978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung visibleRectArray[j].set(visibleRectArray[j].left, 1236978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung visibleRectArray[i].bottom, 1237978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung visibleRectArray[j].right, 1238978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung visibleRectArray[i].bottom + visibleRectArray[j].height()); 1239978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1240978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1241978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1242978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1243978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Step 3. Move up if there is any overflowed rectangle. 1244978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int i = visibleRectCount - 1; i >= 0; --i) { 1245978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (visibleRectArray[i].bottom > height) { 1246978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int overflowedHeight = visibleRectArray[i].bottom - height; 1247978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int j = 0; j <= i; ++j) { 1248978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (visibleRectGroup[i] == visibleRectGroup[j]) { 1249978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung visibleRectArray[j].set(visibleRectArray[j].left, 1250978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung visibleRectArray[j].top - overflowedHeight, 1251978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung visibleRectArray[j].right, 1252978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung visibleRectArray[j].bottom - overflowedHeight); 1253978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1254978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1255978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1256978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1257978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setMeasuredDimension(widthSpecSize, heightSpecSize); 1258978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1259978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1260978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 1261978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung protected void onLayout(boolean changed, int l, int t, int r, int b) { 1262978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int paddingLeft = getPaddingLeft(); 1263978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int paddingTop = getPaddingTop(); 1264978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int count = getChildCount(); 1265978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int i = 0; i < count; ++i) { 1266978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung View child = getChildAt(i); 1267978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (child.getVisibility() != GONE) { 1268978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int childLeft = paddingLeft + mRectArray[i].left; 1269978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int childTop = paddingTop + mRectArray[i].top; 1270978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int childBottom = paddingLeft + mRectArray[i].bottom; 1271978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int childRight = paddingTop + mRectArray[i].right; 1272978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 1273978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, String.format( 1274978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung "child layout bottom: %d left: %d right: %d top: %d", 1275978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung childBottom, childLeft, childRight, childTop)); 1276978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1277978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung child.layout(childLeft, childTop, childRight, childBottom); 1278978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1279978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1280978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1281978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1282978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 1283978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void dispatchDraw(Canvas canvas) { 1284978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int paddingLeft = getPaddingLeft(); 1285978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int paddingTop = getPaddingTop(); 1286978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int count = getChildCount(); 1287978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int i = 0; i < count; ++i) { 1288978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung View child = getChildAt(i); 1289978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (child.getVisibility() != GONE) { 1290978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (i >= mRectArray.length) { 1291978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1292978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1293978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int childLeft = paddingLeft + mRectArray[i].left; 1294978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int childTop = paddingTop + mRectArray[i].top; 1295978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung final int saveCount = canvas.save(); 1296978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung canvas.translate(childLeft, childTop); 1297978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung child.draw(canvas); 1298978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung canvas.restoreToCount(saveCount); 1299978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1300978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1301978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1302978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1303978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1304978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** 1305978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @hide 1306978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 1307978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * Layout containing the safe title area that helps the closed captions look more prominent. 1308978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 1309978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p>This is required by CEA-708B. 1310978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 1311978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung static class CCLayout extends ScaledLayout implements ClosedCaptionLayout { 1312978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final float SAFE_TITLE_AREA_SCALE_START_X = 0.1f; 1313978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final float SAFE_TITLE_AREA_SCALE_END_X = 0.9f; 1314978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final float SAFE_TITLE_AREA_SCALE_START_Y = 0.1f; 1315978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final float SAFE_TITLE_AREA_SCALE_END_Y = 0.9f; 1316978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1317978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private final ScaledLayout mSafeTitleAreaLayout; 1318978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1319978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CCLayout(Context context) { 1320978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung super(context); 1321978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1322978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mSafeTitleAreaLayout = new ScaledLayout(context); 1323978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung addView(mSafeTitleAreaLayout, new ScaledLayout.ScaledLayoutParams( 1324978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung SAFE_TITLE_AREA_SCALE_START_X, SAFE_TITLE_AREA_SCALE_END_X, 1325978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung SAFE_TITLE_AREA_SCALE_START_Y, SAFE_TITLE_AREA_SCALE_END_Y)); 1326978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1327978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1328978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void addOrUpdateViewToSafeTitleArea(CCWindowLayout captionWindowLayout, 1329978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ScaledLayoutParams scaledLayoutParams) { 1330978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int index = mSafeTitleAreaLayout.indexOfChild(captionWindowLayout); 1331978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (index < 0) { 1332978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mSafeTitleAreaLayout.addView(captionWindowLayout, scaledLayoutParams); 1333978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return; 1334978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1335978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mSafeTitleAreaLayout.updateViewLayout(captionWindowLayout, scaledLayoutParams); 1336978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1337978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1338978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void removeViewFromSafeTitleArea(CCWindowLayout captionWindowLayout) { 1339978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mSafeTitleAreaLayout.removeView(captionWindowLayout); 1340978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1341978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1342978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void setCaptionStyle(CaptionStyle style) { 1343978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung final int count = mSafeTitleAreaLayout.getChildCount(); 1344978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int i = 0; i < count; ++i) { 1345978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung final CCWindowLayout windowLayout = 1346978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung (CCWindowLayout) mSafeTitleAreaLayout.getChildAt(i); 1347978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung windowLayout.setCaptionStyle(style); 1348978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1349978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1350978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1351978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void setFontScale(float fontScale) { 1352978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung final int count = mSafeTitleAreaLayout.getChildCount(); 1353978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int i = 0; i < count; ++i) { 1354978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung final CCWindowLayout windowLayout = 1355978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung (CCWindowLayout) mSafeTitleAreaLayout.getChildAt(i); 1356978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung windowLayout.setFontScale(fontScale); 1357978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1358978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1359978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1360978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1361978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** 1362978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @hide 1363978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 1364978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * Renders the selected CC track. 1365978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 1366978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung static class CCHandler implements Handler.Callback { 1367978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // TODO: Remaining works 1368978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // CaptionTrackRenderer does not support the full spec of CEA-708. The remaining works are 1369978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // described in the follows. 1370978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // C0 Table: Backspace, FF, and HCR are not supported. The rule for P16 is not standardized 1371978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // but it is handled as EUC-KR charset for Korea broadcasting. 1372978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // C1 Table: All the styles of windows and pens except underline, italic, pen size, and pen 1373978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // offset specified in CEA-708 are ignored and this follows system wide CC 1374978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // preferences for look and feel. SetPenLocation is not implemented. 1375978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // G2 Table: TSP, NBTSP and BLK are not supported. 1376978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Text/commands: Word wrapping, fonts, row and column locking are not supported. 1377978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1378978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final String TAG = "CCHandler"; 1379978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final boolean DEBUG = false; 1380978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1381978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int TENTHS_OF_SECOND_IN_MILLIS = 100; 1382978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1383978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // According to CEA-708B, there can exist up to 8 caption windows. 1384978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int CAPTION_WINDOWS_MAX = 8; 1385978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int CAPTION_ALL_WINDOWS_BITMAP = 255; 1386978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1387978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int MSG_DELAY_CANCEL = 1; 1388978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int MSG_CAPTION_CLEAR = 2; 1389978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1390978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final long CAPTION_CLEAR_INTERVAL_MS = 60000; 1391978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1392978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private final CCLayout mCCLayout; 1393978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private boolean mIsDelayed = false; 1394978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private CCWindowLayout mCurrentWindowLayout; 1395978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private final CCWindowLayout[] mCaptionWindowLayouts = 1396978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung new CCWindowLayout[CAPTION_WINDOWS_MAX]; 1397978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private final ArrayList<Cea708CCParser.CaptionEvent> mPendingCaptionEvents 1398978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung = new ArrayList<>(); 1399978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private final Handler mHandler; 1400978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1401978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CCHandler(CCLayout ccLayout) { 1402978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCLayout = ccLayout; 1403978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mHandler = new Handler(this); 1404978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1405978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1406978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 1407978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public boolean handleMessage(Message msg) { 1408978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung switch (msg.what) { 1409978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case MSG_DELAY_CANCEL: 1410978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung delayCancel(); 1411978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return true; 1412978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case MSG_CAPTION_CLEAR: 1413978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung clearWindows(CAPTION_ALL_WINDOWS_BITMAP); 1414978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return true; 1415978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1416978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return false; 1417978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1418978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1419978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void processCaptionEvent(Cea708CCParser.CaptionEvent event) { 1420978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mIsDelayed) { 1421978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mPendingCaptionEvents.add(event); 1422978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return; 1423978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1424978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung switch (event.type) { 1425978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_BUFFER: 1426978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung sendBufferToCurrentWindow((String) event.obj); 1427978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1428978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_CONTROL: 1429978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung sendControlToCurrentWindow((char) event.obj); 1430978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1431978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_COMMAND_CWX: 1432978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setCurrentWindowLayout((int) event.obj); 1433978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1434978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_COMMAND_CLW: 1435978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung clearWindows((int) event.obj); 1436978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1437978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_COMMAND_DSW: 1438978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung displayWindows((int) event.obj); 1439978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1440978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_COMMAND_HDW: 1441978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung hideWindows((int) event.obj); 1442978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1443978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_COMMAND_TGW: 1444978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung toggleWindows((int) event.obj); 1445978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1446978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_COMMAND_DLW: 1447978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung deleteWindows((int) event.obj); 1448978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1449978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_COMMAND_DLY: 1450978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung delay((int) event.obj); 1451978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1452978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_COMMAND_DLC: 1453978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung delayCancel(); 1454978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1455978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_COMMAND_RST: 1456978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung reset(); 1457978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1458978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_COMMAND_SPA: 1459978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setPenAttr((Cea708CCParser.CaptionPenAttr) event.obj); 1460978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1461978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_COMMAND_SPC: 1462978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setPenColor((Cea708CCParser.CaptionPenColor) event.obj); 1463978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1464978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_COMMAND_SPL: 1465978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setPenLocation((Cea708CCParser.CaptionPenLocation) event.obj); 1466978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1467978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_COMMAND_SWA: 1468978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setWindowAttr((Cea708CCParser.CaptionWindowAttr) event.obj); 1469978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1470978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CAPTION_EMIT_TYPE_COMMAND_DFX: 1471978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung defineWindow((Cea708CCParser.CaptionWindow) event.obj); 1472978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1473978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1474978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1475978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1476978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // The window related caption commands 1477978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void setCurrentWindowLayout(int windowId) { 1478978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (windowId < 0 || windowId >= mCaptionWindowLayouts.length) { 1479978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return; 1480978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1481978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung CCWindowLayout windowLayout = mCaptionWindowLayouts[windowId]; 1482978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (windowLayout == null) { 1483978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return; 1484978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1485978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (DEBUG) { 1486978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.d(TAG, "setCurrentWindowLayout to " + windowId); 1487978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1488978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCurrentWindowLayout = windowLayout; 1489978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1490978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1491978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Each bit of windowBitmap indicates a window. 1492978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // If a bit is set, the window id is the same as the number of the trailing zeros of the 1493978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // bit. 1494978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private ArrayList<CCWindowLayout> getWindowsFromBitmap(int windowBitmap) { 1495978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ArrayList<CCWindowLayout> windows = new ArrayList<>(); 1496978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int i = 0; i < CAPTION_WINDOWS_MAX; ++i) { 1497978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if ((windowBitmap & (1 << i)) != 0) { 1498978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung CCWindowLayout windowLayout = mCaptionWindowLayouts[i]; 1499978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (windowLayout != null) { 1500978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung windows.add(windowLayout); 1501978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1502978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1503978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1504978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return windows; 1505978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1506978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1507978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void clearWindows(int windowBitmap) { 1508978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (windowBitmap == 0) { 1509978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return; 1510978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1511978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (CCWindowLayout windowLayout : getWindowsFromBitmap(windowBitmap)) { 1512978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung windowLayout.clear(); 1513978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1514978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1515978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1516978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void displayWindows(int windowBitmap) { 1517978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (windowBitmap == 0) { 1518978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return; 1519978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1520978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (CCWindowLayout windowLayout : getWindowsFromBitmap(windowBitmap)) { 1521978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung windowLayout.show(); 1522978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1523978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1524978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1525978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void hideWindows(int windowBitmap) { 1526978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (windowBitmap == 0) { 1527978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return; 1528978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1529978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (CCWindowLayout windowLayout : getWindowsFromBitmap(windowBitmap)) { 1530978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung windowLayout.hide(); 1531978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1532978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1533978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1534978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void toggleWindows(int windowBitmap) { 1535978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (windowBitmap == 0) { 1536978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return; 1537978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1538978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (CCWindowLayout windowLayout : getWindowsFromBitmap(windowBitmap)) { 1539978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (windowLayout.isShown()) { 1540978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung windowLayout.hide(); 1541978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else { 1542978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung windowLayout.show(); 1543978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1544978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1545978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1546978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1547978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void deleteWindows(int windowBitmap) { 1548978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (windowBitmap == 0) { 1549978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return; 1550978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1551978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (CCWindowLayout windowLayout : getWindowsFromBitmap(windowBitmap)) { 1552978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung windowLayout.removeFromCaptionView(); 1553978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCaptionWindowLayouts[windowLayout.getCaptionWindowId()] = null; 1554978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1555978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1556978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1557978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void reset() { 1558978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCurrentWindowLayout = null; 1559978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mIsDelayed = false; 1560978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mPendingCaptionEvents.clear(); 1561978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int i = 0; i < CAPTION_WINDOWS_MAX; ++i) { 1562978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCaptionWindowLayouts[i] != null) { 1563978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCaptionWindowLayouts[i].removeFromCaptionView(); 1564978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1565978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCaptionWindowLayouts[i] = null; 1566978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1567978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCLayout.setVisibility(View.INVISIBLE); 1568978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mHandler.removeMessages(MSG_CAPTION_CLEAR); 1569978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1570978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1571978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void setWindowAttr(Cea708CCParser.CaptionWindowAttr windowAttr) { 1572978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCurrentWindowLayout != null) { 1573978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCurrentWindowLayout.setWindowAttr(windowAttr); 1574978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1575978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1576978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1577978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void defineWindow(Cea708CCParser.CaptionWindow window) { 1578978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (window == null) { 1579978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return; 1580978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1581978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int windowId = window.id; 1582978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (windowId < 0 || windowId >= mCaptionWindowLayouts.length) { 1583978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return; 1584978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1585978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung CCWindowLayout windowLayout = mCaptionWindowLayouts[windowId]; 1586978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (windowLayout == null) { 1587978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung windowLayout = new CCWindowLayout(mCCLayout.getContext()); 1588978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1589978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung windowLayout.initWindow(mCCLayout, window); 1590978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCurrentWindowLayout = mCaptionWindowLayouts[windowId] = windowLayout; 1591978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1592978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1593978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // The job related caption commands 1594978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void delay(int tenthsOfSeconds) { 1595978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (tenthsOfSeconds < 0 || tenthsOfSeconds > 255) { 1596978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return; 1597978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1598978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mIsDelayed = true; 1599978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_DELAY_CANCEL), 1600978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung tenthsOfSeconds * TENTHS_OF_SECOND_IN_MILLIS); 1601978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1602978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1603978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void delayCancel() { 1604978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mIsDelayed = false; 1605978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung processPendingBuffer(); 1606978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1607978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1608978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void processPendingBuffer() { 1609978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (Cea708CCParser.CaptionEvent event : mPendingCaptionEvents) { 1610978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung processCaptionEvent(event); 1611978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1612978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mPendingCaptionEvents.clear(); 1613978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1614978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1615978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // The implicit write caption commands 1616978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void sendControlToCurrentWindow(char control) { 1617978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCurrentWindowLayout != null) { 1618978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCurrentWindowLayout.sendControl(control); 1619978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1620978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1621978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1622978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void sendBufferToCurrentWindow(String buffer) { 1623978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCurrentWindowLayout != null) { 1624978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCurrentWindowLayout.sendBuffer(buffer); 1625978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mHandler.removeMessages(MSG_CAPTION_CLEAR); 1626978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CAPTION_CLEAR), 1627978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung CAPTION_CLEAR_INTERVAL_MS); 1628978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1629978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1630978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1631978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // The pen related caption commands 1632978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void setPenAttr(Cea708CCParser.CaptionPenAttr attr) { 1633978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCurrentWindowLayout != null) { 1634978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCurrentWindowLayout.setPenAttr(attr); 1635978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1636978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1637978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1638978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void setPenColor(Cea708CCParser.CaptionPenColor color) { 1639978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCurrentWindowLayout != null) { 1640978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCurrentWindowLayout.setPenColor(color); 1641978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1642978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1643978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1644978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void setPenLocation(Cea708CCParser.CaptionPenLocation location) { 1645978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCurrentWindowLayout != null) { 1646978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCurrentWindowLayout.setPenLocation(location.row, location.column); 1647978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1648978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1649978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1650978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1651978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** 1652978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @hide 1653978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 1654978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * Layout which renders a caption window of CEA-708B. It contains a {@link TextView} that takes 1655978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * care of displaying the actual CC text. 1656978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 1657978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung static class CCWindowLayout extends RelativeLayout implements View.OnLayoutChangeListener { 1658978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final String TAG = "CCWindowLayout"; 1659978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1660978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final float PROPORTION_PEN_SIZE_SMALL = .75f; 1661978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final float PROPORTION_PEN_SIZE_LARGE = 1.25f; 1662978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1663978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // The following values indicates the maximum cell number of a window. 1664978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int ANCHOR_RELATIVE_POSITIONING_MAX = 99; 1665978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int ANCHOR_VERTICAL_MAX = 74; 1666978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int ANCHOR_HORIZONTAL_16_9_MAX = 209; 1667978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int MAX_COLUMN_COUNT_16_9 = 42; 1668978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1669978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // The following values indicates a gravity of a window. 1670978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int ANCHOR_MODE_DIVIDER = 3; 1671978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int ANCHOR_HORIZONTAL_MODE_LEFT = 0; 1672978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int ANCHOR_HORIZONTAL_MODE_CENTER = 1; 1673978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int ANCHOR_HORIZONTAL_MODE_RIGHT = 2; 1674978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int ANCHOR_VERTICAL_MODE_TOP = 0; 1675978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int ANCHOR_VERTICAL_MODE_CENTER = 1; 1676978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final int ANCHOR_VERTICAL_MODE_BOTTOM = 2; 1677978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1678978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private CCLayout mCCLayout; 1679978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1680978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private CCView mCCView; 1681978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private CaptionStyle mCaptionStyle; 1682978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int mRowLimit = 0; 1683978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private final SpannableStringBuilder mBuilder = new SpannableStringBuilder(); 1684978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private final List<CharacterStyle> mCharacterStyles = new ArrayList<>(); 1685978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int mCaptionWindowId; 1686978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int mRow = -1; 1687978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private float mFontScale; 1688978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private float mTextSize; 1689978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private String mWidestChar; 1690978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int mLastCaptionLayoutWidth; 1691978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int mLastCaptionLayoutHeight; 1692978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1693978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CCWindowLayout(Context context) { 1694978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this(context, null); 1695978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1696978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1697978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CCWindowLayout(Context context, AttributeSet attrs) { 1698978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this(context, attrs, 0); 1699978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1700978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1701978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CCWindowLayout(Context context, AttributeSet attrs, int defStyleAttr) { 1702978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this(context, attrs, defStyleAttr, 0); 1703978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1704978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1705978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CCWindowLayout(Context context, AttributeSet attrs, int defStyleAttr, 1706978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int defStyleRes) { 1707978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung super(context, attrs, defStyleAttr, defStyleRes); 1708978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1709978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Add a subtitle view to the layout. 1710978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCView = new CCView(context); 1711978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung LayoutParams params = new RelativeLayout.LayoutParams( 1712978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 1713978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung addView(mCCView, params); 1714978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1715978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Set the system wide CC preferences to the subtitle view. 1716978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung CaptioningManager captioningManager = 1717978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE); 1718978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mFontScale = captioningManager.getFontScale(); 1719978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setCaptionStyle(captioningManager.getUserStyle()); 1720978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCView.setText(""); 1721978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung updateWidestChar(); 1722978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1723978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1724978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void setCaptionStyle(CaptionStyle style) { 1725978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCaptionStyle = style; 1726978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCView.setCaptionStyle(style); 1727978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1728978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1729978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void setFontScale(float fontScale) { 1730978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mFontScale = fontScale; 1731978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung updateTextSize(); 1732978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1733978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1734978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public int getCaptionWindowId() { 1735978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return mCaptionWindowId; 1736978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1737978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1738978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void setCaptionWindowId(int captionWindowId) { 1739978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCaptionWindowId = captionWindowId; 1740978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1741978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1742978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void clear() { 1743978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung clearText(); 1744978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung hide(); 1745978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1746978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1747978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void show() { 1748978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setVisibility(View.VISIBLE); 1749978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung requestLayout(); 1750978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1751978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1752978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void hide() { 1753978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setVisibility(View.INVISIBLE); 1754978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung requestLayout(); 1755978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1756978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1757978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void setPenAttr(Cea708CCParser.CaptionPenAttr penAttr) { 1758978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCharacterStyles.clear(); 1759978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (penAttr.italic) { 1760978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCharacterStyles.add(new StyleSpan(Typeface.ITALIC)); 1761978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1762978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (penAttr.underline) { 1763978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCharacterStyles.add(new UnderlineSpan()); 1764978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1765978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung switch (penAttr.penSize) { 1766978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CaptionPenAttr.PEN_SIZE_SMALL: 1767978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCharacterStyles.add(new RelativeSizeSpan(PROPORTION_PEN_SIZE_SMALL)); 1768978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1769978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CaptionPenAttr.PEN_SIZE_LARGE: 1770978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCharacterStyles.add(new RelativeSizeSpan(PROPORTION_PEN_SIZE_LARGE)); 1771978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1772978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1773978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung switch (penAttr.penOffset) { 1774978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CaptionPenAttr.OFFSET_SUBSCRIPT: 1775978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCharacterStyles.add(new SubscriptSpan()); 1776978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1777978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case Cea708CCParser.CaptionPenAttr.OFFSET_SUPERSCRIPT: 1778978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCharacterStyles.add(new SuperscriptSpan()); 1779978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1780978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1781978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1782978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1783978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void setPenColor(Cea708CCParser.CaptionPenColor penColor) { 1784978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // TODO: apply pen colors or skip this and use the style of system wide CC style as is. 1785978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1786978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1787978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void setPenLocation(int row, int column) { 1788978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // TODO: change the location of pen based on row and column both. 1789978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mRow >= 0) { 1790978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int r = mRow; r < row; ++r) { 1791978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung appendText("\n"); 1792978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1793978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1794978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mRow = row; 1795978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1796978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1797978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void setWindowAttr(Cea708CCParser.CaptionWindowAttr windowAttr) { 1798978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // TODO: apply window attrs or skip this and use the style of system wide CC style as 1799978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // is. 1800978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1801978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1802978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void sendBuffer(String buffer) { 1803978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung appendText(buffer); 1804978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1805978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1806978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void sendControl(char control) { 1807978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // TODO: there are a bunch of ASCII-style control codes. 1808978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1809978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1810978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** 1811978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * This method places the window on a given CaptionLayout along with the anchor of the 1812978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * window. 1813978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p> 1814978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * According to CEA-708B, the anchor id indicates the gravity of the window as the follows. 1815978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * For example, A value 7 of a anchor id says that a window is align with its parent bottom 1816978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * and is located at the center horizontally of its parent. 1817978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * </p> 1818978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <h4>Anchor id and the gravity of a window</h4> 1819978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <table> 1820978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <tr> 1821978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <th>GRAVITY</th> 1822978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <th>LEFT</th> 1823978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <th>CENTER_HORIZONTAL</th> 1824978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <th>RIGHT</th> 1825978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * </tr> 1826978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <tr> 1827978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <th>TOP</th> 1828978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <td>0</td> 1829978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <td>1</td> 1830978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <td>2</td> 1831978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * </tr> 1832978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <tr> 1833978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <th>CENTER_VERTICAL</th> 1834978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <td>3</td> 1835978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <td>4</td> 1836978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <td>5</td> 1837978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * </tr> 1838978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <tr> 1839978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <th>BOTTOM</th> 1840978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <td>6</td> 1841978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <td>7</td> 1842978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <td>8</td> 1843978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * </tr> 1844978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * </table> 1845978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p> 1846978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * In order to handle the gravity of a window, there are two steps. First, set the size of 1847978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * the window. Since the window will be positioned at ScaledLayout, the size factors are 1848978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * determined in a ratio. Second, set the gravity of the window. CaptionWindowLayout is 1849978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * inherited from RelativeLayout. Hence, we could set the gravity of its child view, 1850978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * SubtitleView. 1851978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * </p> 1852978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * <p> 1853978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * The gravity of the window is also related to its size. When it should be pushed to a one 1854978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * of the end of the window, like LEFT, RIGHT, TOP or BOTTOM, the anchor point should be a 1855978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * boundary of the window. When it should be pushed in the horizontal/vertical center of its 1856978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * container, the horizontal/vertical center point of the window should be the same as the 1857978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * anchor point. 1858978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * </p> 1859978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * 1860978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @param ccLayout a given CaptionLayout, which contains a safe title area. 1861978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * @param captionWindow a given CaptionWindow, which stores the construction info of the 1862978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung * window. 1863978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung */ 1864978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void initWindow(CCLayout ccLayout, Cea708CCParser.CaptionWindow captionWindow) { 1865978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCCLayout != ccLayout) { 1866978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCCLayout != null) { 1867978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCLayout.removeOnLayoutChangeListener(this); 1868978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1869978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCLayout = ccLayout; 1870978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCLayout.addOnLayoutChangeListener(this); 1871978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung updateWidestChar(); 1872978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1873978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1874978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Both anchor vertical and horizontal indicates the position cell number of the window. 1875978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float scaleRow = (float) captionWindow.anchorVertical / 1876978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung (captionWindow.relativePositioning 1877978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ? ANCHOR_RELATIVE_POSITIONING_MAX : ANCHOR_VERTICAL_MAX); 1878978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1879978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Assumes it has a wide aspect ratio track. 1880978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float scaleCol = (float) captionWindow.anchorHorizontal / 1881978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung (captionWindow.relativePositioning ? ANCHOR_RELATIVE_POSITIONING_MAX 1882978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung : ANCHOR_HORIZONTAL_16_9_MAX); 1883978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1884978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // The range of scaleRow/Col need to be verified to be in [0, 1]. 1885978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Otherwise a RuntimeException will be raised in ScaledLayout. 1886978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (scaleRow < 0 || scaleRow > 1) { 1887978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.i(TAG, "The vertical position of the anchor point should be at the range of 0 " 1888978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung + "and 1 but " + scaleRow); 1889978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleRow = Math.max(0, Math.min(scaleRow, 1)); 1890978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1891978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (scaleCol < 0 || scaleCol > 1) { 1892978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Log.i(TAG, "The horizontal position of the anchor point should be at the range of 0" 1893978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung + " and 1 but " + scaleCol); 1894978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleCol = Math.max(0, Math.min(scaleCol, 1)); 1895978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1896978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int gravity = Gravity.CENTER; 1897978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int horizontalMode = captionWindow.anchorId % ANCHOR_MODE_DIVIDER; 1898978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int verticalMode = captionWindow.anchorId / ANCHOR_MODE_DIVIDER; 1899978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float scaleStartRow = 0; 1900978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float scaleEndRow = 1; 1901978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float scaleStartCol = 0; 1902978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float scaleEndCol = 1; 1903978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung switch (horizontalMode) { 1904978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case ANCHOR_HORIZONTAL_MODE_LEFT: 1905978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung gravity = Gravity.LEFT; 1906978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCView.setAlignment(Alignment.ALIGN_NORMAL); 1907978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleStartCol = scaleCol; 1908978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1909978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case ANCHOR_HORIZONTAL_MODE_CENTER: 1910978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float gap = Math.min(1 - scaleCol, scaleCol); 1911978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1912978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Since all TV sets use left text alignment instead of center text alignment 1913978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // for this case, we follow the industry convention if possible. 1914978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int columnCount = captionWindow.columnCount + 1; 1915978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung columnCount = Math.min(getScreenColumnCount(), columnCount); 1916978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung StringBuilder widestTextBuilder = new StringBuilder(); 1917978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int i = 0; i < columnCount; ++i) { 1918978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung widestTextBuilder.append(mWidestChar); 1919978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1920978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Paint paint = new Paint(); 1921978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung paint.setTypeface(mCaptionStyle.getTypeface()); 1922978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung paint.setTextSize(mTextSize); 1923978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float maxWindowWidth = paint.measureText(widestTextBuilder.toString()); 1924978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float halfMaxWidthScale = mCCLayout.getWidth() > 0 1925978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ? maxWindowWidth / 2.0f / (mCCLayout.getWidth() * 0.8f) : 0.0f; 1926978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (halfMaxWidthScale > 0f && halfMaxWidthScale < scaleCol) { 1927978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Calculate the expected max window size based on the column count of the 1928978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // caption window multiplied by average alphabets char width, then align the 1929978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // left side of the window with the left side of the expected max window. 1930978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung gravity = Gravity.LEFT; 1931978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCView.setAlignment(Alignment.ALIGN_NORMAL); 1932978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleStartCol = scaleCol - halfMaxWidthScale; 1933978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleEndCol = 1.0f; 1934978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else { 1935978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // The gap will be the minimum distance value of the distances from both 1936978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // horizontal end points to the anchor point. 1937978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // If scaleCol <= 0.5, the range of scaleCol is [0, the anchor point * 2]. 1938978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // If scaleCol > 0.5, the range of scaleCol is 1939978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // [(1 - the anchor point) * 2, 1]. 1940978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // The anchor point is located at the horizontal center of the window in 1941978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // both cases. 1942978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung gravity = Gravity.CENTER_HORIZONTAL; 1943978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCView.setAlignment(Alignment.ALIGN_CENTER); 1944978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleStartCol = scaleCol - gap; 1945978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleEndCol = scaleCol + gap; 1946978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1947978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1948978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case ANCHOR_HORIZONTAL_MODE_RIGHT: 1949978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung gravity = Gravity.RIGHT; 1950978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCView.setAlignment(Alignment.ALIGN_RIGHT); 1951978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleEndCol = scaleCol; 1952978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1953978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1954978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung switch (verticalMode) { 1955978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case ANCHOR_VERTICAL_MODE_TOP: 1956978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung gravity |= Gravity.TOP; 1957978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleStartRow = scaleRow; 1958978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1959978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case ANCHOR_VERTICAL_MODE_CENTER: 1960978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung gravity |= Gravity.CENTER_VERTICAL; 1961978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1962978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // See the above comment. 1963978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float gap = Math.min(1 - scaleRow, scaleRow); 1964978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleStartRow = scaleRow - gap; 1965978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleEndRow = scaleRow + gap; 1966978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1967978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung case ANCHOR_VERTICAL_MODE_BOTTOM: 1968978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung gravity |= Gravity.BOTTOM; 1969978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung scaleEndRow = scaleRow; 1970978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung break; 1971978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1972978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCLayout.addOrUpdateViewToSafeTitleArea(this, new ScaledLayout 1973978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung .ScaledLayoutParams(scaleStartRow, scaleEndRow, scaleStartCol, scaleEndCol)); 1974978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setCaptionWindowId(captionWindow.id); 1975978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setRowLimit(captionWindow.rowCount); 1976978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setGravity(gravity); 1977978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (captionWindow.visible) { 1978978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung show(); 1979978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else { 1980978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung hide(); 1981978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1982978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1983978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1984978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung @Override 1985978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, 1986978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int oldTop, int oldRight, int oldBottom) { 1987978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int width = right - left; 1988978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int height = bottom - top; 1989978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (width != mLastCaptionLayoutWidth || height != mLastCaptionLayoutHeight) { 1990978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mLastCaptionLayoutWidth = width; 1991978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mLastCaptionLayoutHeight = height; 1992978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung updateTextSize(); 1993978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1994978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 1995978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 1996978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void updateWidestChar() { 1997978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Paint paint = new Paint(); 1998978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung paint.setTypeface(mCaptionStyle.getTypeface()); 1999978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Charset latin1 = Charset.forName("ISO-8859-1"); 2000978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float widestCharWidth = 0f; 2001978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int i = 0; i < 256; ++i) { 2002978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung String ch = new String(new byte[]{(byte) i}, latin1); 2003978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float charWidth = paint.measureText(ch); 2004978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (widestCharWidth < charWidth) { 2005978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung widestCharWidth = charWidth; 2006978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mWidestChar = ch; 2007978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2008978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2009978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung updateTextSize(); 2010978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2011978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2012978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void updateTextSize() { 2013978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCCLayout == null) return; 2014978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2015978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Calculate text size based on the max window size. 2016978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung StringBuilder widestTextBuilder = new StringBuilder(); 2017978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int screenColumnCount = getScreenColumnCount(); 2018978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (int i = 0; i < screenColumnCount; ++i) { 2019978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung widestTextBuilder.append(mWidestChar); 2020978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2021978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung String widestText = widestTextBuilder.toString(); 2022978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Paint paint = new Paint(); 2023978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung paint.setTypeface(mCaptionStyle.getTypeface()); 2024978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float startFontSize = 0f; 2025978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float endFontSize = 255f; 2026978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung while (startFontSize < endFontSize) { 2027978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float testTextSize = (startFontSize + endFontSize) / 2f; 2028978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung paint.setTextSize(testTextSize); 2029978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung float width = paint.measureText(widestText); 2030978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCCLayout.getWidth() * 0.8f > width) { 2031978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung startFontSize = testTextSize + 0.01f; 2032978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else { 2033978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung endFontSize = testTextSize - 0.01f; 2034978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2035978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2036978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mTextSize = endFontSize * mFontScale; 2037978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCView.setTextSize(mTextSize); 2038978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2039978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2040978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private int getScreenColumnCount() { 2041978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Assume it has a wide aspect ratio track. 2042978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung return MAX_COLUMN_COUNT_16_9; 2043978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2044978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2045978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void removeFromCaptionView() { 2046978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (mCCLayout != null) { 2047978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCLayout.removeViewFromSafeTitleArea(this); 2048978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCLayout.removeOnLayoutChangeListener(this); 2049978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCLayout = null; 2050978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2051978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2052978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2053978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void setText(String text) { 2054978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung updateText(text, false); 2055978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2056978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2057978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void appendText(String text) { 2058978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung updateText(text, true); 2059978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2060978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2061978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void clearText() { 2062978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mBuilder.clear(); 2063978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCView.setText(""); 2064978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2065978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2066978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private void updateText(String text, boolean appended) { 2067978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (!appended) { 2068978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mBuilder.clear(); 2069978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2070978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (text != null && text.length() > 0) { 2071978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int length = mBuilder.length(); 2072978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mBuilder.append(text); 2073978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung for (CharacterStyle characterStyle : mCharacterStyles) { 2074978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mBuilder.setSpan(characterStyle, length, mBuilder.length(), 2075978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 2076978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2077978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2078978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung String[] lines = TextUtils.split(mBuilder.toString(), "\n"); 2079978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2080978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Truncate text not to exceed the row limit. 2081978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Plus one here since the range of the rows is [0, mRowLimit]. 2082978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung String truncatedText = TextUtils.join("\n", Arrays.copyOfRange( 2083978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung lines, Math.max(0, lines.length - (mRowLimit + 1)), lines.length)); 2084978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mBuilder.delete(0, mBuilder.length() - truncatedText.length()); 2085978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2086978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung // Trim the buffer first then set text to CCView. 2087978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int start = 0, last = mBuilder.length() - 1; 2088978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int end = last; 2089978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung while ((start <= end) && (mBuilder.charAt(start) <= ' ')) { 2090978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ++start; 2091978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2092978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung while ((end >= start) && (mBuilder.charAt(end) <= ' ')) { 2093978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung --end; 2094978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2095978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (start == 0 && end == last) { 2096978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCView.setText(mBuilder); 2097978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } else { 2098978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung SpannableStringBuilder trim = new SpannableStringBuilder(); 2099978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung trim.append(mBuilder); 2100978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (end < last) { 2101978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung trim.delete(end + 1, last + 1); 2102978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2103978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (start > 0) { 2104978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung trim.delete(0, start); 2105978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2106978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mCCView.setText(trim); 2107978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2108978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2109978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2110978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void setRowLimit(int rowLimit) { 2111978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung if (rowLimit < 0) { 2112978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung throw new IllegalArgumentException("A rowLimit should have a positive number"); 2113978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2114978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung mRowLimit = rowLimit; 2115978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2116978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2117978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2118978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung /** @hide */ 2119978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung static class CCView extends SubtitleView { 2120978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung private static final CaptionStyle DEFAULT_CAPTION_STYLE = CaptionStyle.DEFAULT; 2121978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2122978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CCView(Context context) { 2123978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this(context, null); 2124978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2125978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2126978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CCView(Context context, AttributeSet attrs) { 2127978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this(context, attrs, 0); 2128978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2129978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2130978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CCView(Context context, AttributeSet attrs, int defStyleAttr) { 2131978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung this(context, attrs, defStyleAttr, 0); 2132978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2133978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2134978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public CCView(Context context, AttributeSet attrs, int defStyleAttr, 2135978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung int defStyleRes) { 2136978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung super(context, attrs, defStyleAttr, defStyleRes); 2137978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2138978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung 2139978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung public void setCaptionStyle(CaptionStyle style) { 2140978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setForegroundColor(style.hasForegroundColor() 2141978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ? style.foregroundColor : DEFAULT_CAPTION_STYLE.foregroundColor); 2142978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setBackgroundColor(style.hasBackgroundColor() 2143978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ? style.backgroundColor : DEFAULT_CAPTION_STYLE.backgroundColor); 2144978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setEdgeType(style.hasEdgeType() 2145978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ? style.edgeType : DEFAULT_CAPTION_STYLE.edgeType); 2146978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setEdgeColor(style.hasEdgeColor() 2147978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung ? style.edgeColor : DEFAULT_CAPTION_STYLE.edgeColor); 2148978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung setTypeface(style.getTypeface()); 2149978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2150978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung } 2151978bf5eff0f5bc8a8878696bc886d8b99a29ee39Jaesung Chung} 2152