~ubuntu-branches/ubuntu/lucid/gnustep-back/lucid

« back to all changes in this revision

Viewing changes to Source/cairo/CairoFontInfo.m

  • Committer: Bazaar Package Importer
  • Author(s): Hubert Chathi
  • Date: 2008-07-02 17:19:03 UTC
  • mfrom: (1.2.5 upstream) (4.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080702171903-n1potlcotage8xy0
Tags: 0.14.0-2
Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * CairoFontInfo.m
3
 
 *
4
 
 * Copyright (C) 2003 Free Software Foundation, Inc.
5
 
 * August 31, 2003
6
 
 * Written by Banlu Kemiyatorn <object at gmail dot com>
7
 
 * Base on original code of Alex Malmberg
8
 
 * This library is free software; you can redistribute it and/or
9
 
 * modify it under the terms of the GNU Library General Public
10
 
 * License as published by the Free Software Foundation; either
11
 
 * version 2 of the License, or (at your option) any later version.
12
 
 
13
 
 * This library is distributed in the hope that it will be useful,
14
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 
 * Library General Public License for more details.
17
 
 
18
 
 * You should have received a copy of the GNU Library General Public
19
 
 * License along with this library; if not, write to the Free
20
 
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21
 
 * Boston, MA 02111 USA.
22
 
 */
 
2
   CairoFontInfo.m
 
3
 
 
4
   Copyright (C) 2003 Free Software Foundation, Inc.
 
5
 
 
6
   August 31, 2003
 
7
   Written by Banlu Kemiyatorn <object at gmail dot com>
 
8
   Base on original code of Alex Malmberg
 
9
 
 
10
   This file is part of GNUstep.
 
11
 
 
12
   This library is free software; you can redistribute it and/or
 
13
   modify it under the terms of the GNU Lesser General Public
 
14
   License as published by the Free Software Foundation; either
 
15
   version 2 of the License, or (at your option) any later version.
 
16
 
 
17
   This library is distributed in the hope that it will be useful,
 
18
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
20
   Lesser General Public License for more details.
 
21
 
 
22
   You should have received a copy of the GNU Lesser General Public
 
23
   License along with this library; see the file COPYING.LIB.
 
24
   If not, see <http://www.gnu.org/licenses/> or write to the 
 
25
   Free Software Foundation, 51 Franklin Street, Fifth Floor, 
 
26
   Boston, MA 02110-1301, USA.
 
27
*/
23
28
 
24
29
#include "GNUstepBase/Unicode.h"
25
30
#include <AppKit/NSAffineTransform.h>
 
31
#include <AppKit/NSBezierPath.h>
26
32
#include "cairo/CairoFontInfo.h"
27
33
#include "cairo/CairoFontEnumerator.h"
28
34
 
36
42
  _cacheSize = size;
37
43
  if (_cachedSizes)
38
44
    {
39
 
      free(_cachedSizes);
40
 
    }
41
 
  if (_cachedGlyphs)
42
 
    {
43
 
      free(_cachedGlyphs);
44
 
    }
45
 
  _cachedSizes = malloc(sizeof(NSSize) * size);
46
 
  memset(_cachedSizes, 0, sizeof(NSSize) * size);
47
 
  _cachedGlyphs = malloc(sizeof(unsigned int) * size);
48
 
  memset(_cachedGlyphs, 0, sizeof(unsigned int) * size);
 
45
      objc_free(_cachedSizes);
 
46
    }
 
47
  if (_cachedGlyphs)
 
48
    {
 
49
      objc_free(_cachedGlyphs);
 
50
    }
 
51
  _cachedSizes = objc_malloc(sizeof(NSSize) * size);
 
52
  if (_cachedSizes)
 
53
    {
 
54
      memset(_cachedSizes, 0, sizeof(NSSize) * size);
 
55
    }
 
56
  _cachedGlyphs = objc_malloc(sizeof(unsigned int) * size);
 
57
  if (_cachedGlyphs)
 
58
    {
 
59
      memset(_cachedGlyphs, 0, sizeof(unsigned int) * size);
 
60
    }
49
61
}
50
62
 
51
63
- (BOOL) setupAttributes
56
68
  cairo_matrix_t ctm;
