github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/golang/freetype/truetype/face.go (about) 1 // Copyright 2015 The Freetype-Go Authors. All rights reserved. 2 // Use of this source code is governed by your choice of either the 3 // FreeType License or the GNU General Public License version 2 (or 4 // any later version), both of which can be found in the LICENSE file. 5 6 package truetype 7 8 import ( 9 "image" 10 11 "github.com/insionng/yougam/libraries/golang/freetype/raster" 12 "github.com/insionng/yougam/libraries/x/image/font" 13 "github.com/insionng/yougam/libraries/x/image/math/fixed" 14 ) 15 16 func powerOf2(i int) bool { 17 return i != 0 && (i&(i-1)) == 0 18 } 19 20 // Options are optional arguments to NewFace. 21 type Options struct { 22 // Size is the font size in points, as in "a 10 point font size". 23 // 24 // A zero value means to use a 12 point font size. 25 Size float64 26 27 // DPI is the dots-per-inch resolution. 28 // 29 // A zero value means to use 72 DPI. 30 DPI float64 31 32 // Hinting is how to quantize the glyph nodes. 33 // 34 // A zero value means to use no hinting. 35 Hinting font.Hinting 36 37 // GlyphCacheEntries is the number of entries in the glyph mask image 38 // cache. 39 // 40 // If non-zero, it must be a power of 2. 41 // 42 // A zero value means to use 512 entries. 43 GlyphCacheEntries int 44 45 // SubPixelsX is the number of sub-pixel locations a glyph's dot is 46 // quantized to, in the horizontal direction. For example, a value of 8 47 // means that the dot is quantized to 1/8th of a pixel. This quantization 48 // only affects the glyph mask image, not its bounding box or advance 49 // width. A higher value gives a more faithful glyph image, but reduces the 50 // effectiveness of the glyph cache. 51 // 52 // If non-zero, it must be a power of 2, and be between 1 and 64 inclusive. 53 // 54 // A zero value means to use 4 sub-pixel locations. 55 SubPixelsX int 56 57 // SubPixelsY is the number of sub-pixel locations a glyph's dot is 58 // quantized to, in the vertical direction. For example, a value of 8 59 // means that the dot is quantized to 1/8th of a pixel. This quantization 60 // only affects the glyph mask image, not its bounding box or advance 61 // width. A higher value gives a more faithful glyph image, but reduces the 62 // effectiveness of the glyph cache. 63 // 64 // If non-zero, it must be a power of 2, and be between 1 and 64 inclusive. 65 // 66 // A zero value means to use 1 sub-pixel location. 67 SubPixelsY int 68 } 69 70 func (o *Options) size() float64 { 71 if o != nil && o.Size > 0 { 72 return o.Size 73 } 74 return 12 75 } 76 77 func (o *Options) dpi() float64 { 78 if o != nil && o.DPI > 0 { 79 return o.DPI 80 } 81 return 72 82 } 83 84 func (o *Options) hinting() font.Hinting { 85 if o != nil { 86 switch o.Hinting { 87 case font.HintingVertical, font.HintingFull: 88 // TODO: support vertical hinting. 89 return font.HintingFull 90 } 91 } 92 return font.HintingNone 93 } 94 95 func (o *Options) glyphCacheEntries() int { 96 if o != nil && powerOf2(o.GlyphCacheEntries) { 97 return o.GlyphCacheEntries 98 } 99 // 512 is 128 * 4 * 1, which lets us cache 128 glyphs at 4 * 1 subpixel 100 // locations in the X and Y direction. 101 return 512 102 } 103 104 func (o *Options) subPixelsX() (value uint32, halfQuantum, mask fixed.Int26_6) { 105 if o != nil { 106 switch o.SubPixelsX { 107 case 1, 2, 4, 8, 16, 32, 64: 108 return subPixels(o.SubPixelsX) 109 } 110 } 111 // This default value of 4 isn't based on anything scientific, merely as 112 // small a number as possible that looks almost as good as no quantization, 113 // or returning subPixels(64). 114 return subPixels(4) 115 } 116 117 func (o *Options) subPixelsY() (value uint32, halfQuantum, mask fixed.Int26_6) { 118 if o != nil { 119 switch o.SubPixelsX { 120 case 1, 2, 4, 8, 16, 32, 64: 121 return subPixels(o.SubPixelsX) 122 } 123 } 124 // This default value of 1 isn't based on anything scientific, merely that 125 // vertical sub-pixel glyph rendering is pretty rare. Baseline locations 126 // can usually afford to snap to the pixel grid, so the vertical direction 127 // doesn't have the deal with the horizontal's fractional advance widths. 128 return subPixels(1) 129 } 130 131 // subPixels returns q and the bias and mask that leads to q quantized 132 // sub-pixel locations per full pixel. 133 // 134 // For example, q == 4 leads to a bias of 8 and a mask of 0xfffffff0, or -16, 135 // because we want to round fractions of fixed.Int26_6 as: 136 // - 0 to 7 rounds to 0. 137 // - 8 to 23 rounds to 16. 138 // - 24 to 39 rounds to 32. 139 // - 40 to 55 rounds to 48. 140 // - 56 to 63 rounds to 64. 141 // which means to add 8 and then bitwise-and with -16, in two's complement 142 // representation. 143 // 144 // When q == 1, we want bias == 32 and mask == -64. 145 // When q == 2, we want bias == 16 and mask == -32. 146 // When q == 4, we want bias == 8 and mask == -16. 147 // ... 148 // When q == 64, we want bias == 0 and mask == -1. (The no-op case). 149 // The pattern is clear. 150 func subPixels(q int) (value uint32, bias, mask fixed.Int26_6) { 151 return uint32(q), 32 / fixed.Int26_6(q), -64 / fixed.Int26_6(q) 152 } 153 154 // glyphCacheEntry caches the arguments and return values of rasterize. 155 type glyphCacheEntry struct { 156 key glyphCacheKey 157 val glyphCacheVal 158 } 159 160 type glyphCacheKey struct { 161 index Index 162 fx, fy uint8 163 } 164 165 type glyphCacheVal struct { 166 advanceWidth fixed.Int26_6 167 offset image.Point 168 gw int 169 gh int 170 } 171 172 type indexCacheEntry struct { 173 rune rune 174 index Index 175 } 176 177 // NewFace returns a new font.Face for the given Font. 178 func NewFace(f *Font, opts *Options) font.Face { 179 a := &face{ 180 f: f, 181 hinting: opts.hinting(), 182 scale: fixed.Int26_6(0.5 + (opts.size() * opts.dpi() * 64 / 72)), 183 glyphCache: make([]glyphCacheEntry, opts.glyphCacheEntries()), 184 } 185 a.subPixelX, a.subPixelBiasX, a.subPixelMaskX = opts.subPixelsX() 186 a.subPixelY, a.subPixelBiasY, a.subPixelMaskY = opts.subPixelsY() 187 188 // Fill the cache with invalid entries. Valid glyph cache entries have fx 189 // and fy in the range [0, 64). Valid index cache entries have rune >= 0. 190 for i := range a.glyphCache { 191 a.glyphCache[i].key.fy = 0xff 192 } 193 for i := range a.indexCache { 194 a.indexCache[i].rune = -1 195 } 196 197 // Set the rasterizer's bounds to be big enough to handle the largest glyph. 198 b := f.Bounds(a.scale) 199 xmin := +int(b.Min.X) >> 6 200 ymin := -int(b.Max.Y) >> 6 201 xmax := +int(b.Max.X+63) >> 6 202 ymax := -int(b.Min.Y-63) >> 6 203 a.maxw = xmax - xmin 204 a.maxh = ymax - ymin 205 a.masks = image.NewAlpha(image.Rect(0, 0, a.maxw, a.maxh*len(a.glyphCache))) 206 a.r.SetBounds(a.maxw, a.maxh) 207 a.p = facePainter{a} 208 209 return a 210 } 211 212 type face struct { 213 f *Font 214 hinting font.Hinting 215 scale fixed.Int26_6 216 subPixelX uint32 217 subPixelBiasX fixed.Int26_6 218 subPixelMaskX fixed.Int26_6 219 subPixelY uint32 220 subPixelBiasY fixed.Int26_6 221 subPixelMaskY fixed.Int26_6 222 masks *image.Alpha 223 glyphCache []glyphCacheEntry 224 r raster.Rasterizer 225 p raster.Painter 226 paintOffset int 227 maxw int 228 maxh int 229 glyphBuf GlyphBuf 230 indexCache [indexCacheLen]indexCacheEntry 231 232 // TODO: clip rectangle? 233 } 234 235 const indexCacheLen = 256 236 237 func (a *face) index(r rune) Index { 238 const mask = indexCacheLen - 1 239 c := &a.indexCache[r&mask] 240 if c.rune == r { 241 return c.index 242 } 243 i := a.f.Index(r) 244 c.rune = r 245 c.index = i 246 return i 247 } 248 249 // Close satisfies the font.Face interface. 250 func (a *face) Close() error { return nil } 251 252 // Kern satisfies the font.Face interface. 253 func (a *face) Kern(r0, r1 rune) fixed.Int26_6 { 254 i0 := a.index(r0) 255 i1 := a.index(r1) 256 kern := a.f.Kern(a.scale, i0, i1) 257 if a.hinting != font.HintingNone { 258 kern = (kern + 32) &^ 63 259 } 260 return kern 261 } 262 263 // Glyph satisfies the font.Face interface. 264 func (a *face) Glyph(dot fixed.Point26_6, r rune) ( 265 dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) { 266 267 // Quantize to the sub-pixel granularity. 268 dotX := (dot.X + a.subPixelBiasX) & a.subPixelMaskX 269 dotY := (dot.Y + a.subPixelBiasY) & a.subPixelMaskY 270 271 // Split the coordinates into their integer and fractional parts. 272 ix, fx := int(dotX>>6), dotX&0x3f 273 iy, fy := int(dotY>>6), dotY&0x3f 274 275 index := a.index(r) 276 cIndex := uint32(index) 277 cIndex = cIndex*a.subPixelX - uint32(fx/a.subPixelMaskX) 278 cIndex = cIndex*a.subPixelY - uint32(fy/a.subPixelMaskY) 279 cIndex &= uint32(len(a.glyphCache) - 1) 280 a.paintOffset = a.maxh * int(cIndex) 281 k := glyphCacheKey{ 282 index: index, 283 fx: uint8(fx), 284 fy: uint8(fy), 285 } 286 var v glyphCacheVal 287 if a.glyphCache[cIndex].key != k { 288 var ok bool 289 v, ok = a.rasterize(index, fx, fy) 290 if !ok { 291 return image.Rectangle{}, nil, image.Point{}, 0, false 292 } 293 a.glyphCache[cIndex] = glyphCacheEntry{k, v} 294 } else { 295 v = a.glyphCache[cIndex].val 296 } 297 298 dr.Min = image.Point{ 299 X: ix + v.offset.X, 300 Y: iy + v.offset.Y, 301 } 302 dr.Max = image.Point{ 303 X: dr.Min.X + v.gw, 304 Y: dr.Min.Y + v.gh, 305 } 306 return dr, a.masks, image.Point{Y: a.paintOffset}, v.advanceWidth, true 307 } 308 309 func (a *face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) { 310 if err := a.glyphBuf.Load(a.f, a.scale, a.index(r), a.hinting); err != nil { 311 return fixed.Rectangle26_6{}, 0, false 312 } 313 xmin := +a.glyphBuf.Bounds.Min.X 314 ymin := -a.glyphBuf.Bounds.Max.Y 315 xmax := +a.glyphBuf.Bounds.Max.X 316 ymax := -a.glyphBuf.Bounds.Min.Y 317 if xmin > xmax || ymin > ymax { 318 return fixed.Rectangle26_6{}, 0, false 319 } 320 return fixed.Rectangle26_6{ 321 Min: fixed.Point26_6{ 322 X: xmin, 323 Y: ymin, 324 }, 325 Max: fixed.Point26_6{ 326 X: xmax, 327 Y: ymax, 328 }, 329 }, a.glyphBuf.AdvanceWidth, true 330 } 331 332 func (a *face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) { 333 if err := a.glyphBuf.Load(a.f, a.scale, a.index(r), a.hinting); err != nil { 334 return 0, false 335 } 336 return a.glyphBuf.AdvanceWidth, true 337 } 338 339 // rasterize returns the advance width, integer-pixel offset to render at, and 340 // the width and height of the given glyph at the given sub-pixel offsets. 341 // 342 // The 26.6 fixed point arguments fx and fy must be in the range [0, 1). 343 func (a *face) rasterize(index Index, fx, fy fixed.Int26_6) (v glyphCacheVal, ok bool) { 344 if err := a.glyphBuf.Load(a.f, a.scale, index, a.hinting); err != nil { 345 return glyphCacheVal{}, false 346 } 347 // Calculate the integer-pixel bounds for the glyph. 348 xmin := int(fx+a.glyphBuf.Bounds.Min.X) >> 6 349 ymin := int(fy-a.glyphBuf.Bounds.Max.Y) >> 6 350 xmax := int(fx+a.glyphBuf.Bounds.Max.X+0x3f) >> 6 351 ymax := int(fy-a.glyphBuf.Bounds.Min.Y+0x3f) >> 6 352 if xmin > xmax || ymin > ymax { 353 return glyphCacheVal{}, false 354 } 355 // A TrueType's glyph's nodes can have negative co-ordinates, but the 356 // rasterizer clips anything left of x=0 or above y=0. xmin and ymin are 357 // the pixel offsets, based on the font's FUnit metrics, that let a 358 // negative co-ordinate in TrueType space be non-negative in rasterizer 359 // space. xmin and ymin are typically <= 0. 360 fx -= fixed.Int26_6(xmin << 6) 361 fy -= fixed.Int26_6(ymin << 6) 362 // Rasterize the glyph's vectors. 363 a.r.Clear() 364 pixOffset := a.paintOffset * a.maxw 365 clear(a.masks.Pix[pixOffset : pixOffset+a.maxw*a.maxh]) 366 e0 := 0 367 for _, e1 := range a.glyphBuf.Ends { 368 a.drawContour(a.glyphBuf.Points[e0:e1], fx, fy) 369 e0 = e1 370 } 371 a.r.Rasterize(a.p) 372 return glyphCacheVal{ 373 a.glyphBuf.AdvanceWidth, 374 image.Point{xmin, ymin}, 375 xmax - xmin, 376 ymax - ymin, 377 }, true 378 } 379 380 func clear(pix []byte) { 381 for i := range pix { 382 pix[i] = 0 383 } 384 } 385 386 // drawContour draws the given closed contour with the given offset. 387 func (a *face) drawContour(ps []Point, dx, dy fixed.Int26_6) { 388 if len(ps) == 0 { 389 return 390 } 391 392 // The low bit of each point's Flags value is whether the point is on the 393 // curve. Truetype fonts only have quadratic Bézier curves, not cubics. 394 // Thus, two consecutive off-curve points imply an on-curve point in the 395 // middle of those two. 396 // 397 // See http://chanae.walon.org/pub/ttf/ttf_glyphs.htm for more details. 398 399 // ps[0] is a truetype.Point measured in FUnits and positive Y going 400 // upwards. start is the same thing measured in fixed point units and 401 // positive Y going downwards, and offset by (dx, dy). 402 start := fixed.Point26_6{ 403 X: dx + ps[0].X, 404 Y: dy - ps[0].Y, 405 } 406 var others []Point 407 if ps[0].Flags&0x01 != 0 { 408 others = ps[1:] 409 } else { 410 last := fixed.Point26_6{ 411 X: dx + ps[len(ps)-1].X, 412 Y: dy - ps[len(ps)-1].Y, 413 } 414 if ps[len(ps)-1].Flags&0x01 != 0 { 415 start = last 416 others = ps[:len(ps)-1] 417 } else { 418 start = fixed.Point26_6{ 419 X: (start.X + last.X) / 2, 420 Y: (start.Y + last.Y) / 2, 421 } 422 others = ps 423 } 424 } 425 a.r.Start(start) 426 q0, on0 := start, true 427 for _, p := range others { 428 q := fixed.Point26_6{ 429 X: dx + p.X, 430 Y: dy - p.Y, 431 } 432 on := p.Flags&0x01 != 0 433 if on { 434 if on0 { 435 a.r.Add1(q) 436 } else { 437 a.r.Add2(q0, q) 438 } 439 } else { 440 if on0 { 441 // No-op. 442 } else { 443 mid := fixed.Point26_6{ 444 X: (q0.X + q.X) / 2, 445 Y: (q0.Y + q.Y) / 2, 446 } 447 a.r.Add2(q0, mid) 448 } 449 } 450 q0, on0 = q, on 451 } 452 // Close the curve. 453 if on0 { 454 a.r.Add1(start) 455 } else { 456 a.r.Add2(q0, start) 457 } 458 } 459 460 // facePainter is like a raster.AlphaSrcPainter, with an additional Y offset 461 // (face.paintOffset) to the painted spans. 462 type facePainter struct { 463 a *face 464 } 465 466 func (p facePainter) Paint(ss []raster.Span, done bool) { 467 m := p.a.masks 468 b := m.Bounds() 469 b.Min.Y = p.a.paintOffset 470 b.Max.Y = p.a.paintOffset + p.a.maxh 471 for _, s := range ss { 472 s.Y += p.a.paintOffset 473 if s.Y < b.Min.Y { 474 continue 475 } 476 if s.Y >= b.Max.Y { 477 return 478 } 479 if s.X0 < b.Min.X { 480 s.X0 = b.Min.X 481 } 482 if s.X1 > b.Max.X { 483 s.X1 = b.Max.X 484 } 485 if s.X0 >= s.X1 { 486 continue 487 } 488 base := (s.Y-m.Rect.Min.Y)*m.Stride - m.Rect.Min.X 489 p := m.Pix[base+s.X0 : base+s.X1] 490 color := uint8(s.Alpha >> 8) 491 for i := range p { 492 p[i] = color 493 } 494 } 495 }