359 DEBUG(freetype, 4, "Set glyph for unicode character 0x%04X, size %u", key, size); |
361 DEBUG(freetype, 4, "Set glyph for unicode character 0x%04X, size %u", key, size); |
360 _glyph_ptr[size][GB(key, 8, 8)][GB(key, 0, 8)].sprite = glyph->sprite; |
362 _glyph_ptr[size][GB(key, 8, 8)][GB(key, 0, 8)].sprite = glyph->sprite; |
361 _glyph_ptr[size][GB(key, 8, 8)][GB(key, 0, 8)].width = glyph->width; |
363 _glyph_ptr[size][GB(key, 8, 8)][GB(key, 0, 8)].width = glyph->width; |
362 } |
364 } |
363 |
365 |
|
366 void *AllocateFont(size_t size) |
|
367 { |
|
368 return malloc(size); |
|
369 } |
|
370 |
|
371 |
|
372 /* Check if a glyph should be rendered with antialiasing */ |
|
373 static bool GetFontAAState(FontSize size) |
|
374 { |
|
375 /* AA is only supported for 32 bpp */ |
|
376 if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() != 32) return false; |
|
377 |
|
378 switch (size) { |
|
379 default: NOT_REACHED(); |
|
380 case FS_NORMAL: return _freetype.medium_aa; |
|
381 case FS_SMALL: return _freetype.small_aa; |
|
382 case FS_LARGE: return _freetype.large_aa; |
|
383 } |
|
384 } |
|
385 |
364 |
386 |
365 const Sprite *GetGlyph(FontSize size, WChar key) |
387 const Sprite *GetGlyph(FontSize size, WChar key) |
366 { |
388 { |
367 FT_Face face = GetFontFace(size); |
389 FT_Face face = GetFontFace(size); |
368 FT_GlyphSlot slot; |
390 FT_GlyphSlot slot; |
369 GlyphEntry new_glyph; |
391 GlyphEntry new_glyph; |
370 GlyphEntry *glyph; |
392 GlyphEntry *glyph; |
371 Sprite *sprite; |
393 SpriteLoader::Sprite sprite; |
372 int width; |
394 int width; |
373 int height; |
395 int height; |
374 int x; |
396 int x; |
375 int y; |
397 int y; |
376 int y_adj; |
398 int y_adj; |
388 glyph = GetGlyphPtr(size, key); |
410 glyph = GetGlyphPtr(size, key); |
389 if (glyph != NULL && glyph->sprite != NULL) return glyph->sprite; |
411 if (glyph != NULL && glyph->sprite != NULL) return glyph->sprite; |
390 |
412 |
391 slot = face->glyph; |
413 slot = face->glyph; |
392 |
414 |
|
415 bool aa = GetFontAAState(size); |
|
416 |
393 FT_Load_Char(face, key, FT_LOAD_DEFAULT); |
417 FT_Load_Char(face, key, FT_LOAD_DEFAULT); |
394 FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO); |
418 FT_Render_Glyph(face->glyph, aa ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); |
395 |
419 |
396 /* Add 1 pixel for the shadow on the medium font. Our sprite must be at least 1x1 pixel */ |
420 /* Add 1 pixel for the shadow on the medium font. Our sprite must be at least 1x1 pixel */ |
397 width = max(1, slot->bitmap.width + (size == FS_NORMAL)); |
421 width = max(1, slot->bitmap.width + (size == FS_NORMAL)); |
398 height = max(1, slot->bitmap.rows + (size == FS_NORMAL)); |
422 height = max(1, slot->bitmap.rows + (size == FS_NORMAL)); |
399 |
423 |
400 /* FreeType has rendered the glyph, now we allocate a sprite and copy the image into it */ |
424 /* FreeType has rendered the glyph, now we allocate a sprite and copy the image into it */ |
401 sprite = (Sprite*)calloc(width * height + 8, 1); |
425 sprite.data = CallocT<SpriteLoader::CommonPixel>(width * height); |
402 sprite->info = 1; |
426 sprite.width = width; |
403 sprite->width = width; |
427 sprite.height = height; |
404 sprite->height = height; |
428 sprite.x_offs = slot->bitmap_left; |
405 sprite->x_offs = slot->bitmap_left; |
|
406 // XXX 2 should be determined somehow... it's right for the normal face |
429 // XXX 2 should be determined somehow... it's right for the normal face |
407 y_adj = (size == FS_NORMAL) ? 2 : 0; |
430 y_adj = (size == FS_NORMAL) ? 2 : 0; |
408 sprite->y_offs = GetCharacterHeight(size) - slot->bitmap_top - y_adj; |
431 sprite.y_offs = GetCharacterHeight(size) - slot->bitmap_top - y_adj; |
409 |
432 |
410 /* Draw shadow for medium size */ |
433 /* Draw shadow for medium size */ |
411 if (size == FS_NORMAL) { |
434 if (size == FS_NORMAL) { |
412 for (y = 0; y < slot->bitmap.rows; y++) { |
435 for (y = 0; y < slot->bitmap.rows; y++) { |
413 for (x = 0; x < slot->bitmap.width; x++) { |
436 for (x = 0; x < slot->bitmap.width; x++) { |
414 if (HASBIT(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) { |
437 if (aa ? (slot->bitmap.buffer[x + y * slot->bitmap.pitch] > 0) : HASBIT(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) { |
415 sprite->data[1 + x + (1 + y) * sprite->width] = SHADOW_COLOUR; |
438 sprite.data[1 + x + (1 + y) * sprite.width].m = SHADOW_COLOUR; |
|
439 sprite.data[1 + x + (1 + y) * sprite.width].a = aa ? slot->bitmap.buffer[x + y * slot->bitmap.pitch] : 0xFF; |
416 } |
440 } |
417 } |
441 } |
418 } |
442 } |
419 } |
443 } |
420 |
444 |
421 for (y = 0; y < slot->bitmap.rows; y++) { |
445 for (y = 0; y < slot->bitmap.rows; y++) { |
422 for (x = 0; x < slot->bitmap.width; x++) { |
446 for (x = 0; x < slot->bitmap.width; x++) { |
423 if (HASBIT(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) { |
447 if (aa ? (slot->bitmap.buffer[x + y * slot->bitmap.pitch] > 0) : HASBIT(slot->bitmap.buffer[(x / 8) + y * slot->bitmap.pitch], 7 - (x % 8))) { |
424 sprite->data[x + y * sprite->width] = FACE_COLOUR; |
448 sprite.data[x + y * sprite.width].m = FACE_COLOUR; |
|
449 sprite.data[x + y * sprite.width].a = aa ? slot->bitmap.buffer[x + y * slot->bitmap.pitch] : 0xFF; |
425 } |
450 } |
426 } |
451 } |
427 } |
452 } |
428 |
453 |
429 new_glyph.sprite = sprite; |
454 new_glyph.sprite = BlitterFactoryBase::GetCurrentBlitter()->Encode(&sprite, AllocateFont); |
|
455 free(sprite.data); |
430 new_glyph.width = (slot->advance.x >> 6) + (size != FS_NORMAL); |
456 new_glyph.width = (slot->advance.x >> 6) + (size != FS_NORMAL); |
431 |
457 |
432 SetGlyphPtr(size, key, &new_glyph); |
458 SetGlyphPtr(size, key, &new_glyph); |
433 |
459 |
434 return sprite; |
460 return new_glyph.sprite; |
435 } |
461 } |
436 |
462 |
437 |
463 |
438 uint GetGlyphWidth(FontSize size, WChar key) |
464 uint GetGlyphWidth(FontSize size, WChar key) |
439 { |
465 { |