57
69
  cairo_font_options_t *options;
58
70
 
59
 
  /* do not forget to check for font specific
60
 
   * cache size from face info FIXME FIXME
61
 
   */
62
71
  ASSIGN(_faceInfo, [CairoFontEnumerator fontWithName: fontName]);
63
72
  if (!_faceInfo)
64
73
    {
65
74
      return NO;
66
75
    }
67
76
 
68
 
  _cachedSizes = NULL;
 
77
  // check for font specific cache size from face info
69
78
  [self setCacheSize: [_faceInfo cacheSize]];
70
79
 
71
80
  /* setting GSFontInfo:
83
92
   * xHeight, pix_width, pix_height
84
93
   */
85
94
  cairo_matrix_init(&font_matrix, matrix[0], matrix[1], matrix[2],
86
 
                    matrix[3], matrix[4], matrix[5]);
 
95
                    matrix[3], matrix[4], matrix[5]);
87
96
  cairo_matrix_init_identity(&ctm);
 
97
 
88
98
  // FIXME: Should get default font options from somewhere
89
99
  options = cairo_font_options_create();
90
100
  face = [_faceInfo fontFace];
92
102
    {
93
103
      return NO;
94
104
    }
 
105
 
95
106
  _scaled = cairo_scaled_font_create(face, &font_matrix, &ctm, options);
96
107
  cairo_font_options_destroy(options);
97
108
  if (!_scaled)
105
116
  xHeight = ascender * 0.6;
106
117
  lineHeight = font_extents.height;
107
118
  maximumAdvancement = NSMakeSize(font_extents.max_x_advance, 
108
 
                                  font_extents.max_y_advance);
 
119
                                  font_extents.max_y_advance);
109
120
  fontBBox = NSMakeRect(0, descender, 
110
 
                        maximumAdvancement.width, ascender - descender);
 
121
                        maximumAdvancement.width, ascender - descender);
111
122
 
112
123
  return YES;
113
124
}
114
125
 
115
126
- (id) initWithFontName: (NSString *)name 
116
 
                 matrix: (const float *)fmatrix 
117
 
             screenFont: (BOOL)p_screenFont
 
127
                 matrix: (const float *)fmatrix 
 
128
             screenFont: (BOOL)p_screenFont
118
129
{
119
 
  //NSLog(@"initWithFontName %@",name);
120
 
  [super init];
 
130
  self = [super init];
 
131
  if (!self)
 
132
    return nil;
121
133
 
122
134
  _screenFont = p_screenFont;
123
135
  fontName = [name copy];
128
140
      /* Round up; makes the text more legible. */
129
141
      matrix[0] = ceil(matrix[0]);
130
142
      if (matrix[3] < 0.0)
131
 
        matrix[3] = floor(matrix[3]);
 
143
        matrix[3] = floor(matrix[3]);
132
144
      else
133
 
        matrix[3] = ceil(matrix[3]);
 
145
        matrix[3] = ceil(matrix[3]);
134
146
    }
135
147
 
136
148
  if (![self setupAttributes])
149
161
    {
150
162
      cairo_scaled_font_destroy(_scaled);
151
163
    }
152
 
  free(_cachedSizes);
153
 
  free(_cachedGlyphs);
 
164
  if (_cachedSizes)
 
165
    objc_free(_cachedSizes);
 
166
  if (_cachedGlyphs)
 
167
    objc_free(_cachedGlyphs);
154
168
  [super dealloc];
155
169
}
156
170
 
161
175
 
162
176
- (BOOL) glyphIsEncoded: (NSGlyph)glyph
163
177
{
164
 
  /* subclass should override */
165
 
  return YES;
 
178
  /* FIXME: There is no proper way to determine with the toy font API,
 
179
     whether a glyph is supported or not. We will just ignore ligatures 
 
180
     and report all other glyph as existing.
 
181
  return !NSEqualSizes([self advancementForGlyph: glyph], NSZeroSize);
 
182
  */
 
183
  if ((glyph >= 0xFB00) && (glyph <= 0xFB05))
 
184
    return NO;
 
185
  else
 
186
    return YES;
166
187
}
167
188
 
