From 14f2df1aefdcbb0d92535f948451410b38a877e3 Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Fri, 2 Apr 2010 10:07:24 +1100 Subject: [PATCH] Freetype-Go: Initial code check-in. R=r, rsc CC=golang-dev http://codereview.appspot.com/841042 --- AUTHORS | 14 ++ CONTRIBUTORS | 31 +++ LICENSE | 10 + README | 19 ++ example/raster/main.go | 173 +++++++++++++ freetype/raster/Makefile | 13 + freetype/raster/raster.go | 517 ++++++++++++++++++++++++++++++++++++++ licenses/ftl.txt | 169 +++++++++++++ licenses/gpl.txt | 340 +++++++++++++++++++++++++ 9 files changed, 1286 insertions(+) create mode 100644 AUTHORS create mode 100644 CONTRIBUTORS create mode 100644 LICENSE create mode 100644 README create mode 100644 example/raster/main.go create mode 100644 freetype/raster/Makefile create mode 100644 freetype/raster/raster.go create mode 100644 licenses/ftl.txt create mode 100644 licenses/gpl.txt diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..050eba8 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,14 @@ +# This is the official list of Freetype-Go authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS files. +# See the latter for an explanation. +# +# Freetype-Go is derived from Freetype, which is written in C. The latter +# is copyright 1996-2010 David Turner, Robert Wilhelm, and Werner Lemberg. + +# Names should be added to this file as +# Name or Organization +# The email address is not required for organizations. + +# Please keep the list sorted. + +Google Inc. diff --git a/CONTRIBUTORS b/CONTRIBUTORS new file mode 100644 index 0000000..e55dfee --- /dev/null +++ b/CONTRIBUTORS @@ -0,0 +1,31 @@ +# This is the official list of people who can contribute +# (and typically have contributed) code to the Freetype-Go repository. +# The AUTHORS file lists the copyright holders; this file +# lists people. For example, Google employees are listed here +# but not in AUTHORS, because Google holds the copyright. +# +# The submission process automatically checks to make sure +# that people submitting code are listed in this file (by email address). +# +# Names should be added to this file only after verifying that +# the individual or the individual's organization has agreed to +# the appropriate Contributor License Agreement, found here: +# +# http://code.google.com/legal/individual-cla-v1.0.html +# http://code.google.com/legal/corporate-cla-v1.0.html +# +# The agreement for individuals can be filled out on the web. +# +# When adding J Random Contributor's name to this file, +# either J's name or J's organization's name should be +# added to the AUTHORS file, depending on whether the +# individual or corporate CLA was used. + +# Names should be added to this file like so: +# Name + +# Please keep the list sorted. + +Nigel Tao +Rob Pike +Russ Cox diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..58a583f --- /dev/null +++ b/LICENSE @@ -0,0 +1,10 @@ +Use of the Freetype-Go software is subject to your choice of exactly one of +the following two licenses: + * The FreeType License, which is similar to the original BSD license with + an advertising clause, or + * The GNU General Public License (GPL), version 2 or later. + +The text of these licenses are available in the licenses/ftl.txt and the +licenses/gpl.txt files respectively. They are also available at +http://freetype.sourceforge.net/license.html + diff --git a/README b/README new file mode 100644 index 0000000..936b3f0 --- /dev/null +++ b/README @@ -0,0 +1,19 @@ +This is a port of the Freetype font rasterizer (www.freetype.org) to the Go +programming language (golang.org). + +It is an incomplete port: + * It only supports TrueType fonts, and not Type 1 fonts nor bitmap fonts. + * It only supports the Unicode encoding. + +There are also some implementation differences: + * It uses a 24.8 fixed point co-ordinate system everywhere internally, + as opposed to the original Freetype's mix of 26.6 (or 10.6 for 16-bit + systems) in some places, and 24.8 in the "smooth" rasterizer. + +Freetype-Go is derived from Freetype, which is written in C. Freetype is +copyright 1996-2010 David Turner, Robert Wilhelm, and Werner Lemberg. +Freetype-Go is copyright The Freetype-Go Authors, who are listed in the +AUTHORS file. + +The Freetype-Go homepage is http://code.google.com/p/freetype-go/ + diff --git a/example/raster/main.go b/example/raster/main.go new file mode 100644 index 0000000..359d7c3 --- /dev/null +++ b/example/raster/main.go @@ -0,0 +1,173 @@ +// Copyright 2010 The Freetype-Go Authors. All rights reserved. +// Use of this source code is governed by your choice of either the +// FreeType License or the GNU General Public License version 2, +// both of which can be found in the LICENSE file. + +package main + +import ( + "bufio" + "exp/draw" + "fmt" + "image" + "image/png" + "log" + "os" + + "freetype-go.googlecode.com/hg/freetype/raster" +) + +type node struct { + x, y, degree int +} + +// These contours "outside" and "inside" are from the `A' glyph from the Droid +// Serif Regular font. + +var outside = []node{ + node{414, 489, 1}, + node{336, 274, 2}, + node{327, 250, 0}, + node{322, 226, 2}, + node{317, 203, 0}, + node{317, 186, 2}, + node{317, 134, 0}, + node{350, 110, 2}, + node{384, 86, 0}, + node{453, 86, 1}, + node{500, 86, 1}, + node{500, 0, 1}, + node{0, 0, 1}, + node{0, 86, 1}, + node{39, 86, 2}, + node{69, 86, 0}, + node{90, 92, 2}, + node{111, 99, 0}, + node{128, 117, 2}, + node{145, 135, 0}, + node{160, 166, 2}, + node{176, 197, 0}, + node{195, 246, 1}, + node{649, 1462, 1}, + node{809, 1462, 1}, + node{1272, 195, 2}, + node{1284, 163, 0}, + node{1296, 142, 2}, + node{1309, 121, 0}, + node{1326, 108, 2}, + node{1343, 96, 0}, + node{1365, 91, 2}, + node{1387, 86, 0}, + node{1417, 86, 1}, + node{1444, 86, 1}, + node{1444, 0, 1}, + node{881, 0, 1}, + node{881, 86, 1}, + node{928, 86, 2}, + node{1051, 86, 0}, + node{1051, 184, 2}, + node{1051, 201, 0}, + node{1046, 219, 2}, + node{1042, 237, 0}, + node{1034, 260, 1}, + node{952, 489, 1}, + node{414, 489, -1}, +} + +var inside = []node{ + node{686, 1274, 1}, + node{453, 592, 1}, + node{915, 592, 1}, + node{686, 1274, -1}, +} + +func p(n node) raster.Point { + x, y := 20+n.x/4, 380-n.y/4 + return raster.Point{raster.Fixed(x * 256), raster.Fixed(y * 256)} +} + +func contour(r *raster.Rasterizer, ns []node) { + if len(ns) == 0 { + return + } + i := 0 + r.Start(p(ns[i])) + for { + switch ns[i].degree { + case -1: + // -1 signifies end-of-contour. + return + case 1: + i += 1 + r.Move1(p(ns[i])) + case 2: + i += 2 + r.Move2(p(ns[i-1]), p(ns[i])) + default: + panic("bad degree") + } + } +} + +func showNodes(m *image.RGBA, ns []node) { + for _, n := range ns { + p := p(n) + x, y := int(p.X)/256, int(p.Y)/256 + if x < 0 || x >= m.Width() || y < 0 || y >= m.Height() { + continue + } + var c image.Color + switch n.degree { + case 0: + c = image.Aqua + case 1: + c = image.Red + case 2: + c = image.Red + } + if c != nil { + m.Set(x, y, c) + } + } +} + +func main() { + // Rasterize the contours to a mask image. + const ( + w = 400 + h = 400 + ) + r := raster.New(w, h) + contour(r, outside) + contour(r, inside) + mask := image.NewAlpha(w, h) + r.Rasterize(raster.AlphaSrcPainter(mask)) + + // Draw the mask image (in gray) onto an RGBA image. + rgba := image.NewRGBA(w, h) + gray := image.ColorImage{image.AlphaColor{0x1f}} + draw.Draw(rgba, draw.Rect(0, 0, w, h), image.Black, draw.ZP) + draw.DrawMask(rgba, draw.Rect(0, 0, w, h), gray, draw.ZP, mask, draw.ZP, draw.Over) + showNodes(rgba, outside) + showNodes(rgba, inside) + + // Save that RGBA image to disk. + f, err := os.Open("out.png", os.O_CREAT|os.O_WRONLY, 0600) + if err != nil { + log.Stderr(err) + return + } + defer f.Close() + b := bufio.NewWriter(f) + err = png.Encode(b, rgba) + if err != nil { + log.Stderr(err) + return + } + err = b.Flush() + if err != nil { + log.Stderr(err) + return + } + fmt.Println("Wrote out.png OK.") +} diff --git a/freetype/raster/Makefile b/freetype/raster/Makefile new file mode 100644 index 0000000..3871e7b --- /dev/null +++ b/freetype/raster/Makefile @@ -0,0 +1,13 @@ +# Copyright 2010 The Freetype-Go Authors. All rights reserved. +# Use of this source code is governed by your choice of either the +# FreeType License or the GNU General Public License version 2, +# both of which can be found in the LICENSE file. + +include $(GOROOT)/src/Make.$(GOARCH) + +TARG=freetype-go.googlecode.com/hg/freetype/raster +GOFILES=\ + raster.go\ + +include $(GOROOT)/src/Make.pkg + diff --git a/freetype/raster/raster.go b/freetype/raster/raster.go new file mode 100644 index 0000000..02da407 --- /dev/null +++ b/freetype/raster/raster.go @@ -0,0 +1,517 @@ +// Copyright 2010 The Freetype-Go Authors. All rights reserved. +// Use of this source code is governed by your choice of either the +// FreeType License or the GNU General Public License version 2, +// both of which can be found in the LICENSE file. + +// The raster package provides an anti-aliasing 2-D rasterizer. +// +// It is part of the larger Freetype-Go suite of font-related packages, +// but the raster package is not specific to font rasterization, and can +// be used standalone without any other Freetype-Go package. +// +// Rasterization is done by the same area/coverage accumulation algorithm +// as the Freetype "smooth" module, and the Anti-Grain Geometry library. +// A description of the area/coverage algorithm is at +// http://projects.tuxee.net/cl-vectors/section-the-cl-aa-algorithm +package raster + +import ( + "fmt" + "image" + "strconv" +) + +// A Painter knows how to paint a span, and a span is a horizontal segment +// of a certain alpha. A fully opaque span has alpha == 1<<32-1. A span's +// alpha is non-zero until the final Paint call of the rasterization, which +// has all arguments zero. +// TODO(nigeltao): Is it worth batching spans, so that Paint takes a []Span +// instead of a single Span? +type Painter interface { + Paint(yi, xi0, xi1 int, alpha uint32) +} + +// The PainterFunc type adapts an ordinary function to the Painter interface. +type PainterFunc func(yi, xi0, xi1 int, alpha uint32) + +// Paint just delegates the call to f. +func (f PainterFunc) Paint(yi, xi0, xi1 int, alpha uint32) { + f(yi, xi0, xi1, alpha) +} + +// A 24.8 fixed point number. +type Fixed int32 + +// Human-readable format for a 24.8 fixed point number. For example, the +// number one-and-a-quarter becomes "1:064". +func (x Fixed) String() string { + i, f := x/256, x%256 + if f < 0 { + f = -f + } + return fmt.Sprintf("%d:%03d", i, f) +} + +// Two-dimensional point, in 24.8 fixed point format. +type Point struct { + X, Y Fixed +} + +// A cell is part of a linked list (for a given yi coordinate) of accumulated +// area/coverage for the pixel at (xi, yi). +type cell struct { + xi int + area, cover int + next int +} + +type Rasterizer struct { + // If false, the default behavior is to use the even-odd winding fill + // rule during Rasterize. + UseNonZeroWinding bool + + // The width of the Rasterizer. The height is implicit in len(cellIndex). + width int + // quadSplitScale is the scaling factor used to determine how many times + // to decompose a quadratic segment into a linear approximation. + quadSplitScale int + + // The current pen position. + a Point + // The current cell and its area/coverage being accumulated. + xi, yi int + area, cover int + + // Saved cells. + cell []cell + // Linked list of cells, one per row. + cellIndex []int + // Buffers. + cellBuf [256]cell + cellIndexBuf [64]int +} + +// findCell returns the index in r.cell for the cell corresponding to +// (r.xi, r.yi). The cell is created if necessary. +func (r *Rasterizer) findCell() int { + if r.yi < 0 || r.yi >= len(r.cellIndex) { + return -1 + } + xi := r.xi + if xi < 0 { + xi = -1 + } else if xi > r.width { + xi = r.width + } + i, prev := r.cellIndex[r.yi], -1 + for i != -1 && r.cell[i].xi <= xi { + if r.cell[i].xi == xi { + return i + } + i, prev = r.cell[i].next, i + } + c := len(r.cell) + if c == cap(r.cell) { + buf := make([]cell, c, 4*c) + copy(buf, r.cell) + r.cell = buf[0 : c+1] + } else { + r.cell = r.cell[0 : c+1] + } + r.cell[c] = cell{xi, 0, 0, i} + if prev == -1 { + r.cellIndex[r.yi] = c + } else { + r.cell[prev].next = c + } + return c +} + +// saveCell saves any accumulated r.area/r.cover for (r.xi, r.yi). +func (r *Rasterizer) saveCell() { + if r.area != 0 || r.cover != 0 { + i := r.findCell() + if i != -1 { + r.cell[i].area += r.area + r.cell[i].cover += r.cover + } + r.area = 0 + r.cover = 0 + } +} + +// setCell sets the (xi, yi) cell that r is accumulating area/coverage for. +func (r *Rasterizer) setCell(xi, yi int) { + if r.xi != xi || r.yi != yi { + r.saveCell() + r.xi, r.yi = xi, yi + } +} + +// scan accumulates area/coverage for the yi'th scanline, going from +// x0 to x1 in the horizontal direction (in 24.8 fixed point co-ordinates) +// and from y0f to y1f fractional vertical units within that scanline. +func (r *Rasterizer) scan(yi int, x0, y0f, x1, y1f Fixed) { + // Break the 24.8 fixed point X co-ordinates into integral and fractional parts. + x0i := int(x0) / 256 + x0f := x0 - Fixed(256*x0i) + x1i := int(x1) / 256 + x1f := x1 - Fixed(256*x1i) + + // A perfectly horizontal scan. + if y0f == y1f { + r.setCell(x1i, yi) + return + } + dx, dy := x1-x0, y1f-y0f + // A single cell scan. + if x0i == x1i { + r.area += int((x0f + x1f) * dy) + r.cover += int(dy) + return + } + // There are at least two cells. Apart from the first and last cells, + // all intermediate cells go through the full width of the cell, + // or 256 units in 24.8 fixed point format. + var ( + p, q, edge0, edge1 Fixed + xiDelta int + ) + if dx > 0 { + p, q = (256-x0f)*dy, dx + edge0, edge1, xiDelta = 0, 256, 1 + } else { + p, q = x0f*dy, -dx + edge0, edge1, xiDelta = 256, 0, -1 + } + yDelta, yRem := p/q, p%q + if yRem < 0 { + yDelta -= 1 + yRem += q + } + // Do the first cell. + xi, y := x0i, y0f + r.area += int((x0f + edge1) * yDelta) + r.cover += int(yDelta) + xi, y = xi+xiDelta, y+yDelta + r.setCell(xi, yi) + if xi != x1i { + // Do all the intermediate cells. + p = 256 * (y1f - y + yDelta) + fullDelta, fullRem := p/q, p%q + if fullRem < 0 { + fullDelta -= 1 + fullRem += q + } + yRem -= q + for xi != x1i { + yDelta = fullDelta + yRem += fullRem + if yRem >= 0 { + yDelta += 1 + yRem -= q + } + r.area += int(256 * yDelta) + r.cover += int(yDelta) + xi, y = xi+xiDelta, y+yDelta + r.setCell(xi, yi) + } + } + // Do the last cell. + yDelta = y1f - y + r.area += int((edge0 + x1f) * yDelta) + r.cover += int(yDelta) +} + +// Start starts a new curve at the given point. +func (r *Rasterizer) Start(a Point) { + r.setCell(int(a.X/256), int(a.Y/256)) + r.a = a +} + +// Move1 adds a linear segment to the current curve. +func (r *Rasterizer) Move1(b Point) { + x0, y0 := r.a.X, r.a.Y + x1, y1 := b.X, b.Y + dx, dy := x1-x0, y1-y0 + // Break the 24.8 fixed point Y co-ordinates into integral and fractional parts. + y0i := int(y0) / 256 + y0f := y0 - Fixed(256*y0i) + y1i := int(y1) / 256 + y1f := y1 - Fixed(256*y1i) + + if y0i == y1i { + // There is only one scanline. + r.scan(y0i, x0, y0f, x1, y1f) + } else { + // There are at least two scanlines. Apart from the first and last scanlines, + // all intermediate scanlines go through the full height of the row, or 256 + // units in 24.8 fixed point format. + var ( + p, q, edge0, edge1 Fixed + yiDelta int + ) + if dy > 0 { + p, q = (256-y0f)*dx, dy + edge0, edge1, yiDelta = 0, 256, 1 + } else { + p, q = y0f*dx, -dy + edge0, edge1, yiDelta = 256, 0, -1 + } + xDelta, xRem := p/q, p%q + if xRem < 0 { + xDelta -= 1 + xRem += q + } + // Do the first scanline. + x, yi := x0, y0i + r.scan(yi, x, y0f, x+xDelta, edge1) + x, yi = x+xDelta, yi+yiDelta + r.setCell(int(x)/256, yi) + if yi != y1i { + // Do all the intermediate scanlines. + p = 256 * dx + fullDelta, fullRem := p/q, p%q + if fullRem < 0 { + fullDelta -= 1 + fullRem += q + } + xRem -= q + for yi != y1i { + xDelta = fullDelta + xRem += fullRem + if xRem >= 0 { + xDelta += 1 + xRem -= q + } + r.scan(yi, x, edge0, x+xDelta, edge1) + x, yi = x+xDelta, yi+yiDelta + r.setCell(int(x)/256, yi) + } + } + // Do the last scanline. + r.scan(yi, x, edge0, x1, y1f) + } + // The next lineTo starts from b. + r.a = b +} + +// Move2 adds a quadratic segment to the current curve. +func (r *Rasterizer) Move2(b, c Point) { + // Calculate nSplit (the number of recursive decompositions) based on how `curvy' it is. + // Specifically, how much the middle point b deviates from (a+c)/2. + dx := r.a.X - 2*b.X + c.X + dy := r.a.Y - 2*b.Y + c.Y + if dx < 0 { + dx = -dx + } + if dy < 0 { + dy = -dy + } + deviation := dx + if deviation < dy { + deviation = dy + } + nsplit := 0 + deviation /= Fixed(r.quadSplitScale) + for deviation > 0 { + deviation /= 4 + nsplit++ + } + // maxd is 32-bit, and nsplit++ every time we shift off 2 bits, so maxNsplit is 16. + const maxNsplit = 16 + if nsplit > maxNsplit { + panic("freetype/raster: Move2 nsplit too large: " + strconv.Itoa(nsplit)) + } + // Recursively decompose the curve nSplit levels deep. + var ( + pStack [2*maxNsplit + 3]Point + sStack [maxNsplit + 1]int + i int + ) + sStack[0] = nsplit + pStack[0] = c + pStack[1] = b + pStack[2] = r.a + for i >= 0 { + s := sStack[i] + if s > 0 { + pp := pStack[2*i:] + // Split the quadratic curve pp[0:3] into an equivalent set of two shorter curves: + // pp[0:3] and pp[2:5]. The new pp[4] is the old pp[2], and pp[0] is unchanged. + mx := pp[1].X + pp[4].X = pp[2].X + pp[3].X = (pp[4].X + mx) / 2 + pp[1].X = (pp[0].X + mx) / 2 + pp[2].X = (pp[1].X + pp[3].X) / 2 + my := pp[1].Y + pp[4].Y = pp[2].Y + pp[3].Y = (pp[4].Y + my) / 2 + pp[1].Y = (pp[0].Y + my) / 2 + pp[2].Y = (pp[1].Y + pp[3].Y) / 2 + // The two shorter curves have one less split to do. + sStack[i] = s - 1 + sStack[i+1] = s - 1 + i++ + } else { + // Replace the level-0 quadratic with a two-linear-piece approximation. + midx := (r.a.X + 2*pStack[2*i+1].X + pStack[2*i].X) / 4 + midy := (r.a.Y + 2*pStack[2*i+1].Y + pStack[2*i].Y) / 4 + r.Move1(Point{midx, midy}) + r.Move1(pStack[2*i]) + i-- + } + } +} + +// Move3 adds a cubic segment to the current curve. +func (r *Rasterizer) Move3(b, c, d Point) { + // TODO(nigeltao): implement cubic splines, similar to Move2's quadratic splines. + panic("not implemented") +} + +// Converts an area value to a uint32 alpha value. A completely filled pixel +// corresponds to an area of 256*256*2, and an alpha of 1<<32-1. The +// conversion of area values greater than this depends on the winding rule: +// even-odd or non-zero. +func (r *Rasterizer) areaToAlpha(area int) uint32 { + // The C Freetype implementation (version 2.3.12) does "alpha := area>>1" without + // the +1. Round-to-nearest gives a more symmetric result than round-down. + // The C implementation also returns 8-bit alpha, not 32-bit alpha. + a := (area + 1) >> 1 + if a < 0 { + a = -a + } + alpha := uint32(a) + if r.UseNonZeroWinding { + if alpha > 0xffff { + alpha = 0xffff + } + } else { + alpha &= 0x1ffff + if alpha > 0x10000 { + alpha = 0x20000 - alpha + } else if alpha == 0x10000 { + alpha = 0x0ffff + } + } + alpha |= alpha << 16 + return alpha +} + +// Rasterize converts r's accumulated curves into spans for p. The spans +// passed to p are non-overlapping, and sorted by Y and then X. They all +// have non-zero width (and 0 <= xi0 < xi1 <= r.width) and non-zero alpha, +// except for the final span, which has yi, xi0, xi1 and alpha all equal +// to zero. +func (r *Rasterizer) Rasterize(p Painter) { + r.saveCell() + for yi := 0; yi < len(r.cellIndex); yi++ { + xi, cover := 0, 0 + for c := r.cellIndex[yi]; c != -1; c = r.cell[c].next { + if cover != 0 && r.cell[c].xi > xi { + alpha := r.areaToAlpha(cover * 256 * 2) + if alpha != 0 { + xi0, xi1 := xi, r.cell[c].xi + if xi0 < 0 { + xi0 = 0 + } + if xi1 >= r.width { + xi1 = r.width + } + if xi0 < xi1 { + p.Paint(yi, xi0, xi1, alpha) + } + } + } + cover += r.cell[c].cover + alpha := r.areaToAlpha(cover*256*2 - r.cell[c].area) + xi = r.cell[c].xi + 1 + if alpha != 0 { + xi0, xi1 := r.cell[c].xi, xi + if xi0 < 0 { + xi0 = 0 + } + if xi1 >= r.width { + xi1 = r.width + } + if xi0 < xi1 { + p.Paint(yi, xi0, xi1, alpha) + } + } + } + } + p.Paint(0, 0, 0, 0) +} + +// Clear cancels any previous calls to r.Start or r.MoveN. +func (r *Rasterizer) Clear() { + r.a = Point{0, 0} + r.xi = 0 + r.yi = 0 + r.area = 0 + r.cover = 0 + r.cell = r.cell[0:0] + for i := 0; i < len(r.cellIndex); i++ { + r.cellIndex[i] = -1 + } +} + +// Creates a new Rasterizer with the given bounds. +func New(width, height int) *Rasterizer { + if width < 0 { + width = 0 + } + if height < 0 { + height = 0 + } + + // Use the same qss heuristic as the C Freetype implementation. + qss := 128 + if width > 24 || height > 24 { + qss *= 2 + if width > 120 || height > 120 { + qss *= 2 + } + } + + r := new(Rasterizer) + r.width = width + r.quadSplitScale = qss + r.cell = r.cellBuf[0:0] + if height > len(r.cellIndexBuf) { + r.cellIndex = make([]int, height) + } else { + r.cellIndex = r.cellIndexBuf[0:height] + } + for i := 0; i < len(r.cellIndex); i++ { + r.cellIndex[i] = -1 + } + return r +} + +// AlphaOverPainter returns a Painter that paints onto the given Alpha image +// using the "src over dst" Porter-Duff composition operator. +func AlphaOverPainter(m *image.Alpha) Painter { + return PainterFunc(func(yi, xi0, xi1 int, alpha uint32) { + a := int(alpha >> 24) + p := m.Pixel[yi] + for i := xi0; i < xi1; i++ { + ai := int(p[i].A) + ai = (ai*255 + (255-ai)*a) / 255 + p[i] = image.AlphaColor{uint8(ai)} + } + }) +} + +// AlphaSrcPainter returns a Painter that paints onto the given Alpha image +// using the "src" Porter-Duff composition operator. +func AlphaSrcPainter(m *image.Alpha) Painter { + return PainterFunc(func(yi, xi0, xi1 int, alpha uint32) { + color := image.AlphaColor{uint8(alpha >> 24)} + p := m.Pixel[yi] + for i := xi0; i < xi1; i++ { + p[i] = color + } + }) +} diff --git a/licenses/ftl.txt b/licenses/ftl.txt new file mode 100644 index 0000000..bbaba33 --- /dev/null +++ b/licenses/ftl.txt @@ -0,0 +1,169 @@ + The FreeType Project LICENSE + ---------------------------- + + 2006-Jan-27 + + Copyright 1996-2002, 2006 by + David Turner, Robert Wilhelm, and Werner Lemberg + + + +Introduction +============ + + The FreeType Project is distributed in several archive packages; + some of them may contain, in addition to the FreeType font engine, + various tools and contributions which rely on, or relate to, the + FreeType Project. + + This license applies to all files found in such packages, and + which do not fall under their own explicit license. The license + affects thus the FreeType font engine, the test programs, + documentation and makefiles, at the very least. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we will be + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + FreeType code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering The FreeType Project and + assume no liability related to The FreeType Project. + + + Finally, many people asked us for a preferred form for a + credit/disclaimer to use in compliance with this license. We thus + encourage you to use the following text: + + """ + Portions of this software are copyright © The FreeType + Project (www.freetype.org). All rights reserved. + """ + + Please replace with the value from the FreeType version you + actually use. + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `package', `FreeType Project', + and `FreeType archive' refer to the set of files originally + distributed by the authors (David Turner, Robert Wilhelm, and + Werner Lemberg) as the `FreeType Project', be they named as alpha, + beta or final release. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using the FreeType + engine'. + + This license applies to all files distributed in the original + FreeType Project, including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The FreeType Project is copyright (C) 1996-2000 by David Turner, + Robert Wilhelm, and Werner Lemberg. All rights reserved except as + specified below. + +1. No Warranty +-------------- + + THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO + USE, OF THE FREETYPE PROJECT. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the FreeType Project (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`FTL.TXT') unaltered; any additions, deletions or changes to + the original files must be clearly indicated in accompanying + documentation. The copyright notices of the unaltered, + original files must be preserved in all copies of source + files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part of the work of the + FreeType Team, in the distribution documentation. We also + encourage you to put an URL to the FreeType web page in your + documentation, though this isn't mandatory. + + These conditions apply to any software derived from or based on + the FreeType Project, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither the FreeType authors and contributors nor you shall use + the name of the other for commercial, advertising, or promotional + purposes without specific prior written permission. + + We suggest, but do not require, that you use one or more of the + following phrases to refer to this software in your documentation + or advertising materials: `FreeType Project', `FreeType Engine', + `FreeType library', or `FreeType Distribution'. + + As you have not signed this license, you are not required to + accept it. However, as the FreeType Project is copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the FreeType + Project, you indicate that you understand and accept all the terms + of this license. + +4. Contacts +----------- + + There are two mailing lists related to FreeType: + + o freetype@nongnu.org + + Discusses general use and applications of FreeType, as well as + future and wanted additions to the library and distribution. + If you are looking for support, start in this list if you + haven't found anything to help you in the documentation. + + o freetype-devel@nongnu.org + + Discusses bugs, as well as engine internals, design issues, + specific licenses, porting, etc. + + Our home page can be found at + + http://www.freetype.org + + +--- end of FTL.TXT --- diff --git a/licenses/gpl.txt b/licenses/gpl.txt new file mode 100644 index 0000000..b2fe7b6 --- /dev/null +++ b/licenses/gpl.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License.