cairo-cleartype-1.10.patch

патч - Dmitry Ron, 12/14/2011 06:49 am

Download (13.6 KB)

 
cairo-9999/src/cairo-ft-font.c 2010-08-06 21:52:00.926000031 +0300
57 57
#include FT_SYNTHESIS_H
58 58
#endif
59 59

  
60
#define FIR_FILTER 1
61

  
60 62
#if HAVE_FT_LIBRARY_SETLCDFILTER
61 63
#include FT_LCD_FILTER_H
62 64
#endif
......
607 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 614
static cairo_bool_t
611 615
_has_unlocked_face (const void *entry)
612 616
{
......
1114 1118
    unsigned char *data;
1115 1119
    int format = CAIRO_FORMAT_A8;
1116 1120
    cairo_image_surface_t *image;
1121
    cairo_bool_t subpixel = FALSE;
1117 1122

  
1118 1123
    width = bitmap->width;
1119 1124
    height = bitmap->rows;
......
1183 1188
	    }
1184 1189

  
1185 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 1405
	    /* if we get there, the  data from the source bitmap
1188 1406
	     * really comes from _fill_xrender_bitmap, and is
1189 1407
	     * made of 32-bit ARGB or ABGR values */
......
1194 1412
		stride = bitmap->pitch;
1195 1413
		format = CAIRO_FORMAT_ARGB32;
1196 1414
	}
1415
#endif /* !FIR_FILTER */
1197 1416
	break;
1198 1417
    case FT_PIXEL_MODE_GRAY2:
1199 1418
    case FT_PIXEL_MODE_GRAY4:
......
1244 1463
		       cairo_font_options_t	 *font_options,
1245 1464
		       cairo_image_surface_t	**surface)
1246 1465
{
1247
    int rgba = FC_RGBA_UNKNOWN;
1248
    int lcd_filter = FT_LCD_FILTER_LEGACY;
1249
    FT_GlyphSlot glyphslot = face->glyph;
1466
   FT_GlyphSlot glyphslot = face->glyph;
1250 1467
    FT_Outline *outline = &glyphslot->outline;
1251 1468
    FT_Bitmap bitmap;
1252 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 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 1477
    FT_Outline_Get_CBox (outline, &cbox);
1302 1478

  
......
1307 1483

  
1308 1484
    width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
1309 1485
    height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
1486
    stride = (width * hmul + 3) & ~3;
1310 1487

  
1311 1488
    if (width * height == 0) {
1312 1489
	cairo_format_t format;
1313 1490
	/* Looks like fb handles zero-sized images just fine */
1314
	switch (render_mode) {
1315
	case FT_RENDER_MODE_MONO:
1491
	switch (font_options->antialias) {
1492
	case CAIRO_ANTIALIAS_NONE:
1316 1493
	    format = CAIRO_FORMAT_A1;
1317 1494
	    break;
1318
	case FT_RENDER_MODE_LCD:
1319
	case FT_RENDER_MODE_LCD_V:
1495
	case CAIRO_ANTIALIAS_SUBPIXEL:
1320 1496
	    format= CAIRO_FORMAT_ARGB32;
1321 1497
	    break;
1322
	case FT_RENDER_MODE_LIGHT:
1323
	case FT_RENDER_MODE_NORMAL:
1324
	case FT_RENDER_MODE_MAX:
1498
	case CAIRO_ANTIALIAS_DEFAULT:
1499
	case CAIRO_ANTIALIAS_GRAY:
1325 1500
	default:
1326 1501
	    format = CAIRO_FORMAT_A8;
1327 1502
	    break;
......
1331 1506
	    cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
1332 1507
	if ((*surface)->base.status)
1333 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) {
1339
	case FT_RENDER_MODE_LCD:
1340
	    if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR) {
1341
		rgba = FC_RGBA_BGR;
1342
	    } else {
1343
		rgba = FC_RGBA_RGB;
1344
	    }
1345
	case FT_RENDER_MODE_LCD_V:
1346
	    if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR) {
1347
		rgba = FC_RGBA_VBGR;
1348
	    } else {
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:
1514
	switch (font_options->antialias) {
1515
	case CAIRO_ANTIALIAS_NONE:
1516
	    bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
1517
	    bitmap.num_grays  = 1;
1518
	    stride = ((width + 31) & -32) >> 3;
1519
	    break;
1520
	case CAIRO_ANTIALIAS_DEFAULT:
1521
	case CAIRO_ANTIALIAS_GRAY:
1522
	    bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
1523
	    bitmap.num_grays  = 256;
1524
	    stride = (width + 3) & -4;
1357 1525
	    break;
1358
	    }
1359

  
1360
#if HAVE_FT_LIBRARY_SETLCDFILTER
1361
	FT_Library_SetLcdFilter (library, lcd_filter);
1526
	case CAIRO_ANTIALIAS_SUBPIXEL:
1527
	    switch (font_options->subpixel_order) {
1528
	    case CAIRO_SUBPIXEL_ORDER_RGB:
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 1539
#endif
1363

  
1364
	fterror = FT_Render_Glyph (face->glyph, render_mode);
1365

  
1366
#if HAVE_FT_LIBRARY_SETLCDFILTER
1367
	FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE);
1540
		break;
1541
	    case CAIRO_SUBPIXEL_ORDER_VRGB:
1542
	    case CAIRO_SUBPIXEL_ORDER_VBGR:
1543
		matrix.yy *= 3;
1544
		vmul = 3;
1545
		subpixel = TRUE;
1546
#ifdef FIR_FILTER
1547
		cbox.yMin -= 64;
1548
		cbox.yMax += 64;
1549
		height    += 2;
1368 1550
#endif
1551
		break;
1552
	    }
1553
	    FT_Outline_Transform (outline, &matrix);
1369 1554

  
1370
	if (fterror != 0)
1371
		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1555
	    bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
1556
	    bitmap.num_grays  = 256;
1557
	    stride = (width * hmul + 3) & -4;
1558
	}
1372 1559

  
1373
	bitmap_size = _compute_xrender_bitmap_size (&bitmap,
1374
						    face->glyph,
1375
						    render_mode);
1376
	if (bitmap_size < 0)
1560
	bitmap.pitch = stride;
1561
	bitmap.width = width * hmul;
1562
	bitmap.rows = height * vmul;
1563
	bitmap.buffer = calloc (stride, bitmap.rows);
1564
	if (bitmap.buffer == NULL)
1377 1565
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1378 1566

  
1379
	bitmap.buffer = calloc (1, bitmap_size);
1380
	if (bitmap.buffer == NULL)
1381
		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1567
	FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
1382 1568

  
1383
	_fill_xrender_bitmap (&bitmap, face->glyph, render_mode,
1384
			      (rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR));
1569
	if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
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 1574
	status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
1390
	if (unlikely (status))
1575
	if (status)
1391 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 1589
    return CAIRO_STATUS_SUCCESS;
1404 1590
}
1405 1591

  
Thank you!