168
189
static
169
190
BOOL _cairo_extents_for_NSGlyph(cairo_scaled_font_t *scaled_font, NSGlyph glyph,
170
 
                                cairo_text_extents_t *ctext)
 
191
                                cairo_text_extents_t *ctext)
171
192
{
172
193
  unichar ustr[2];
173
194
  char str[4];
180
201
 
181
202
  b = (unsigned char *)str;
182
203
  if (!GSFromUnicode(&b, &size, ustr, length, 
183
 
                     NSUTF8StringEncoding, NULL, GSUniTerminate))
 
204
                     NSUTF8StringEncoding, NULL, GSUniTerminate))
184
205
    {
185
206
      NSLog(@"Conversion failed for %@", 
186
 
            [NSString stringWithCharacters: ustr length: length]);
 
207
            [NSString stringWithCharacters: ustr length: length]);
187
208
      return NO;
188
209
    }
189
210
 
194
215
- (NSSize) advancementForGlyph: (NSGlyph)glyph
195
216
{
196
217
  cairo_text_extents_t ctext;
197
 
  int entry;
198
 
 
199
 
  entry = glyph % _cacheSize;
200
 
 
201
 
  if (_cachedGlyphs[entry] == glyph)
 
218
 
 
219
  if (_cachedSizes)
202
220
    {
203
 
      return _cachedSizes[entry];
 
221
      int entry = glyph % _cacheSize;
 
222
 
 
223
      if (_cachedGlyphs[entry] == glyph)
 
224
        {
 
225
          return _cachedSizes[entry];
 
226
        }
 
227
      
 
228
      if (_cairo_extents_for_NSGlyph(_scaled, glyph, &ctext))
 
229
        {
 
230
          _cachedGlyphs[entry] = glyph;
 
231
          _cachedSizes[entry] = NSMakeSize(ctext.x_advance, ctext.y_advance);
 
232
          
 
233
          return _cachedSizes[entry];
 
234
        }
204
235
    }
205
 
 
206
 
  if (_cairo_extents_for_NSGlyph(_scaled, glyph, &ctext))
 
236
  else
207
237
    {
208
 
      _cachedGlyphs[entry] = glyph;
209
 
      _cachedSizes[entry] = NSMakeSize(ctext.x_advance, ctext.y_advance);
210
 
 
211
 
      return _cachedSizes[entry];
 
238
      if (_cairo_extents_for_NSGlyph(_scaled, glyph, &ctext))
 
239
        {
 
240
          return NSMakeSize(ctext.x_advance, ctext.y_advance);
 
241
        }
212
242
    }
213
243
 
214
244
  return NSZeroSize;
221
251
  if (_cairo_extents_for_NSGlyph(_scaled, glyph, &ctext))
222
252
    {
223
253
      return NSMakeRect(ctext.x_bearing, ctext.y_bearing,
224
 
                        ctext.width, ctext.height);
 
254
                        ctext.width, ctext.height);
225
255
    }
226
256
 
227
257
  return NSZeroRect;
