Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/vcl/source/font/EOTConverter.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 */
9
10
#include <string.h>
11
#include <vector>
12
#include <tools/vcompat.hxx>
13
#include <cstdio>
14
#include <tools/stream.hxx>
15
#include <vcl/font/EOTConverter.hxx>
16
#include <osl/endian.h>
17
#include <font/TTFStructure.hxx>
18
#include <font/TTFReader.hxx>
19
20
namespace font
21
{
22
namespace
23
{
24
// Writes padding, length and string data to font output
25
void writeNameTableString(font::TTFFont& rFont,
26
                          std::unique_ptr<NameTableHandler>& pNameTableHandler,
27
                          font::NameID eNameID, std::vector<sal_uInt8>& rEotOutput)
28
3.04k
{
29
3.04k
    sal_uInt64 nOffset = 0;
30
3.04k
    sal_uInt16 nLength = 0;
31
32
    // Padding
33
3.04k
    rEotOutput.push_back(0);
34
3.04k
    rEotOutput.push_back(0);
35
36
3.04k
    if (pNameTableHandler
37
3.04k
        && pNameTableHandler->findEnglishUnicodeNameOffset(eNameID, nOffset, nLength))
38
297
    {
39
        // Length
40
297
        rEotOutput.push_back(sal_uInt8((nLength + 2) & 0xff));
41
297
        rEotOutput.push_back(sal_uInt8((nLength + 2) >> 8));
42
43
297
        OUString aString = rFont.getNameTableString(nOffset, nLength);
44
445k
        for (sal_Int32 i = 0; i < aString.getLength(); i++)
45
445k
        {
46
445k
            sal_Unicode nUniChar = aString[i];
47
445k
            rEotOutput.push_back(sal_uInt8(nUniChar & 0xff));
48
445k
            rEotOutput.push_back(sal_uInt8(nUniChar >> 8));
49
445k
        }
50
        // null terminated
51
297
        rEotOutput.push_back(sal_uInt8(0));
52
297
        rEotOutput.push_back(sal_uInt8(0));
53
297
    }
54
2.74k
    else
55
2.74k
    {
56
        // Length 0
57
2.74k
        rEotOutput.push_back(sal_uInt8(0));
58
2.74k
        rEotOutput.push_back(sal_uInt8(0));
59
2.74k
    }
60
3.04k
}
61
}
62
63
bool EOTConverter::convert(std::vector<sal_uInt8>& rEotOutput)
64
767
{
65
767
    font::TTFFont aFont(mrFontDataContainer);
66
67
767
    rEotOutput.clear();
68
767
    rEotOutput.resize(sizeof(EOTHeader));
69
70
767
    EOTHeader* pEot = reinterpret_cast<EOTHeader*>(rEotOutput.data());
71
767
    pEot->nFontDataSize = mrFontDataContainer.size();
72
767
    pEot->nVersion = 0x00020002;
73
767
    pEot->nFlags = 0;
74
767
    pEot->nCharset = 0;
75
767
    pEot->nMagicNumber = 0x504c;
76
767
    pEot->nReserved1 = 0;
77
767
    pEot->nReserved2 = 0;
78
767
    pEot->nReserved3 = 0;
79
767
    pEot->nReserved4 = 0;
80
81
767
    auto pHandler = aFont.getTableEntriesHandler();
82
767
    if (!pHandler)
83
7
        return false;
84
85
760
    const font::OS2Table* pOS2 = pHandler->getOS2Table();
86
760
    if (pOS2)
87
38
    {
88
418
        for (sal_uInt32 n = 0; n < 10; n++)
89
380
            pEot->nFontPANOSE[n] = pOS2->nPanose[n];
90
91
38
        pEot->nItalic = pOS2->nFsSelection & 0x01;
92
38
        pEot->nWeight = pOS2->nWeightClass;
93
        // FIXME: Should use OS2->fsType, but some TrueType fonts set it to an over-restrictive value.
94
        // Since ATS does not enforce this on Mac OS X, we do not enforce it either.
95
38
        pEot->nFsType = 0x0000;
96
38
        pEot->nUnicodeRange1 = pOS2->nUnicodeRange1;
97
38
        pEot->nUnicodeRange2 = pOS2->nUnicodeRange2;
98
38
        pEot->nUnicodeRange3 = pOS2->nUnicodeRange3;
99
38
        pEot->nUnicodeRange4 = pOS2->nUnicodeRange4;
100
38
        pEot->nCodePageRange1 = pOS2->nCodePageRange1;
101
38
        pEot->nCodePageRange2 = pOS2->nCodePageRange2;
102
38
    }
103
104
760
    const font::HeadTable* pHeadTable = pHandler->getHeadTable();
105
760
    if (pHeadTable)
106
49
    {
107
49
        pEot->nCheckSumAdjustment = pHeadTable->nCheckSumAdjustment;
108
49
    }
109
110
760
    auto pNameTableHandler = pHandler->getNameTableHandler();
111
112
760
    writeNameTableString(aFont, pNameTableHandler, font::NameID::FamilyName, rEotOutput);
113
760
    writeNameTableString(aFont, pNameTableHandler, font::NameID::SubfamilyName, rEotOutput);
114
760
    writeNameTableString(aFont, pNameTableHandler, font::NameID::Version, rEotOutput);
115
760
    writeNameTableString(aFont, pNameTableHandler, font::NameID::FullFontName, rEotOutput);
116
117
    // Padding5
118
760
    rEotOutput.push_back(0);
119
760
    rEotOutput.push_back(0);
120
121
    // Root String Size
122
760
    rEotOutput.push_back(0);
123
760
    rEotOutput.push_back(0);
124
125
    // Root String CheckSum (for size 0)
126
760
    rEotOutput.push_back(0x42);
127
760
    rEotOutput.push_back(0x53);
128
760
    rEotOutput.push_back(0x47);
129
760
    rEotOutput.push_back(0x50);
130
131
    // EUDC CodePage
132
760
    rEotOutput.push_back(0xE4);
133
760
    rEotOutput.push_back(0x04);
134
760
    rEotOutput.push_back(0x00);
135
760
    rEotOutput.push_back(0x00);
136
137
    // Padding6
138
760
    rEotOutput.push_back(0);
139
760
    rEotOutput.push_back(0);
140
141
    // Signature Size = should be 0x0000
142
760
    rEotOutput.push_back(0);
143
760
    rEotOutput.push_back(0);
144
145
    // EUDC Flags
146
760
    rEotOutput.push_back(0);
147
760
    rEotOutput.push_back(0);
148
760
    rEotOutput.push_back(0);
149
760
    rEotOutput.push_back(0);
150
151
    // EUDC Font Size = 0
152
760
    rEotOutput.push_back(0);
153
760
    rEotOutput.push_back(0);
154
760
    rEotOutput.push_back(0);
155
760
    rEotOutput.push_back(0);
156
157
    // rEOTOutput could've been reallocated - need to reinterpret that.
158
760
    pEot = reinterpret_cast<EOTHeader*>(rEotOutput.data());
159
760
    pEot->nEotSize = rEotOutput.size() + mrFontDataContainer.size();
160
161
760
    rEotOutput.insert(rEotOutput.end(), mrFontDataContainer.begin(), mrFontDataContainer.end());
162
163
760
    return true;
164
767
}
165
166
} // end font namespace
167
168
int TestEOT(const void* data, sal_uInt32 size)
169
767
{
170
767
    const sal_uInt8* bytes = static_cast<const sal_uInt8*>(data);
171
767
    std::vector<sal_uInt8> input(bytes, bytes + size);
172
173
767
    std::vector<sal_uInt8> aEOT;
174
767
    font::FontDataContainer aContainer(input);
175
767
    font::EOTConverter aConverter(aContainer);
176
767
    return aConverter.convert(aEOT) ? 1 : 0;
177
767
}
178
179
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */