Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 331743
Collapse All | Expand All

(-)cairo-9999.new/src/cairo-ft-font.c (-111 / +297 lines)
Lines 57-62 Link Here
57
#include FT_SYNTHESIS_H
57
#include FT_SYNTHESIS_H
58
#endif
58
#endif
59
59
60
#define FIR_FILTER 1
61
60
#if HAVE_FT_LIBRARY_SETLCDFILTER
62
#if HAVE_FT_LIBRARY_SETLCDFILTER
61
#include FT_LCD_FILTER_H
63
#include FT_LCD_FILTER_H
62
#endif
64
#endif
Lines 607-612 _cairo_ft_unscaled_font_destroy (void *a Link Here
607
    _cairo_ft_unscaled_font_fini (unscaled);
609
    _cairo_ft_unscaled_font_fini (unscaled);
608
}
610
}
609
611
612
static const int   fir_filter[5] = { 0x1C, 0x38, 0x55, 0x38, 0x1C };
613
610
static cairo_bool_t
614
static cairo_bool_t
611
_has_unlocked_face (const void *entry)
615
_has_unlocked_face (const void *entry)
612
{
616
{
Lines 1114-1119 _get_bitmap_surface (FT_Bitmap *bi Link Here
1114
    unsigned char *data;
1118
    unsigned char *data;
1115
    int format = CAIRO_FORMAT_A8;
1119
    int format = CAIRO_FORMAT_A8;
1116
    cairo_image_surface_t *image;
1120
    cairo_image_surface_t *image;
1121
    cairo_bool_t subpixel = FALSE;
1117
1122
1118
    width = bitmap->width;
1123
    width = bitmap->width;
1119
    height = bitmap->rows;
1124
    height = bitmap->rows;
Lines 1183-1189 _get_bitmap_surface (FT_Bitmap *bi Link Here
1183
	    }
1188
	    }
1184
1189
1185
	format = CAIRO_FORMAT_A8;
1190
	format = CAIRO_FORMAT_A8;
1186
	} else {
1191
	} else
1192
#ifdef FIR_FILTER
1193
	{
1194
	    unsigned char*  line;
1195
	    unsigned char*  bufBitmap;
1196
	    int		    pitch;
1197
	    unsigned char   *data_rgba;
1198
	    unsigned int    width_rgba, stride_rgba;
1199
	    int		    vmul = 1;
1200
	    int		    hmul = 1;
1201
1202
	    switch (font_options->subpixel_order) {
1203
	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
1204
	    case CAIRO_SUBPIXEL_ORDER_RGB:
1205
	    case CAIRO_SUBPIXEL_ORDER_BGR:
1206
	    default:
1207
		width /= 3;
1208
		hmul = 3;
1209
		break;
1210
	    case CAIRO_SUBPIXEL_ORDER_VRGB:
1211
	    case CAIRO_SUBPIXEL_ORDER_VBGR:
1212
		vmul = 3;
1213
		height /= 3;
1214
		break;
1215
	    }
1216
	    /*
1217
	     * Filter the glyph to soften the color fringes
1218
	     */
1219
	    width_rgba = width;
1220
	    stride = bitmap->pitch;
1221
	    stride_rgba = (width_rgba * 4 + 3) & ~3;
1222
	    data_rgba = calloc (1, stride_rgba * height);
1223
1224
	    /* perform in-place FIR filtering in either the horizontal or
1225
	     * vertical direction. We're going to modify the RGB graymap,
1226
	     * but that's ok, because we either own it, or its part of
1227
	     * the FreeType glyph slot, which will not be used anymore.
1228
	     */
1229
	    pitch  = bitmap->pitch;
1230
	    line   = (unsigned char*)bitmap->buffer;
1231
	    if ( pitch < 0 )
1232
		line -= pitch*(height-1);
1233
1234
	    bufBitmap = line;
1235
1236
	    switch (font_options->subpixel_order) {
1237
	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
1238
	    case CAIRO_SUBPIXEL_ORDER_RGB:
1239
	    case CAIRO_SUBPIXEL_ORDER_BGR:
1240
	    {
1241
		int  h;
1242
1243
		for ( h = height; h > 0; h--, line += pitch ) {
1244
		    int             pix[6] = { 0, 0, 0, 0, 0, 0 };
1245
		    unsigned char*  p      = line;
1246
		    unsigned char*  limit  = line + width*3;
1247
		    int             nn, val, val2;
1248
1249
		    val = p[0];
1250
		    for (nn = 0; nn < 3; nn++)
1251
			pix[2 + nn] += val * fir_filter[nn];
1252
1253
		    val = p[1];
1254
		    for (nn = 0; nn < 4; nn++)
1255
			pix[1 + nn] += val * fir_filter[nn];
1256
1257
		    p += 2;
1258
1259
		    for ( ; p  < limit; p++ ) {
1260
			val = p[0];
1261
			for (nn = 0; nn < 5; nn++)
1262
			    pix[nn] += val * fir_filter[nn];
1263
1264
			val2  = pix[0] / 256;
1265
			val2 |= -(val2 >> 8);
1266
			p[-2]  = (unsigned char)val2;
1267
1268
			for (nn = 0; nn < 5; nn++)
1269
			    pix[nn] = pix[nn + 1];
1270
		    }
1271
		    for (nn = 0; nn < 2; nn++ ) {
1272
			val2  = pix[nn] / 256;
1273
			val2 |= -(val2 >> 8);
1274
			p[nn - 2] = (unsigned char)val2;
1275
		    }
1276
		}
1277
	    }
1278
	    break;
1279
	    case CAIRO_SUBPIXEL_ORDER_VRGB:
1280
	    case CAIRO_SUBPIXEL_ORDER_VBGR:
1281
	    {
1282
		int  w;
1283
1284
		for (w = 0; w < width; w++ ) {
1285
		    int  pix[6] = { 0, 0, 0, 0, 0, 0 };
1286
		    unsigned char*  p     = bufBitmap + w;
1287
		    unsigned char*  limit = bufBitmap + w + height*3*pitch;
1288
		    int             nn, val, val2;
1289
1290
		    val = p[0];
1291
		    for (nn = 0; nn < 3; nn++)
1292
			pix[2 + nn] += val*fir_filter[nn];
1293
1294
		    val = p[pitch];
1295
		    for (nn = 0; nn < 4; nn++ )
1296
			pix[1 + nn] += val * fir_filter[nn];
1297
1298
		    p += 2*pitch;
1299
		    for ( ; p < limit; p += pitch ) {
1300
			val = p[0];
1301
			for (nn = 0; nn < 5; nn++ )
1302
			    pix[nn] += val * fir_filter[nn];
1303
1304
			val2  = pix[0] / 256;
1305
			val2 |= -(val2 >> 8);
1306
			p[-2 * pitch] = (unsigned char)val2;
1307
1308
			for (nn = 0; nn < 5; nn++)
1309
			    pix[nn] = pix[nn+1];
1310
		    }
1311
1312
		    for (nn = 0; nn < 2; nn++) {
1313
			val2  = pix[nn] / 256;
1314
			val2 |= -(val2 >> 8);
1315
			p[(nn - 2) * pitch] = (unsigned char)val2;
1316
		    }
1317
		}
1318
	    }
1319
	    break;
1320
	    default:  /* shouldn't happen */
1321
		break;
1322
	    }
1323
1324
	    /* now copy the resulting graymap into an ARGB32 image */
1325
	    {
1326
		unsigned char*  in_line  = bufBitmap;
1327
		unsigned char*  out_line = data_rgba;
1328
		int             h        = height;
1329
1330
		switch (font_options->subpixel_order) {
1331
		case CAIRO_SUBPIXEL_ORDER_DEFAULT:
1332
		case CAIRO_SUBPIXEL_ORDER_RGB:
1333
		    for ( ; h > 0; h--, in_line += pitch, out_line += stride_rgba) {
1334
			unsigned char*  in  = in_line;
1335
			int*            out = (int*)out_line;
1336
			int             w;
1337
1338
			for (w = width; w > 0; w--, in += 3, out += 1) {
1339
			    int  r = in[0];
1340
			    int  g = in[1];
1341
			    int  b = in[2];
1342
1343
			    out[0] = (g << 24) | (r << 16) | (g << 8) | b;
1344
			}
1345
		    }
1346
		    break;
1347
		case CAIRO_SUBPIXEL_ORDER_BGR:
1348
		    for ( ; h > 0; h--, in_line += pitch, out_line += stride_rgba) {
1349
			unsigned char*  in  = in_line;
1350
			int*            out = (int*)out_line;
1351
			int             w;
1352
1353
			for (w = width; w > 0; w--, in += 3, out += 1) {
1354
			    int  r = in[2];
1355
			    int  g = in[1];
1356
			    int  b = in[0];
1357
1358
			    out[0] = (g << 24) | (r << 16) | (g << 8) | b;
1359
			}
1360
		    }
1361
		    break;
1362
		case CAIRO_SUBPIXEL_ORDER_VRGB:
1363
		    for ( ; h > 0; h--, in_line += pitch*3, out_line += stride_rgba) {
1364
			unsigned char*  in  = in_line;
1365
			int*            out = (int*)out_line;
1366
			int             w;
1367
1368
			for (w = width; w > 0; w--, in += 1, out += 1) {
1369
			    int  r = in[0];
1370
			    int  g = in[pitch];
1371
			    int  b = in[pitch*2];
1372
1373
			    out[0] = (g << 24) | (r << 16) | (g << 8) | b;
1374
			}
1375
		    }
1376
		    break;
1377
		case CAIRO_SUBPIXEL_ORDER_VBGR:
1378
		    for ( ; h > 0; h--, in_line += pitch*3, out_line += stride_rgba) {
1379
			unsigned char*  in  = in_line;
1380
			int*            out = (int*)out_line;
1381
			int             w;
1382
1383
			for (w = width; w > 0; w--, in += 1, out += 1) {
1384
			    int  r = in[2*pitch];
1385
			    int  g = in[pitch];
1386
			    int  b = in[0];
1387
1388
			    out[0] = (g << 24) | (r << 16) | (g << 8) | b;
1389
			}
1390
		    }
1391
		    break;
1392
		}
1393
	    }
1394
1395
	    if (own_buffer)
1396
		free (bitmap->buffer);
1397
	    data = data_rgba;
1398
	    stride = stride_rgba;
1399
	    format = CAIRO_FORMAT_ARGB32;
1400
	    subpixel = TRUE;
1401
	    break;
1402
	}
1403
#else /* !FIR_FILTER */
1404
	{
1187
	    /* if we get there, the  data from the source bitmap
1405
	    /* if we get there, the  data from the source bitmap
1188
	     * really comes from _fill_xrender_bitmap, and is
1406
	     * really comes from _fill_xrender_bitmap, and is
1189
	     * made of 32-bit ARGB or ABGR values */
1407
	     * made of 32-bit ARGB or ABGR values */
Lines 1194-1199 _get_bitmap_surface (FT_Bitmap *bi Link Here
1194
		stride = bitmap->pitch;
1412
		stride = bitmap->pitch;
1195
		format = CAIRO_FORMAT_ARGB32;
1413
		format = CAIRO_FORMAT_ARGB32;
1196
	}
1414
	}
1415
#endif /* !FIR_FILTER */
1197
	break;
1416
	break;
1198
    case FT_PIXEL_MODE_GRAY2:
1417
    case FT_PIXEL_MODE_GRAY2:
1199
    case FT_PIXEL_MODE_GRAY4:
1418
    case FT_PIXEL_MODE_GRAY4:
Lines 1244-1302 _render_glyph_outline (FT_Face Link Here
1244
		       cairo_font_options_t	 *font_options,
1463
		       cairo_font_options_t	 *font_options,
1245
		       cairo_image_surface_t	**surface)
1464
		       cairo_image_surface_t	**surface)