231
261
{
232
262
  cairo_text_extents_t ctext;
233
263
 
234
 
        cairo_scaled_font_text_extents(_scaled, [string UTF8String], &ctext);
 
264
  if (!string)
 
265
    {
 
266
      return 0.0;
 
267
    }
 
268
 
 
269
  cairo_scaled_font_text_extents(_scaled, [string UTF8String], &ctext);
235
270
  if (cairo_scaled_font_status(_scaled) == CAIRO_STATUS_SUCCESS)
236
271
    {
237
272
      return ctext.width;
249
284
  return g;
250
285
}
251
286
 
252
 
/* need cairo to export its cairo_path_t first */
253
287
- (void) appendBezierPathWithGlyphs: (NSGlyph *)glyphs 
254
 
                              count: (int)count 
255
 
                       toBezierPath: (NSBezierPath *)path
 
288
                              count: (int)length 
 
289
                       toBezierPath: (NSBezierPath *)path
256
290
{
257
 
  /* TODO LATER
258
 
     cairo_t *ct;
259
 
     int i;
260
 
     NSPoint start = [path currentPoint];
261
 
     cairo_glyph_t *cairo_glyphs;
262
 
 
263
 
     cairo_glyphs = malloc(sizeof(cairo_glyph_t) * count);
264
 
     ct = cairo_create();
265
 
 
266
 
 
267
 
     cairo_destroy(ct);
268
 
   */
 
291
  cairo_format_t format = CAIRO_FORMAT_ARGB32;
 
292
  cairo_surface_t *isurface;
 
293
  cairo_t *ct;
 
294
  int ix = 400;
 
295
  int iy = 400;
 
296
  unsigned char *cdata;
 
297
  int i;
 
298
  unichar ustr[length+1];
 
299
  char str[3*length+1];
 
300
  unsigned char *b;
 
301
  unsigned int size = 3*length+1;
 
302
  cairo_status_t status;
 
303
  cairo_matrix_t font_matrix;
 
304
 
 
305
  for (i = 0; i < length; i++)
 
306
    {
 
307
      ustr[i] = glyphs[i];
 
308
    }
 
309
  ustr[length] = 0;
 
310
 
 
311
  b = (unsigned char *)str;
 
312
  if (!GSFromUnicode(&b, &size, ustr, length, 
 
313
                     NSUTF8StringEncoding, NULL, GSUniTerminate))
 
314
    {
 
315
      NSLog(@"Conversion failed for %@", 
 
316
            [NSString stringWithCharacters: ustr length: length]);
 
317
      return;
 
318
    }
 
319
 
 
320
  cdata = objc_malloc(sizeof(char) * 4 * ix * iy);
 
321
  if (!cdata)
 
322
    {
 
323
      NSLog(@"Could not allocate drawing space for glyphs");
 
324
      return;
 
325
    }
 
326
 
 
327
  isurface = cairo_image_surface_create_for_data(cdata, format, ix, iy, 4*ix);
 
328
  status = cairo_surface_status(isurface);
 
329
  if (status != CAIRO_STATUS_SUCCESS)
 
330
    {
 
331
      NSLog(@"Error while creating surface: %s", 
 
332
            cairo_status_to_string(status));
 
333
      cairo_surface_destroy(isurface);
 
334
      objc_free(cdata);
 
335
      return;
 
336
    }
 
337
 
 
338
  ct = cairo_create(isurface);
 
339
  if (cairo_status(ct) != CAIRO_STATUS_SUCCESS)
 
340
    {
 
341
      NSLog(@"Error while creating context: %s", 
 
342
            cairo_status_to_string(cairo_status(ct)));
 
343
      cairo_destroy(ct);
 
344
      cairo_surface_destroy(isurface);
 
345
      objc_free(cdata);
 
346
      return;
 
347
    }
 
348
 
 
349
  // Use flip matrix
 
350
  cairo_matrix_init(&font_matrix, matrix[0], matrix[1], matrix[2],
 
351
                    -matrix[3], matrix[4], matrix[5]);
 
352
  cairo_set_font_matrix(ct, &font_matrix);
 
353
  if (cairo_status(ct) != CAIRO_STATUS_SUCCESS)
 
354
    {
 
355
      NSLog(@"Error while setting font matrix: %s", 
 
356
            cairo_status_to_string(cairo_status(ct)));
 
357
      cairo_destroy(ct);
 
358
      cairo_surface_destroy(isurface);
 
359
      objc_free(cdata);
 
360
      return;
 
361
    }
 
362
 
 
363
  cairo_set_font_face(ct, [_faceInfo fontFace]);
 
364
  if (cairo_status(ct) != CAIRO_STATUS_SUCCESS)
 
365
    {
 
366
      NSLog(@"Error while setting font face: %s", 
 
367
            cairo_status_to_string(cairo_status(ct)));
 
368
      cairo_destroy(ct);
 
369
      cairo_surface_destroy(isurface);
 
370
      objc_free(cdata);
 
371
      return;
 
372
    }
 
373
 
 
374
  if ([path elementCount] > 0)
 
375
    {
 
376
      NSPoint p;
 
377
 
 
378
      p = [path currentPoint];
 
379
      cairo_move_to(ct, floorf(p.x), floorf(p.y));
 
380
    }
 
381
 
 
382
  cairo_text_path(ct, str);
 
383
  if (cairo_status(ct) == CAIRO_STATUS_SUCCESS)
 
384
     {
 
385
      cairo_path_t *cpath;
 
386
      cairo_path_data_t *data;
 
387
      
 
388
      cpath = cairo_copy_path(ct);
 
389
      
 
390
      for (i = 0; i < cpath->num_data; i += cpath->data[i].header.length) 
 
391
        {
 
392
          data = &cpath->data[i];
 
393
          switch (data->header.type) 
 
394
            {
 
395
              case CAIRO_PATH_MOVE_TO:
 
396
                [path moveToPoint: NSMakePoint(data[1].point.x, data[1].point.y)];
 
397
                break;
 
398
              case CAIRO_PATH_LINE_TO:
 
399
                [path lineToPoint: NSMakePoint(data[1].point.x, data[1].point.y)];
 
400
                break;
 
401
              case CAIRO_PATH_CURVE_TO:
 
402
                [path curveToPoint: NSMakePoint(data[3].point.x, data[3].point.y) 
 
403
                      controlPoint1: NSMakePoint(data[1].point.x, data[1].point.y)
 
404
                      controlPoint2: NSMakePoint(data[2].point.x, data[2].point.y)];
 
405
                break;
 
406
              case CAIRO_PATH_CLOSE_PATH:
 
407
                [path closePath];
 
408
                break;
 
409
            }
 
410
        }
 
411
      cairo_path_destroy(cpath);
 
412
    }
 
413
  cairo_destroy(ct);
 
414
  cairo_surface_destroy(isurface);
 
415
  objc_free(cdata);
269
416
}
270
417
 
271
418
- (void) drawGlyphs: (const NSGlyph*)glyphs
272
 
             length: (int)length 
273
 
                 on: (cairo_t*)ct
 
419
             length: (int)length 
 
420
                 on: (cairo_t*)ct
274
421
{
275
422
  cairo_matrix_t font_matrix;
276
423
  unichar ustr[length+1];
287
434
 
288
435
  b = (unsigned char *)str;
289
436
  if (!GSFromUnicode(&b, &size, ustr, length, 
290
 
                     NSUTF8StringEncoding, NULL, GSUniTerminate))
 
437
                     NSUTF8StringEncoding, NULL, GSUniTerminate))
