File: text-userfont.lua

package info (click to toggle)
oocairo 1.4-1.2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 712 kB
  • sloc: ansic: 3,352; makefile: 59; sh: 15
file content (104 lines) | stat: -rw-r--r-- 4,093 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
-- A simple demonstration of creating a 'user font' in Lua.  The new user
-- font feature in Cairo 1.8 allows you to define a font's metrics and
-- glyph images by providing callback functions, which Lua calls as needed.
-- The idea is that you can provide Cairo with access to fonts in unusual
-- formats it wouldn't normally understand, or create special effects.
--
-- Note that for now at least user fonts can't contain colour information,
-- only shapes drawn with the Cairo context provided to the rendering
-- callback.  You're not allowed to use the 'set_source' methods on it.
-- Also, there seem to be some problems with generating PDF output with
-- user fonts.
--
-- This example has callbacks which make a font based purely on the Unicode
-- codepoint numbers used for characters.  Each character is drawn as a box
-- with some diamonds in, which indicate which bits are set in the codepoint
-- number.  I can't think of any practical use for this, but I wanted
-- something simple to draw which wouldn't require a bunch of ancillary
-- font data.
--
-- I'm relying on the default glyph index mapping, which is that the glyph
-- index numbers are exactly the same as the Unicode codepoints of the
-- characters.  You can do more interesting things by providing other
-- callback functions, but for this example we just need the rendering one.
-- The rendering callback also provides the metrics for each character.
-- We actually leave them as their defaults, except for the width of the
-- glyphs, which can be wider for larger numbered characters (because we
-- display them with several columns of bits).

local Cairo = require "oocairo"

if not Cairo.user_font_face_create then
    error("User font example requires module built with Cairo 1.8", 0)
end

local BIT_WIDTH, BIT_HEIGHT, CHAR_GAP = 0.2, 1 / 8, 0.1

local function make_bit_font ()
    local function render_glyph (font, glyph, cr, extents)
        if glyph == 32 then return end      -- space, just default advance

        -- Draw a diamond shape for each bit which is set within the codepoint
        -- number, with eight bits per column.
        local n = glyph
        local x = 0
        while n ~= 0 do
            local byte = n % 0x100
            n = (n - byte) / 0x100
            for i = 0, 7 do
                local bit = byte % 2
                byte = (byte - bit) / 2
                if bit ~= 0 then
                    cr:move_to(x, (i + 0.5) * BIT_HEIGHT)
                    cr:rel_line_to(BIT_WIDTH / 2, BIT_HEIGHT / 2)
                    cr:rel_line_to(BIT_WIDTH / 2, -BIT_HEIGHT / 2)
                    cr:rel_line_to(-BIT_WIDTH / 2, -BIT_HEIGHT / 2)
                    cr:close_path()
                    cr:fill()
                end
            end
            x = x + BIT_WIDTH
        end

        -- Box round edge, 1 pixel wide and aligned on a pixel in device
        -- coordinates (so that it's sharp, and as thin as possible).
        local xpix, ypix = cr:device_to_user_distance(1, 1)
        cr:rectangle(xpix / 2, ypix / 2, x - xpix, 1 - ypix)
        cr:set_line_width(xpix)
        cr:stroke()
        extents.x_advance = x + CHAR_GAP
    end

    return Cairo.user_font_face_create({ render_glyph = render_glyph })
end

local surface = Cairo.image_surface_create("rgb24", 440, 230)
local cr = Cairo.context_create(surface)

-- White background.
cr:set_source_rgb(1, 1, 1)
cr:paint()

cr:set_font_face(make_bit_font())
cr:set_font_size(50)

-- Draw lines of text, each in a different colour.
local x, y = 20, 20
for _, info in ipairs{
    { "The quick brown fox,", { .5, 0, 0 } },
    { "jumped lazy dog…", { 0, .5, 0 } },
    -- These characters will have three columns of bits because they have
    -- large Unicode codepoint numbers.  They're actually a random selection
    -- of cuneiform characters.
    { "𒀽𒍬𒍭𒍅𒌡𒌤", { 0, 0, .5 } },
} do
    local line, color = unpack(info)
    cr:move_to(x, y)
    cr:set_source_rgb(unpack(color))
    cr:show_text(line)
    y = y + 70
end

surface:write_to_png("text-userfont.png")

-- vi:ts=4 sw=4 expandtab