1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2010 Robert Bieber
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 #include "rbfontcache.h"
24 #include "rbtextcache.h"
36 quint16
RBFont::maxFontSizeFor16BitOffsets
= 0xFFDB;
38 RBFont::RBFont(QString file
)
39 : valid(false), imageData(0), offsetData(0), widthData(0)
42 /* Attempting to locate the correct file name */
43 if(!QFile::exists(file
))
45 /* Checking in the fonts repository */
47 settings
.beginGroup("RBFont");
49 file
= file
.split("/").last();
50 file
= settings
.value("fontDir", "").toString() + "/" + file
;
54 if(!QFile::exists(file
))
55 file
= ":/fonts/08-Schumacher-Clean.fnt";
57 header
.insert("filename", file
);
59 /* Checking for a cache entry */
60 RBFontCache::CacheInfo
* cache
= RBFontCache::lookup(file
);
63 imageData
= cache
->imageData
;
64 offsetData
= cache
->offsetData
;
65 widthData
= cache
->widthData
;
66 header
= cache
->header
;
71 /* Opening the file */
73 fin
.open(QFile::ReadOnly
);
75 /* Loading the header info */
80 QDataStream
data(&fin
);
81 data
.setByteOrder(QDataStream::LittleEndian
);
83 /* Grabbing the magic number and version */
85 header
.insert("version", dword
);
89 header
.insert("maxwidth", word
);
93 header
.insert("height", word
);
97 header
.insert("ascent", word
);
102 /* First character code */
104 header
.insert("firstchar", dword
);
106 /* Default character code */
108 header
.insert("defaultchar", dword
);
110 /* Number of characters */
112 header
.insert("size", dword
);
114 /* Bytes of imagebits in file */
116 header
.insert("nbits", dword
);
118 /* Longs (dword) of offset data in file */
120 header
.insert("noffset", dword
);
122 /* Bytes of width data in file */
124 header
.insert("nwidth", dword
);
126 /* Loading the image data */
127 imageData
= new quint8
[header
.value("nbits").toInt()];
128 data
.readRawData(reinterpret_cast<char*>(imageData
),
129 header
.value("nbits").toInt());
131 /* Aligning on 16-bit boundary */
132 if(header
.value("nbits").toInt() % 2 == 1)
135 /* Loading the offset table if necessary */
136 if(header
.value("noffset").toInt() > 0)
139 if(header
.value("nbits").toInt() > maxFontSizeFor16BitOffsets
)
140 bytesToRead
= 4 * header
.value("noffset").toInt();
142 bytesToRead
= 2 * header
.value("noffset").toInt();
143 offsetData
= new quint16
[bytesToRead
];
144 data
.readRawData(reinterpret_cast<char*>(offsetData
), bytesToRead
);
147 /* Loading the width table if necessary */
148 if(header
.value("nwidth").toInt() > 0)
150 widthData
= new quint8
[header
.value("nwidth").toInt()];
151 data
.readRawData(reinterpret_cast<char*>(widthData
),
152 header
.value("nwidth").toInt());
157 /* Caching the font data */
158 cache
= new RBFontCache::CacheInfo
;
159 cache
->imageData
= imageData
;
160 cache
->offsetData
= offsetData
;
161 cache
->widthData
= widthData
;
162 cache
->header
= header
;
163 RBFontCache::insert(file
, cache
);
171 RBText
* RBFont::renderText(QString text
, QColor color
, int viewWidth
,
172 QGraphicsItem
*parent
)
175 /* Checking for a cache hit first */
176 QImage
* image
= RBTextCache::lookup(header
.value("filename").toString()
179 return new RBText(image
, viewWidth
, parent
);
181 int firstChar
= header
.value("firstchar").toInt();
182 int height
= header
.value("height").toInt();
183 int maxWidth
= header
.value("maxwidth").toInt();
185 bool extendedSet
= header
.value("nbits").
186 toUInt() > maxFontSizeFor16BitOffsets
;
188 /* First we determine the width of the combined text */
190 for(int i
= 0; i
< text
.length(); i
++)
193 widths
.append(widthData
[text
[i
].unicode() - firstChar
]);
195 widths
.append(maxWidth
);
199 for(int i
= 0; i
< widths
.count(); i
++)
200 totalWidth
+= widths
[i
];
202 image
= new QImage(totalWidth
, height
, QImage::Format_Indexed8
);
204 image
->setColor(0, qRgba(0,0,0,0));
205 image
->setColor(1, color
.rgb());
207 /* Drawing the text */
209 for(int i
= 0; i
< text
.length(); i
++)
215 offset
= reinterpret_cast<quint32
*>(offsetData
)[text
[i
].unicode() - firstChar
];
217 offset
= offsetData
[text
[i
].unicode() - firstChar
];
221 offset
= (text
[i
].unicode() - firstChar
) * maxWidth
;
224 int bytesHigh
= height
/ 8;
228 int bytes
= bytesHigh
* widths
[i
];
230 for(int byte
= 0; byte
< bytes
; byte
++)
232 int x
= startX
+ byte
% widths
[i
];
233 int y
= byte
/ widths
[i
] * 8;
234 quint8 data
= imageData
[offset
];
236 for(int bit
= 0; bit
< 8; bit
++)
239 image
->setPixel(x
, y
, 1);
241 image
->setPixel(x
, y
, 0);
255 RBTextCache::insert(header
.value("filename").toString() + text
, image
);
256 return new RBText(image
, viewWidth
, parent
);