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 |
|