1246
{
1465
{
1247
    int rgba = FC_RGBA_UNKNOWN;
1466
   FT_GlyphSlot glyphslot = face->glyph;
1248
    int lcd_filter = FT_LCD_FILTER_LEGACY;
1249
    FT_GlyphSlot glyphslot = face->glyph;
1250
    FT_Outline *outline = &glyphslot->outline;
1467
    FT_Outline *outline = &glyphslot->outline;
1251
    FT_Bitmap bitmap;
1468
    FT_Bitmap bitmap;
1252
    FT_BBox cbox;
1469
    FT_BBox cbox;
1253
    unsigned int width, height;
1470
    FT_Matrix matrix;
1471
    int hmul = 1;
1472
    int vmul = 1;
1473
    unsigned int width, height, stride;
1474
    cairo_bool_t subpixel = FALSE;
1254
    cairo_status_t status;
1475
    cairo_status_t status;
1255
    FT_Error fterror;
1256
    FT_Library library = glyphslot->library;
1257
    FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
1258
1259
    switch (font_options->antialias) {
1260
    case CAIRO_ANTIALIAS_NONE:
1261
	render_mode = FT_RENDER_MODE_MONO;
1262
	break;
1263
1264
    case CAIRO_ANTIALIAS_SUBPIXEL:
1265
	switch (font_options->subpixel_order) {
1266
	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
1267
	    case CAIRO_SUBPIXEL_ORDER_RGB:
1268
	    case CAIRO_SUBPIXEL_ORDER_BGR:
1269
		render_mode = FT_RENDER_MODE_LCD;
1270
		break;
1271
1272
	    case CAIRO_SUBPIXEL_ORDER_VRGB:
1273
	    case CAIRO_SUBPIXEL_ORDER_VBGR:
1274
		render_mode = FT_RENDER_MODE_LCD_V;
1275
		break;
1276
	}
1277
1278
	switch (font_options->lcd_filter) {
1279
	case CAIRO_LCD_FILTER_NONE:
1280
	    lcd_filter = FT_LCD_FILTER_NONE;
1281
	    break;
1282
	case CAIRO_LCD_FILTER_DEFAULT:
1283
	case CAIRO_LCD_FILTER_INTRA_PIXEL:
1284
	    lcd_filter = FT_LCD_FILTER_LEGACY;
1285
	    break;
1286
	case CAIRO_LCD_FILTER_FIR3:
1287
	    lcd_filter = FT_LCD_FILTER_LIGHT;
1288
	    break;
1289
	case CAIRO_LCD_FILTER_FIR5:
1290
	    lcd_filter = FT_LCD_FILTER_DEFAULT;
1291
	    break;
1292
	}
1293
1294
	break;
1295
1296
    case CAIRO_ANTIALIAS_DEFAULT:
1297
    case CAIRO_ANTIALIAS_GRAY:
1298
	render_mode = FT_RENDER_MODE_NORMAL;
1299
    }
1300
1476
1301
    FT_Outline_Get_CBox (outline, &cbox);
1477
    FT_Outline_Get_CBox (outline, &cbox);
1302
1478
Lines 1307-1327 _render_glyph_outline (FT_Face Link Here
1307
1483
1308
    width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
1484
    width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
1309
    height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
1485
    height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
1486
    stride = (width * hmul + 3) & ~3;
1310
1487
1311
    if (width * height == 0) {
1488
    if (width * height == 0) {
1312
	cairo_format_t format;
1489
	cairo_format_t format;
1313
	/* Looks like fb handles zero-sized images just fine */
1490
	/* Looks like fb handles zero-sized images just fine */
1314
	switch (render_mode) {
1491
	switch (font_options->antialias) {
1315
	case FT_RENDER_MODE_MONO:
1492
	case CAIRO_ANTIALIAS_NONE:
1316
	    format = CAIRO_FORMAT_A1;
1493
	    format = CAIRO_FORMAT_A1;
1317
	    break;
1494
	    break;
1318
	case FT_RENDER_MODE_LCD:
1495
	case CAIRO_ANTIALIAS_SUBPIXEL:
1319
	case FT_RENDER_MODE_LCD_V:
1320
	    format= CAIRO_FORMAT_ARGB32;
1496
	    format= CAIRO_FORMAT_ARGB32;
1321
	    break;
1497
	    break;
1322
	case FT_RENDER_MODE_LIGHT:
1498
	case CAIRO_ANTIALIAS_DEFAULT:
1323
	case FT_RENDER_MODE_NORMAL:
1499
	case CAIRO_ANTIALIAS_GRAY:
1324
	case FT_RENDER_MODE_MAX:
1325
	default:
1500
	default:
1326
	    format = CAIRO_FORMAT_A8;
1501
	    format = CAIRO_FORMAT_A8;
1327
	    break;
1502
	    break;
Lines 1331-1405 _render_glyph_outline (FT_Face Link Here
1331
	    cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
1506
	    cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
1332
	if ((*surface)->base.status)
1507
	if ((*surface)->base.status)
1333
	    return (*surface)->base.status;
1508
	    return (*surface)->base.status;
1334
    } else {
1509
    } else  {
1335
1510
1336
	int bitmap_size;
1511
	matrix.xx = matrix.yy = 0x10000L;
1512
	matrix.xy = matrix.yx = 0;
1337
1513
1338
	switch (render_mode) {
1514
	switch (font_options->antialias) {
1339
	case FT_RENDER_MODE_LCD:
1515
	case CAIRO_ANTIALIAS_NONE:
1340
	    if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR) {
1516
	    bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
1341
		rgba = FC_RGBA_BGR;
1517
	    bitmap.num_grays  = 1;
1342
	    } else {
1518
	    stride = ((width + 31) & -32) >> 3;
1343
		rgba = FC_RGBA_RGB;
1519
	    break;
1344
	    }
1520
	case CAIRO_ANTIALIAS_DEFAULT:
1345
	case FT_RENDER_MODE_LCD_V:
1521
	case CAIRO_ANTIALIAS_GRAY:
1346
	    if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR) {
1522
	    bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
1347
		rgba = FC_RGBA_VBGR;
1523
	    bitmap.num_grays  = 256;
1348
	    } else {
1524
	    stride = (width + 3) & -4;
1349
		rgba = FC_RGBA_VRGB;
1350
		}
1351
	    break;
1352
	case FT_RENDER_MODE_MONO:
1353
	case FT_RENDER_MODE_LIGHT:
1354
	case FT_RENDER_MODE_NORMAL:
1355
	case FT_RENDER_MODE_MAX:
1356
	default:
1357
	    break;
1525
	    break;
1358
	    }
1526
	case CAIRO_ANTIALIAS_SUBPIXEL:
1359
1527
	    switch (font_options->subpixel_order) {
1360
#if HAVE_FT_LIBRARY_SETLCDFILTER
1528
	    case CAIRO_SUBPIXEL_ORDER_RGB:
1361
	FT_Library_SetLcdFilter (library, lcd_filter);
1529
	    case CAIRO_SUBPIXEL_ORDER_BGR:
1530
	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
1531
	    default:
1532
		matrix.xx *= 3;
1533
		hmul = 3;
1534
		subpixel = TRUE;
1535
#ifdef FIR_FILTER
1536
		cbox.xMin -= 64;
1537
		cbox.xMax += 64;
1538
		width    += 2;
1362
#endif
1539
#endif
1363
1540
		break;
1364
	fterror = FT_Render_Glyph (face->glyph, render_mode);
1541
	    case CAIRO_SUBPIXEL_ORDER_VRGB:
1365
1542
	    case CAIRO_SUBPIXEL_ORDER_VBGR:
1366
#if HAVE_FT_LIBRARY_SETLCDFILTER
1543
		matrix.yy *= 3;
1367
	FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE);
1544
		vmul = 3;
1545
		subpixel = TRUE;
1546
#ifdef FIR_FILTER
1547
		cbox.yMin -= 64;
1548
		cbox.yMax += 64;
1549
		height    += 2;
1368
#endif
1550
#endif
1551
		break;
1552
	    }
1553
	    FT_Outline_Transform (outline, &matrix);
1369
1554
1370
	if (fterror != 0)
1555
	    bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
1371
		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1556
	    bitmap.num_grays  = 256;
1557
	    stride = (width * hmul + 3) & -4;
1558
	}
1372
1559
1373
	bitmap_size = _compute_xrender_bitmap_size (&bitmap,
1560
	bitmap.pitch = stride;
1374
						    face->glyph,
1561
	bitmap.width = width * hmul;
1375
						    render_mode);
1562
	bitmap.rows = height * vmul;
1376
	if (bitmap_size < 0)
1563
	bitmap.buffer = calloc (stride, bitmap.rows);
1564
	if (bitmap.buffer == NULL)
1377
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1565
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1378
1566
1379
	bitmap.buffer = calloc (1, bitmap_size);
1567
	FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
1380
	if (bitmap.buffer == NULL)
1381
		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1382
1568
1383
	_fill_xrender_bitmap (&bitmap, face->glyph, render_mode,
1569
	if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
1384
			      (rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR));
1570
	    free (bitmap.buffer);
1571
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1572
	}
1385
1573
1386
	/* Note:
1387
	 * _get_bitmap_surface will free bitmap.buffer if there is an error
1388
	 */
1389
	status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
1574
	status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
1390
	if (unlikely (status))
1575
	if (status)
1391
	    return status;
1576
	    return status;
1392
1393
	/* Note: the font's coordinate system is upside down from ours, so the
1394
	 * Y coordinate of the control box needs to be negated.  Moreover, device
1395
	 * offsets are position of glyph origin relative to top left while xMin
1396
	 * and yMax are offsets of top left relative to origin.  Another negation.
1397
	 */
1398
	cairo_surface_set_device_offset (&(*surface)->base,
1399
					 (double)-glyphslot->bitmap_left,
1400
					 (double)+glyphslot->bitmap_top);
1401
    }
1577
    }
1402
1578
1579
    /*
1580
     * Note: the font's coordinate system is upside down from ours, so the
1581
     * Y coordinate of the control box needs to be negated.  Moreover, device
1582
     * offsets are position of glyph origin relative to top left while xMin
1583
     * and yMax are offsets of top left relative to origin.  Another negation.
1584
     */
1585
    cairo_surface_set_device_offset (&(*surface)->base,
1586
				     floor (-(double) cbox.xMin / 64.0),
1587
				     floor (+(double) cbox.yMax / 64.0));
1588
1403
    return CAIRO_STATUS_SUCCESS;
1589
    return CAIRO_STATUS_SUCCESS;
1404
}
1590
}
1405
1591

Return to bug 331743