1

right now, i'm trying to port over Steve Hanov's ttf parser in to c++ but ran in to a issue trying to convert char* to uintN_t.

when putting ComicSans.ttf, and arial.ttf, scarlar type should out put as 65536, but it turns out as 256

even changing the sizeof(x) in fi.read((char*)&x, sizeof(x)); under getUInt32 to some random number like fi.read((char*)&x, 3621); it still turns out as 256

class BinaryReader{
    private:
    ifstream fi;
    streampos fileSize;

    public:
    int position = 0;

    void open(string fname){
        fi.open(fname, ios::binary);

        fi.seekg(0, ios::end);
        fileSize = fi.tellg();
        fi.seekg(0, ios::beg);
    }

    void close(){
        fi.close();
    }

    int getUInt8(){
        fi.seekg(position, ios::beg);
        uint8_t x;
        fi.read((char*)&x, sizeof(x));
        position+=sizeof(x);
        return (int)x;
    }

    int getUInt16(){
        fi.seekg(position, ios::beg);
        uint16_t x;
        fi.read((char*)&x, sizeof(x));
        position+=sizeof(x);
        return (int)x;
    }

    int getUInt32(){
        fi.seekg(position, ios::beg);
        uint32_t x = 0;
        fi.read((char*)&x, sizeof(x));
        position+=sizeof(x);
        return x;
    }
};


int main(int argc, char* argv[]) {

    BinaryReader fontie;
    fontie.open("./fonts/ComicSans.ttf");
    cout << "scarlar type: " << fontie.getUInt32() << endl;
    cout << "numTables: " << fontie.getUInt16() << endl;
    cout << "searchRange: " << fontie.getUInt16() << endl;
    cout << "entrySelector: " << fontie.getUInt16() << endl;
    cout << "rangeShift: " << fontie.getUInt16() << endl;
    cout << "pose: " << fontie.position << endl;
    fontie.close();
}
  • 2
    Have you looked at a hex dump your input files to see what's really there? You say it should be 65536 but until you look at the data you don't really know that your code is bugged. – john Jun 09 '22 at 09:35
  • 2
    Looks to be an [endianess](https://en.wikipedia.org/wiki/Endianness) issue. True type is big endian, but you are reading little endian. You need to swap the bytes of any integer that you read. – john Jun 09 '22 at 09:45
  • that worked. using , I just wrapped the returns in htobe32 or htobe16, then it started out putting the right numbers. Thank you! :D – Luna Le Tuna Jun 09 '22 at 10:01
  • 1
    You are converting from big endian to host, so you should be using `be32toh` and `be16toh` instead. Same outcome, but at least it matches the intent. – Botje Jun 09 '22 at 10:31

0 Answers0