291
438
    {
292
439
      NSLog(@"Conversion failed for %@", 
293
 
            [NSString stringWithCharacters: ustr length: length]);
 
440
            [NSString stringWithCharacters: ustr length: length]);
294
441
      return;
295
442
    }
296
443
 
297
444
  cairo_matrix_init(&font_matrix, matrix[0], matrix[1], matrix[2],
298
 
                    matrix[3], matrix[4], matrix[5]);
 
445
                    matrix[3], matrix[4], matrix[5]);
299
446
  cairo_set_font_matrix(ct, &font_matrix);
300
447
  if (cairo_status(ct) != CAIRO_STATUS_SUCCESS)
301
448
    {
302
 
        NSLog(@"Error while setting font matrix: %s", 
303
 
              cairo_status_to_string(cairo_status(ct)));
304
 
        return;
 
449
      NSLog(@"Error while setting font matrix: %s", 
 
450
            cairo_status_to_string(cairo_status(ct)));
 
451
      return;
305
452
    }
 
453
 
306
454
  cairo_set_font_face(ct, [_faceInfo fontFace]);
307
455
  if (cairo_status(ct) != CAIRO_STATUS_SUCCESS)
308
456
    {
309
 
        NSLog(@"Error while setting font face: %s", 
310
 
              cairo_status_to_string(cairo_status(ct)));
311
 
        return;
 
457
      NSLog(@"Error while setting font face: %s", 
 
458
            cairo_status_to_string(cairo_status(ct)));
 
459
      return;
312
460
    }
313
461
 
314
462
  cairo_show_text(ct, str);
315
463
  if (cairo_status(ct) != CAIRO_STATUS_SUCCESS)
316
464
    {
317
 
        NSLog(@"Error drawing string: '%s' for string %s", 
318
 
              cairo_status_to_string(cairo_status(ct)), str);
 
465
      NSLog(@"Error drawing string: '%s' for string %s", 
 
466
            cairo_status_to_string(cairo_status(ct)), str);
319
467
    }
320
468
}
321
 
 
 
469
 
322
470
@end