13b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang/*
23b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang * Copyright (C) 2011 The Android Open Source Project
33b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang *
43b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang * Licensed under the Apache License, Version 2.0 (the "License");
53b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang * you may not use this file except in compliance with the License.
63b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang * You may obtain a copy of the License at
73b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang *
83b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang *      http://www.apache.org/licenses/LICENSE-2.0
93b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang *
103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang * Unless required by applicable law or agreed to in writing, software
113b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang * distributed under the License is distributed on an "AS IS" BASIS,
123b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang * See the License for the specific language governing permissions and
143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang * limitations under the License.
153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang */
163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
173b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang#include "TextDescriptions.h"
183b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang#include <media/stagefright/Utils.h>
193b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang#include <media/stagefright/MediaErrors.h>
203b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
213b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wangnamespace android {
223b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
233b573f7bf1c5736d500e39013b8d32478a1429e6Gloria WangTextDescriptions::TextDescriptions() {
243b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang}
253b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
263b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wangstatus_t TextDescriptions::getParcelOfDescriptions(
273b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        const uint8_t *data, ssize_t size,
283b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        uint32_t flags, int timeMs, Parcel *parcel) {
293b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    parcel->freeData();
303b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
313b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    if (flags & IN_BAND_TEXT_3GPP) {
323b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        if (flags & GLOBAL_DESCRIPTIONS) {
33d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            return extract3GPPGlobalDescriptions(data, size, parcel);
343b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        } else if (flags & LOCAL_DESCRIPTIONS) {
35d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            return extract3GPPLocalDescriptions(data, size, timeMs, parcel);
363b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
373b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    } else if (flags & OUT_OF_BAND_TEXT_SRT) {
383b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        if (flags & LOCAL_DESCRIPTIONS) {
393b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            return extractSRTLocalDescriptions(data, size, timeMs, parcel);
403b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
413b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    }
423b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
433b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    return ERROR_UNSUPPORTED;
443b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang}
453b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
463b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang// Parse the SRT text sample, and store the timing and text sample in a Parcel.
473b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang// The Parcel will be sent to MediaPlayer.java through event, and will be
483b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang// parsed in TimedText.java.
493b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wangstatus_t TextDescriptions::extractSRTLocalDescriptions(
503b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        const uint8_t *data, ssize_t size, int timeMs, Parcel *parcel) {
513b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    parcel->writeInt32(KEY_LOCAL_SETTING);
523b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    parcel->writeInt32(KEY_START_TIME);
533b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    parcel->writeInt32(timeMs);
543b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
553b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    parcel->writeInt32(KEY_STRUCT_TEXT);
563b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    // write the size of the text sample
573b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    parcel->writeInt32(size);
583b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    // write the text sample as a byte array
593b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    parcel->writeInt32(size);
603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    parcel->write(data, size);
613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
623b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    return OK;
633b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang}
643b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
653b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang// Extract the local 3GPP display descriptions. 3GPP local descriptions
663b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang// are appended to the text sample if any. The descriptions could include
673b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang// information such as text styles, highlights, karaoke and so on. They
683b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang// are contained in different boxes, such as 'styl' box contains text
693b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang// styles, and 'krok' box contains karaoke timing and positions.
703b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wangstatus_t TextDescriptions::extract3GPPLocalDescriptions(
713b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        const uint8_t *data, ssize_t size,
72d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        int timeMs, Parcel *parcel) {
73d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
74d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    parcel->writeInt32(KEY_LOCAL_SETTING);
75d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
76d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    // write start time to display this text sample
77d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    parcel->writeInt32(KEY_START_TIME);
78d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    parcel->writeInt32(timeMs);
79d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
80d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    if (size < 2) {
81d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        return OK;
823b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    }
83d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    ssize_t textLen = (*data) << 8 | (*(data + 1));
843b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
85d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    if (size < textLen + 2) {
86d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        return OK;
87d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    }
883b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
89d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    // write text sample length and text sample itself
90d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    parcel->writeInt32(KEY_STRUCT_TEXT);
91d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    parcel->writeInt32(textLen);
92d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    parcel->writeInt32(textLen);
93d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    parcel->write(data + 2, textLen);
94d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
95d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    if (size > textLen + 2) {
96d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        data += (textLen + 2);
97d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        size -= (textLen + 2);
98d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    } else {
993b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        return OK;
1003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    }
1013b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
102d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    while (size >= 8) {
103d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        const uint8_t *tmpData = data;
104d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        ssize_t chunkSize = U32_AT(tmpData);      // size includes size and type
105d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        uint32_t chunkType = U32_AT(tmpData + 4);
1063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
107d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        if (chunkSize <= 8 || chunkSize > size) {
108d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            return OK;
109d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        }
1103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
111d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        size_t remaining = chunkSize - 8;
1123b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
113d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        tmpData += 8;
1143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
115d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        switch(chunkType) {
116d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // 'styl' box specifies the style of the text.
117d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            case FOURCC('s', 't', 'y', 'l'):
118d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            {
119d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining < 2) {
120d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
121d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
122d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                size_t dataPos = parcel->dataPosition();
123d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                uint16_t count = U16_AT(tmpData);
1243b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
125d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                tmpData += 2;
126d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= 2;
1273b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
128d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                for (int i = 0; i < count; i++) {
129d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    if (remaining < 12) {
130d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                        // roll back
131d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                        parcel->setDataPosition(dataPos);
132d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                        return OK;
133d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    }
134d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(KEY_STRUCT_STYLE_LIST);
135d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(KEY_START_CHAR);
136d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(U16_AT(tmpData));
1373b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
138d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(KEY_END_CHAR);
139d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(U16_AT(tmpData + 2));
1403b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
141d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(KEY_FONT_ID);
142d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(U16_AT(tmpData + 4));
1433b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
144d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(KEY_STYLE_FLAGS);
145d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(*(tmpData + 6));
146d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
147d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(KEY_FONT_SIZE);
148d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(*(tmpData + 7));
149d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
150d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(KEY_TEXT_COLOR_RGBA);
151d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    uint32_t rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16
152d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                        | *(tmpData + 10) << 8 | *(tmpData + 11);
153d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(rgba);
154d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
155d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    tmpData += 12;
156d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    remaining -= 12;
157d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
158d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
159d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                break;
160d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            }
161d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // 'krok' box. The number of highlight events is specified, and each
162d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // event is specified by a starting and ending char offset and an end
163d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // time for the event.
164d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            case FOURCC('k', 'r', 'o', 'k'):
165d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            {
166d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining < 6) {
167d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
168d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
169d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                size_t dataPos = parcel->dataPosition();
170d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
171d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_STRUCT_KARAOKE_LIST);
172d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
173d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                int startTime = U32_AT(tmpData);
174d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                uint16_t count = U16_AT(tmpData + 4);
175d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(count);
176d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
177d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                tmpData += 6;
178d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= 6;
179d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                int lastEndTime = 0;
180d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
181d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                for (int i = 0; i < count; i++) {
182d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    if (remaining < 8) {
183d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                        // roll back
184d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                        parcel->setDataPosition(dataPos);
185d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                        return OK;
186d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    }
187d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(startTime + lastEndTime);
188d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
189d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    lastEndTime = U32_AT(tmpData);
190d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(lastEndTime);
191d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
192d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(U16_AT(tmpData + 4));
193d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(U16_AT(tmpData + 6));
194d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
195d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    tmpData += 8;
196d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    remaining -= 8;
197d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
198d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
199d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                break;
2003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
201d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // 'hlit' box specifies highlighted text
202d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            case FOURCC('h', 'l', 'i', 't'):
203d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            {
204d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining < 4) {
205d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
206d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
2073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
208d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_STRUCT_HIGHLIGHT_LIST);
2093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
210d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                // the start char offset to highlight
211d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U16_AT(tmpData));
212d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                // the last char offset to highlight
213d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U16_AT(tmpData + 2));
2143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
215d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                tmpData += 4;
216d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= 4;
217d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                break;
218d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            }
219d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // 'hclr' box specifies the RGBA color: 8 bits each of
220d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // red, green, blue, and an alpha(transparency) value
221d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            case FOURCC('h', 'c', 'l', 'r'):
222d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            {
223d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining < 4) {
224d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
225d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
226d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_HIGHLIGHT_COLOR_RGBA);
227d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
228d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                uint32_t rgba = *(tmpData) << 24 | *(tmpData + 1) << 16
229d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    | *(tmpData + 2) << 8 | *(tmpData + 3);
230d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(rgba);
231d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
232d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                tmpData += 4;
233d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= 4;
234d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                break;
235d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            }
236d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // 'dlay' box specifies a delay after a scroll in and/or
237d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // before scroll out.
238d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            case FOURCC('d', 'l', 'a', 'y'):
239d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            {
240d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining < 4) {
241d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
242d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
243d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_SCROLL_DELAY);
244d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
245d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                uint32_t delay = *(tmpData) << 24 | *(tmpData + 1) << 16
246d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    | *(tmpData + 2) << 8 | *(tmpData + 3);
247d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(delay);
248d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
249d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                tmpData += 4;
250d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= 4;
251d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                break;
252d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            }
253d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // 'href' box for hyper text link
254d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            case FOURCC('h', 'r', 'e', 'f'):
255d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            {
256d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining < 5) {
257d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
258d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
2593b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
260d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                size_t dataPos = parcel->dataPosition();
2613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
262d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_STRUCT_HYPER_TEXT_LIST);
2633b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
264d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                // the start offset of the text to be linked
265d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U16_AT(tmpData));
266d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                // the end offset of the text
267d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U16_AT(tmpData + 2));
2683b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
269d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                // the number of bytes in the following URL
270d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                size_t len = *(tmpData + 4);
271d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(len);
272d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
273d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= 5;
274d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
275d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining  < len) {
276d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->setDataPosition(dataPos);
277d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
278d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
279d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                // the linked-to URL
280d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(len);
281d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->write(tmpData + 5, len);
282d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
283d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                tmpData += (5 + len);
284d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= len;
285d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
286d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining  < 1) {
287d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->setDataPosition(dataPos);
288d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
289d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
290d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
291d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                // the number of bytes in the following "alt" string
292d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                len = *tmpData;
293d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(len);
294d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
295d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                tmpData += 1;
296d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= 1;
297d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining  < len) {
298d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->setDataPosition(dataPos);
299d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
300d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
301d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
302d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                // an "alt" string for user display
303d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(len);
304d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->write(tmpData, len);
305d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
306d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                tmpData += 1;
307d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= 1;
308d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                break;
309d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            }
310d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // 'tbox' box to indicate the position of the text with values
311d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // of top, left, bottom and right
312d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            case FOURCC('t', 'b', 'o', 'x'):
313d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            {
314d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining < 8) {
315d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
316d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
317d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_STRUCT_TEXT_POS);
318d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U16_AT(tmpData));
319d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U16_AT(tmpData + 2));
3203b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                parcel->writeInt32(U16_AT(tmpData + 4));
3213b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                parcel->writeInt32(U16_AT(tmpData + 6));
3223b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
3233b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                tmpData += 8;
324d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= 8;
325d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                break;
3263b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
327d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // 'blnk' to specify the char range to be blinked
328d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            case FOURCC('b', 'l', 'n', 'k'):
329d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            {
330d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining < 4) {
331d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
332d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
3333b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
334d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_STRUCT_BLINKING_TEXT_LIST);
3353b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
336d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                // start char offset
337d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U16_AT(tmpData));
338d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                // end char offset
339d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U16_AT(tmpData + 2));
3403b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
341d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                tmpData += 4;
342d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= 4;
343d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                break;
344d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            }
345d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // 'twrp' box specifies text wrap behavior. If the value if 0x00,
346d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // then no wrap. If it's 0x01, then automatic 'soft' wrap is enabled.
347d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            // 0x02-0xff are reserved.
348d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            case FOURCC('t', 'w', 'r', 'p'):
349d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            {
350d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining < 1) {
351d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
352d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
353d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_WRAP_TEXT);
354d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(*tmpData);
355d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
356d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                tmpData += 1;
357d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= 1;
358d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                break;
359d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            }
360d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            default:
361d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            {
362d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                break;
363d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            }
3643b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
3653b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
366d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        data += chunkSize;
367d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        size -= chunkSize;
368d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    }
369d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
370d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    return OK;
371d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen}
3723b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
373d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen// To extract box 'tx3g' defined in 3GPP TS 26.245, and store it in a Parcel
374d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissenstatus_t TextDescriptions::extract3GPPGlobalDescriptions(
375d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        const uint8_t *data, ssize_t size, Parcel *parcel) {
376d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
377d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    parcel->writeInt32(KEY_GLOBAL_SETTING);
3783b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
379d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen    while (size >= 8) {
380d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        ssize_t chunkSize = U32_AT(data);
381d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        uint32_t chunkType = U32_AT(data + 4);
382d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        const uint8_t *tmpData = data;
383d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        tmpData += 8;
384d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        size_t remaining = size - 8;
3853b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
386d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        if (size < chunkSize) {
387d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            return OK;
3883b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
389d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        switch(chunkType) {
390d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            case FOURCC('t', 'x', '3', 'g'):
391d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            {
392d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining < 18) { // 8 just below, and another 10 a little further down
393d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
394d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
395d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                tmpData += 8; // skip the first 8 bytes
396d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -=8;
397d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_DISPLAY_FLAGS);
398d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U32_AT(tmpData));
399d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
400d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_STRUCT_JUSTIFICATION);
401d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(tmpData[4]);
402d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(tmpData[5]);
403d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
404d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_BACKGROUND_COLOR_RGBA);
405d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                uint32_t rgba = *(tmpData + 6) << 24 | *(tmpData + 7) << 16
406d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    | *(tmpData + 8) << 8 | *(tmpData + 9);
407d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(rgba);
4083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
409d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                tmpData += 10;
410d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= 10;
4113b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
412d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining < 8) {
413d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
414d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
415d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_STRUCT_TEXT_POS);
416d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U16_AT(tmpData));
417d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U16_AT(tmpData + 2));
418d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U16_AT(tmpData + 4));
419d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U16_AT(tmpData + 6));
4203b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
421d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                tmpData += 8;
422d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= 8;
4233b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
424d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining < 12) {
425d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
426d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
427d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_STRUCT_STYLE_LIST);
428d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_START_CHAR);
429d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U16_AT(tmpData));
4303b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
431d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_END_CHAR);
432d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U16_AT(tmpData + 2));
4333b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
434d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_FONT_ID);
435d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(U16_AT(tmpData + 4));
4363b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
437d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_STYLE_FLAGS);
438d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(*(tmpData + 6));
4393b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
440d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_FONT_SIZE);
441d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(*(tmpData + 7));
4423b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
443d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_TEXT_COLOR_RGBA);
444d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16
445d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    | *(tmpData + 10) << 8 | *(tmpData + 11);
446d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(rgba);
4473b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
448d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                tmpData += 12;
449d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= 12;
4503b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
451d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                if (remaining < 2) {
452d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    return OK;
453d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
4543b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
455d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                size_t dataPos = parcel->dataPosition();
4563b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
457d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(KEY_STRUCT_FONT_LIST);
458d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                uint16_t count = U16_AT(tmpData);
459d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                parcel->writeInt32(count);
4603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
461d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                tmpData += 2;
462d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                remaining -= 2;
4633b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
464d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                for (int i = 0; i < count; i++) {
465d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    if (remaining < 3) {
466d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                        // roll back
467d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                        parcel->setDataPosition(dataPos);
468d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                        return OK;
469d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    }
470d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    // font ID
471d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(U16_AT(tmpData));
4723b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
473d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    // font name length
474d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->writeInt32(*(tmpData + 2));
4753b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
476d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    size_t len = *(tmpData + 2);
4773b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
478d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    tmpData += 3;
479d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    remaining -= 3;
4803b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
481d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    if (remaining < len) {
482d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                        // roll back
483d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                        parcel->setDataPosition(dataPos);
484d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                        return OK;
485d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    }
4863b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
487d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    parcel->write(tmpData, len);
488d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    tmpData += len;
489d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                    remaining -= len;
490d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                }
4913b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
492d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                // there is a "DisparityBox" after this according to the spec, but we ignore it
493d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                break;
494d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            }
495d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            default:
496d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            {
497d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen                break;
498d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen            }
499d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        }
500d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen
501d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        data += chunkSize;
502d53aced041b7214a92b1f2fd5970d895bb9934e5Marco Nelissen        size -= chunkSize;
5033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    }
5043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
5053b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    return OK;
5063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang}
5073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
5083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang}  // namespace android
509