~ubuntu-branches/ubuntu/trusty/fluxbox/trusty-proposed

« back to all changes in this revision

Viewing changes to src/FbTk/XFontImp.cc

  • Committer: Bazaar Package Importer
  • Author(s): Dmitry E. Oboukhov
  • Date: 2008-07-01 10:38:14 UTC
  • mfrom: (2.1.12 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080701103814-khx2b6il152x9p93
Tags: 1.0.0+deb1-8
* x-dev has been removed from build-depends (out-of-date package).
* Standards-Version bumped to 3.8.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// XFontImp.cc for FbTk fluxbox toolkit
2
 
// Copyright (c) 2002 - 2005 Henrik Kinnunen (fluxgen at fluxbox dot org)
3
 
// 
4
 
// Permission is hereby granted, free of charge, to any person obtaining a
5
 
// copy of this software and associated documentation files (the "Software"),
6
 
// to deal in the Software without restriction, including without limitation
7
 
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 
// and/or sell copies of the Software, and to permit persons to whom the
9
 
// Software is furnished to do so, subject to the following conditions:
10
 
//
11
 
// The above copyright notice and this permission notice shall be included in
12
 
// all copies or substantial portions of the Software.
13
 
//
14
 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
 
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17
 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
 
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20
 
// DEALINGS IN THE SOFTWARE.
21
 
 
22
 
// $Id: XFontImp.cc 3864 2005-01-24 18:02:34Z mathias $
23
 
 
24
 
#include "XFontImp.hh"
25
 
#include "App.hh"
26
 
#include "GContext.hh"
27
 
#include "FbPixmap.hh"
28
 
#include "I18n.hh"
29
 
 
30
 
#include <X11/Xutil.h>
31
 
 
32
 
#include <iostream>
33
 
#include <new>
34
 
#ifdef HAVE_CSTDIO
35
 
  #include <cstdio>
36
 
#else
37
 
  #include <stdio.h>
38
 
#endif
39
 
using namespace std;
40
 
 
41
 
namespace FbTk {
42
 
 
43
 
XFontImp::XFontImp(const char *fontname):m_rotfont(0), m_fontstruct(0),
44
 
                                         m_angle(0), m_rotate(true) {
45
 
    if (fontname != 0)
46
 
        load(fontname); 
47
 
}
48
 
 
49
 
XFontImp::~XFontImp() {
50
 
    if (m_fontstruct != 0)
51
 
        XFreeFont(App::instance()->display(), m_fontstruct);
52
 
    if (m_rotfont != 0)
53
 
        freeRotFont();
54
 
}
55
 
 
56
 
int XFontImp::ascent() const {
57
 
    if (m_fontstruct == 0)
58
 
        return 0;
59
 
    if (m_rotfont != 0)
60
 
        return m_rotfont->max_ascent;
61
 
                
62
 
    return m_fontstruct->ascent;
63
 
}
64
 
 
65
 
bool XFontImp::load(const std::string &fontname) {
66
 
    XFontStruct *font = XLoadQueryFont(App::instance()->display(), fontname.c_str());
67
 
    if (font == 0)
68
 
        return false;
69
 
    if (m_fontstruct != 0) // free old font struct, if any
70
 
        XFreeFont(App::instance()->display(), m_fontstruct);
71
 
 
72
 
    m_fontstruct = font; //set new font
73
 
 
74
 
    if (m_rotfont != 0) {
75
 
        freeRotFont(); // free old rotated font
76
 
        rotate(m_angle); // allocate new rotated font and rotate it to old angle
77
 
    }
78
 
 
79
 
    return true;
80
 
}
81
 
 
82
 
void XFontImp::drawText(const FbDrawable &w, int screen, GC gc, const char *text, size_t len, int x, int y) const {
83
 
    if (m_fontstruct == 0)
84
 
        return;
85
 
    // use roated font functions?
86
 
    if (m_rotfont != 0 && m_rotate) {
87
 
        drawRotText(w.drawable(), screen, gc, text, len, x, y);
88
 
        return;
89
 
    }
90
 
 
91
 
    XSetFont(w.display(), gc, m_fontstruct->fid);
92
 
    XDrawString(w.display(), w.drawable(), gc, x, y, text, len);
93
 
}
94
 
 
95
 
unsigned int XFontImp::textWidth(const char * const text, unsigned int size) const {
96
 
    if (text == 0 || m_fontstruct == 0)
97
 
        return 0;
98
 
 
99
 
    // check rotated font?
100
 
    if (m_rotfont != 0)
101
 
        return rotTextWidth(text, size);
102
 
 
103
 
    return XTextWidth(m_fontstruct, text, size);
104
 
}
105
 
 
106
 
unsigned int XFontImp::height() const {
107
 
    if (m_fontstruct == 0)
108
 
        return 0;
109
 
 
110
 
    return m_fontstruct->ascent + m_fontstruct->descent;
111
 
}
112
 
 
113
 
void XFontImp::rotate(float angle) {
114
 
    //we must have a font loaded before we rotate
115
 
    if (m_fontstruct == 0 || m_fontstruct->per_char == 0)
116
 
        return;
117
 
 
118
 
    if (m_rotfont != 0)
119
 
        freeRotFont();
120
 
 
121
 
    // no need for rotating, use regular font
122
 
    if (angle == 0) {
123
 
        m_angle = 0;
124
 
        return;
125
 
    }
126
 
 
127
 
    _FB_USES_NLS;
128
 
 
129
 
    //get positive angle
130
 
    while (angle < 0)
131
 
        angle += 360;
132
 
 
133
 
    m_angle = angle;
134
 
 
135
 
    // X system default vars
136
 
    Display *dpy = App::instance()->display();
137
 
    Window rootwin = DefaultRootWindow(dpy);
138
 
    int screen = DefaultScreen(dpy);
139
 
 
140
 
    char text[3];
141
 
    int ichar, i, j, index, boxlen = 60;
142
 
    int vert_w, vert_h, vert_len, bit_w, bit_h, bit_len;
143
 
    int min_char, max_char;
144
 
    unsigned char *vertdata, *bitdata;
145
 
    int ascent, descent, lbearing, rbearing;
146
 
 
147
 
    // get nearest vertical or horizontal direction 
148
 
    int dir = (int)((angle+45.0)/90.0)%4;
149
 
 
150
 
    if (dir == 0) // no rotation
151
 
        return;
152
 
 
153
 
    // create the depth 1 canvas bitmap
154
 
    FbTk::FbPixmap canvas(rootwin, boxlen, boxlen, 1);
155
 
 
156
 
    // create graphic context for our canvas
157
 
    FbTk::GContext font_gc(canvas);
158
 
    font_gc.setBackground(None);
159
 
    font_gc.setFont(m_fontstruct->fid);
160
 
 
161
 
    // allocate space for rotated font
162
 
    m_rotfont = new(nothrow) XRotFontStruct;
163
 
 
164
 
    if (m_rotfont == 0) {
165
 
        cerr<<"RotFont: "<<_FBTKTEXT(Error, OutOfMemory, "Out of memory", "Something couldn't allocate memory")<<endl;
166
 
        return;
167
 
    }
168
 
   
169
 
    // determine which characters are defined in font
170
 
    min_char = m_fontstruct->min_char_or_byte2; 
171
 
    max_char = m_fontstruct->max_char_or_byte2;
172
 
 
173
 
    // we only want printable chars
174
 
    if (min_char<32)
175
 
        min_char = 32;
176
 
    if (max_char>126)
177
 
        max_char = 126;
178
 
     
179
 
    /* some overall font data ... */
180
 
    m_rotfont->dir = dir;
181
 
    m_rotfont->min_char = min_char;
182
 
    m_rotfont->max_char = max_char;
183
 
    m_rotfont->max_ascent = m_fontstruct->max_bounds.ascent;
184
 
    m_rotfont->max_descent = m_fontstruct->max_bounds.descent;   
185
 
    m_rotfont->height = m_rotfont->max_ascent + m_rotfont->max_descent;
186
 
 
187
 
    // font needs rotation
188
 
    // loop through each character
189
 
    for (ichar = min_char; ichar <= max_char; ichar++) {
190
 
        index = ichar - m_fontstruct->min_char_or_byte2;
191
 
 
192
 
        // per char dimensions ...
193
 
        ascent = m_rotfont->per_char[ichar-32].ascent = m_fontstruct->per_char[index].ascent;
194
 
        descent =  m_rotfont->per_char[ichar-32].descent = m_fontstruct->per_char[index].descent;
195
 
        lbearing = m_rotfont->per_char[ichar-32].lbearing = m_fontstruct->per_char[index].lbearing;
196
 
        rbearing = m_rotfont->per_char[ichar-32].rbearing = m_fontstruct->per_char[index].rbearing;
197
 
        m_rotfont->per_char[ichar-32].width = m_fontstruct->per_char[index].width;
198
 
 
199
 
        // some space chars have zero body, but a bitmap can't have
200
 
        if (!ascent && !descent)   
201
 
            ascent = m_rotfont->per_char[ichar-32].ascent =   1;
202
 
        if (!lbearing && !rbearing) 
203
 
            rbearing = m_rotfont->per_char[ichar-32].rbearing = 1;
204
 
 
205
 
        // glyph width and height when vertical
206
 
        vert_w = rbearing - lbearing;
207
 
        vert_h = ascent + descent;
208
 
 
209
 
        // width in bytes
210
 
        vert_len = (vert_w-1)/8+1;   
211
 
 
212
 
        font_gc.setForeground(None);        
213
 
        canvas.fillRectangle(font_gc.gc(),
214
 
                             0, 0,
215
 
                             boxlen, boxlen);
216
 
        // draw the character centre top right on canvas
217
 
        sprintf(text, "%c", ichar);
218
 
        font_gc.setForeground(1);
219
 
        XDrawImageString(dpy, canvas.drawable(), font_gc.gc(),
220
 
                         boxlen/2 - lbearing,
221
 
                         boxlen/2 - descent, text, 1);
222
 
 
223
 
        // reserve memory for first XImage
224
 
        vertdata = new unsigned char[vert_len * vert_h];
225
 
 
226
 
        XImage *I1 = XCreateImage(dpy, DefaultVisual(dpy, screen), 
227
 
                                  1, XYBitmap,
228
 
                                  0, (char *)vertdata, 
229
 
                                  vert_w, vert_h, 8, 0);
230
 
 
231
 
        if (I1 == None) {                               
232
 
            cerr<<"RotFont: "<<_FBTKTEXT(Error, CreateXImage, "Cant create XImage", "XCreateImage failed for some reason")<<"."<<endl;
233
 
            delete m_rotfont;
234
 
            m_rotfont = 0;                      
235
 
            return;
236
 
        }
237
 
 
238
 
        I1->byte_order = I1->bitmap_bit_order = MSBFirst;
239
 
 
240
 
        // extract character from canvas
241
 
        XGetSubImage(dpy, canvas.drawable(), 
242
 
                     boxlen/2, boxlen/2 - vert_h,
243
 
                     vert_w, vert_h, 1, XYPixmap, I1, 0, 0);
244
 
 
245
 
        I1->format = XYBitmap; 
246
 
 
247
 
        // width, height of rotated character
248
 
        if (dir == 2) { 
249
 
            bit_w = vert_w;
250
 
            bit_h = vert_h; 
251
 
        } else {
252
 
            bit_w = vert_h;
253
 
            bit_h = vert_w; 
254
 
        }
255
 
 
256
 
        // width in bytes
257
 
        bit_len = (bit_w-1)/8 + 1;
258
 
 
259
 
        m_rotfont->per_char[ichar-32].glyph.bit_w = bit_w;
260
 
        m_rotfont->per_char[ichar-32].glyph.bit_h = bit_h;
261
 
 
262
 
        // reserve memory for the rotated image
263
 
        bitdata = (unsigned char *)calloc((unsigned)(bit_h * bit_len), 1);
264
 
 
265
 
        // create the image
266
 
        XImage *I2 = XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap, 0,
267
 
                          (char *)bitdata, bit_w, bit_h, 8, 0); 
268
 
 
269
 
        if (I2 == None) {
270
 
            cerr<<"XFontImp: "<<_FBTKTEXT(Error, CreateXImage, "Cant create XImage", "XCreateImage failed for some reason")<<"."<<endl;
271
 
            delete m_rotfont;
272
 
            m_rotfont = 0;
273
 
            return;
274
 
        }
275
 
 
276
 
        I2->byte_order = I2->bitmap_bit_order = MSBFirst;
277
 
 
278
 
        // map vertical data to rotated character
279
 
        for (j = 0; j < bit_h; j++) {
280
 
            for (i = 0; i < bit_w; i++) {
281
 
                char val = 0;
282
 
                if (dir == 1) {
283
 
                    val = vertdata[i*vert_len + (vert_w-j-1)/8] &
284
 
                        (128>>((vert_w-j-1)%8));
285
 
                } else if (dir == 2) {
286
 
                    val = vertdata[(vert_h-j-1)*vert_len +
287
 
                                   (vert_w-i-1)/8] & (128>>((vert_w-i-1)%8));
288
 
                } else {
289
 
                    val = vertdata[(vert_h-i-1)*vert_len + j/8] & 
290
 
                        (128>>(j%8));
291
 
                } 
292
 
                if (val) {
293
 
                    bitdata[j*bit_len + i/8] = bitdata[j*bit_len + i/8] |
294
 
                        (128>>(i%8));
295
 
                }
296
 
            }
297
 
        }
298
 
 
299
 
        // create this character's bitmap 
300
 
        m_rotfont->per_char[ichar-32].glyph.bm = 
301
 
            XCreatePixmap(dpy, rootwin, bit_w, bit_h, 1);
302
 
 
303
 
        // put the image into the bitmap 
304
 
        XPutImage(dpy, m_rotfont->per_char[ichar-32].glyph.bm, 
305
 
                  font_gc.gc(), I2, 0, 0, 0, 0, bit_w, bit_h);
306
 
 
307
 
        // free the image and data
308
 
        XDestroyImage(I1);
309
 
        XDestroyImage(I2);
310
 
    }
311
 
 
312
 
}
313
 
 
314
 
void XFontImp::freeRotFont() {
315
 
    if (m_rotfont == 0)
316
 
        return;
317
 
    // loop through each character and free its pixmap
318
 
    for (int ichar = m_rotfont->min_char - 32; 
319
 
         ichar <= m_rotfont->max_char - 32; ++ichar) {
320
 
        XFreePixmap(App::instance()->display(), m_rotfont->per_char[ichar].glyph.bm);
321
 
    }
322
 
 
323
 
    delete m_rotfont;
324
 
    m_rotfont = 0;
325
 
}
326
 
 
327
 
void XFontImp::drawRotText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const {            
328
 
 
329
 
    Display *dpy = App::instance()->display();
330
 
    static GC my_gc = 0;
331
 
    int xp, yp, dir, ichar;
332
 
 
333
 
    if (text == NULL || len<1)
334
 
        return;
335
 
 
336
 
    dir = m_rotfont->dir;
337
 
    if (my_gc == 0)
338
 
        my_gc = XCreateGC(dpy, w, 0, 0);
339
 
 
340
 
    XCopyGC(dpy, gc, GCForeground|GCBackground, my_gc);
341
 
 
342
 
    // vertical or upside down
343
 
 
344
 
    XSetFillStyle(dpy, my_gc, FillStippled);
345
 
 
346
 
    // loop through each character in texting
347
 
    for (size_t i = 0; i<len; i++) {
348
 
        ichar = text[i]-32;
349
 
 
350
 
        // make sure it's a printing character
351
 
        if (ichar >= 0 && ichar<95) {
352
 
            // suitable offset
353
 
            if (dir == 1) {
354
 
                xp = x-m_rotfont->per_char[ichar].ascent;
355
 
                yp = y-m_rotfont->per_char[ichar].rbearing; 
356
 
            } else if (dir == 2) {
357
 
                xp = x-m_rotfont->per_char[ichar].rbearing;
358
 
                yp = y-m_rotfont->per_char[ichar].descent+1; 
359
 
            } else {
360
 
                xp = x-m_rotfont->per_char[ichar].descent+1;  
361
 
                yp = y+m_rotfont->per_char[ichar].lbearing; 
362
 
            }
363
 
                   
364
 
            // draw the glyph
365
 
            XSetStipple(dpy, my_gc, m_rotfont->per_char[ichar].glyph.bm);
366
 
    
367
 
            XSetTSOrigin(dpy, my_gc, xp, yp);
368
 
      
369
 
            XFillRectangle(dpy, w, my_gc, xp, yp,
370
 
                           m_rotfont->per_char[ichar].glyph.bit_w,
371
 
                           m_rotfont->per_char[ichar].glyph.bit_h);
372
 
    
373
 
            // advance position
374
 
            if (dir == 1)
375
 
                y -= m_rotfont->per_char[ichar].width;
376
 
            else if (dir == 2)
377
 
                x -= m_rotfont->per_char[ichar].width;
378
 
            else 
379
 
                y += m_rotfont->per_char[ichar].width;
380
 
        }
381
 
    }
382
 
}
383
 
 
384
 
 
385
 
unsigned int XFontImp::rotTextWidth(const char * const text, unsigned int size) const {
386
 
 
387
 
    if (text == 0)
388
 
        return 0;
389
 
 
390
 
    unsigned int width = 0;     
391
 
    for (size_t i = 0; i<size; i++) {
392
 
        int ichar = text[i] - 32;  
393
 
        // make sure it's a printing character
394
 
        if (ichar >= 0 && ichar < 95) 
395
 
            width += m_rotfont->per_char[ichar].width;
396
 
    }
397
 
 
398
 
    return width;
399
 
}
400
 
 
401
 
};