OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
10 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 bool fDoLinearMetrics; | 206 bool fDoLinearMetrics; |
207 bool fLCDIsVert; | 207 bool fLCDIsVert; |
208 | 208 |
209 // Need scalar versions for generateFontMetrics | 209 // Need scalar versions for generateFontMetrics |
210 SkVector fScale; | 210 SkVector fScale; |
211 SkMatrix fMatrix22Scalar; | 211 SkMatrix fMatrix22Scalar; |
212 | 212 |
213 FT_Error setupSize(); | 213 FT_Error setupSize(); |
214 void getBBoxForCurrentGlyph(SkGlyph* glyph, FT_BBox* bbox, | 214 void getBBoxForCurrentGlyph(SkGlyph* glyph, FT_BBox* bbox, |
215 bool snapToPixelBoundary = false); | 215 bool snapToPixelBoundary = false); |
| 216 bool getCBoxForLetter(char letter, FT_BBox* bbox); |
216 // Caller must lock gFTMutex before calling this function. | 217 // Caller must lock gFTMutex before calling this function. |
217 void updateGlyphIfLCD(SkGlyph* glyph); | 218 void updateGlyphIfLCD(SkGlyph* glyph); |
218 }; | 219 }; |
219 | 220 |
220 /////////////////////////////////////////////////////////////////////////// | 221 /////////////////////////////////////////////////////////////////////////// |
221 /////////////////////////////////////////////////////////////////////////// | 222 /////////////////////////////////////////////////////////////////////////// |
222 | 223 |
223 struct SkFaceRec { | 224 struct SkFaceRec { |
224 SkFaceRec* fNext; | 225 SkFaceRec* fNext; |
225 FT_Face fFace; | 226 FT_Face fFace; |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 return (os2_table->fsType & 0x202) == 0; | 425 return (os2_table->fsType & 0x202) == 0; |
425 } | 426 } |
426 return false; // We tried, fail safe. | 427 return false; // We tried, fail safe. |
427 #endif | 428 #endif |
428 } | 429 } |
429 | 430 |
430 static bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) { | 431 static bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) { |
431 const FT_UInt glyph_id = FT_Get_Char_Index(face, letter); | 432 const FT_UInt glyph_id = FT_Get_Char_Index(face, letter); |
432 if (!glyph_id) | 433 if (!glyph_id) |
433 return false; | 434 return false; |
434 FT_Load_Glyph(face, glyph_id, FT_LOAD_NO_SCALE); | 435 if (FT_Load_Glyph(face, glyph_id, FT_LOAD_NO_SCALE) != 0) |
| 436 return false; |
435 FT_Outline_Get_CBox(&face->glyph->outline, bbox); | 437 FT_Outline_Get_CBox(&face->glyph->outline, bbox); |
436 return true; | 438 return true; |
437 } | 439 } |
438 | 440 |
439 static bool getWidthAdvance(FT_Face face, int gId, int16_t* data) { | 441 static bool getWidthAdvance(FT_Face face, int gId, int16_t* data) { |
440 FT_Fixed advance = 0; | 442 FT_Fixed advance = 0; |
441 if (getAdvances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) { | 443 if (getAdvances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) { |
442 return false; | 444 return false; |
443 } | 445 } |
444 SkASSERT(data); | 446 SkASSERT(data); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 | 577 |
576 TT_PCLT* pclt_info; | 578 TT_PCLT* pclt_info; |
577 TT_OS2* os2_table; | 579 TT_OS2* os2_table; |
578 if ((pclt_info = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != NULL) { | 580 if ((pclt_info = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != NULL) { |
579 info->fCapHeight = pclt_info->CapHeight; | 581 info->fCapHeight = pclt_info->CapHeight; |
580 uint8_t serif_style = pclt_info->SerifStyle & 0x3F; | 582 uint8_t serif_style = pclt_info->SerifStyle & 0x3F; |
581 if (serif_style >= 2 && serif_style <= 6) | 583 if (serif_style >= 2 && serif_style <= 6) |
582 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; | 584 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; |
583 else if (serif_style >= 9 && serif_style <= 12) | 585 else if (serif_style >= 9 && serif_style <= 12) |
584 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; | 586 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; |
585 } else if ((os2_table = | 587 } else if (((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != N
ULL) && |
586 (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) { | 588 // sCapHeight is available only when version 2 or later. |
| 589 os2_table->version != 0xFFFF && |
| 590 os2_table->version >= 2) { |
587 info->fCapHeight = os2_table->sCapHeight; | 591 info->fCapHeight = os2_table->sCapHeight; |
588 } else { | 592 } else { |
589 // Figure out a good guess for CapHeight: average the height of M and X. | 593 // Figure out a good guess for CapHeight: average the height of M and X. |
590 FT_BBox m_bbox, x_bbox; | 594 FT_BBox m_bbox, x_bbox; |
591 bool got_m, got_x; | 595 bool got_m, got_x; |
592 got_m = GetLetterCBox(face, 'M', &m_bbox); | 596 got_m = GetLetterCBox(face, 'M', &m_bbox); |
593 got_x = GetLetterCBox(face, 'X', &x_bbox); | 597 got_x = GetLetterCBox(face, 'X', &x_bbox); |
594 if (got_m && got_x) { | 598 if (got_m && got_x) { |
595 info->fCapHeight = (m_bbox.yMax - m_bbox.yMin + x_bbox.yMax - | 599 info->fCapHeight = (m_bbox.yMax - m_bbox.yMin + x_bbox.yMax - |
596 x_bbox.yMin) / 2; | 600 x_bbox.yMin) / 2; |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1119 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.ho
riBearingX; | 1123 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.ho
riBearingX; |
1120 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.h
oriBearingY; | 1124 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.h
oriBearingY; |
1121 FT_Vector_Transform(&vector, &fMatrix22); | 1125 FT_Vector_Transform(&vector, &fMatrix22); |
1122 bbox->xMin += vector.x; | 1126 bbox->xMin += vector.x; |
1123 bbox->xMax += vector.x; | 1127 bbox->xMax += vector.x; |
1124 bbox->yMin += vector.y; | 1128 bbox->yMin += vector.y; |
1125 bbox->yMax += vector.y; | 1129 bbox->yMax += vector.y; |
1126 } | 1130 } |
1127 } | 1131 } |
1128 | 1132 |
| 1133 bool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) { |
| 1134 const FT_UInt glyph_id = FT_Get_Char_Index(fFace, letter); |
| 1135 if (!glyph_id) |
| 1136 return false; |
| 1137 if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0) |
| 1138 return false; |
| 1139 if ((fRec.fFlags & kEmbolden_Flag) && |
| 1140 !(fFace->style_flags & FT_STYLE_FLAG_BOLD)) { |
| 1141 emboldenOutline(fFace, &fFace->glyph->outline); |
| 1142 } |
| 1143 FT_Outline_Get_CBox(&fFace->glyph->outline, bbox); |
| 1144 return true; |
| 1145 } |
| 1146 |
1129 void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) { | 1147 void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) { |
1130 if (isLCD(fRec)) { | 1148 if (isLCD(fRec)) { |
1131 if (fLCDIsVert) { | 1149 if (fLCDIsVert) { |
1132 glyph->fHeight += gLCDExtra; | 1150 glyph->fHeight += gLCDExtra; |
1133 glyph->fTop -= gLCDExtra >> 1; | 1151 glyph->fTop -= gLCDExtra >> 1; |
1134 } else { | 1152 } else { |
1135 glyph->fWidth += gLCDExtra; | 1153 glyph->fWidth += gLCDExtra; |
1136 glyph->fLeft -= gLCDExtra >> 1; | 1154 glyph->fLeft -= gLCDExtra >> 1; |
1137 } | 1155 } |
1138 } | 1156 } |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1351 if (!upem) { | 1369 if (!upem) { |
1352 TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head); | 1370 TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head); |
1353 if (ttHeader) { | 1371 if (ttHeader) { |
1354 upem = SkIntToScalar(ttHeader->Units_Per_EM); | 1372 upem = SkIntToScalar(ttHeader->Units_Per_EM); |
1355 } | 1373 } |
1356 } | 1374 } |
1357 | 1375 |
1358 // use the os/2 table as a source of reasonable defaults. | 1376 // use the os/2 table as a source of reasonable defaults. |
1359 SkScalar x_height = 0.0f; | 1377 SkScalar x_height = 0.0f; |
1360 SkScalar avgCharWidth = 0.0f; | 1378 SkScalar avgCharWidth = 0.0f; |
| 1379 SkScalar cap_height = 0.0f; |
1361 TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); | 1380 TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); |
1362 if (os2) { | 1381 if (os2) { |
1363 x_height = scaleX * SkIntToScalar(os2->sxHeight) / upem; | 1382 x_height = scaleX * SkIntToScalar(os2->sxHeight) / upem; |
1364 avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem; | 1383 avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem; |
| 1384 if (os2->version != 0xFFFF && os2->version >= 2) { |
| 1385 cap_height = scaleX * SkIntToScalar(os2->sCapHeight) / upem; |
| 1386 } |
1365 } | 1387 } |
1366 | 1388 |
1367 // pull from format-specific metrics as needed | 1389 // pull from format-specific metrics as needed |
1368 SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax; | 1390 SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax; |
1369 if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font | 1391 if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font |
1370 ascent = -SkIntToScalar(face->ascender) / upem; | 1392 ascent = -SkIntToScalar(face->ascender) / upem; |
1371 descent = -SkIntToScalar(face->descender) / upem; | 1393 descent = -SkIntToScalar(face->descender) / upem; |
1372 leading = SkIntToScalar(face->height + (face->descender - face->ascender
)) / upem; | 1394 leading = SkIntToScalar(face->height + (face->descender - face->ascender
)) / upem; |
1373 xmin = SkIntToScalar(face->bbox.xMin) / upem; | 1395 xmin = SkIntToScalar(face->bbox.xMin) / upem; |
1374 xmax = SkIntToScalar(face->bbox.xMax) / upem; | 1396 xmax = SkIntToScalar(face->bbox.xMax) / upem; |
1375 ymin = -SkIntToScalar(face->bbox.yMin) / upem; | 1397 ymin = -SkIntToScalar(face->bbox.yMin) / upem; |
1376 ymax = -SkIntToScalar(face->bbox.yMax) / upem; | 1398 ymax = -SkIntToScalar(face->bbox.yMax) / upem; |
1377 // we may be able to synthesize x_height from outline | 1399 // we may be able to synthesize x_height and cap_height from outline |
1378 if (!x_height) { | 1400 if (!x_height) { |
1379 const FT_UInt x_glyph = FT_Get_Char_Index(fFace, 'x'); | 1401 FT_BBox bbox; |
1380 if (x_glyph) { | 1402 if (getCBoxForLetter('x', &bbox)) { |
1381 FT_BBox bbox; | |
1382 FT_Load_Glyph(fFace, x_glyph, fLoadGlyphFlags); | |
1383 if ((fRec.fFlags & kEmbolden_Flag) && !(fFace->style_flags & FT_
STYLE_FLAG_BOLD)) { | |
1384 emboldenOutline(fFace, &fFace->glyph->outline); | |
1385 } | |
1386 FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox); | |
1387 x_height = SkIntToScalar(bbox.yMax) / 64.0f; | 1403 x_height = SkIntToScalar(bbox.yMax) / 64.0f; |
1388 } | 1404 } |
1389 } | 1405 } |
| 1406 if (!cap_height) { |
| 1407 FT_BBox bbox; |
| 1408 if (getCBoxForLetter('H', &bbox)) { |
| 1409 cap_height = SkIntToScalar(bbox.yMax) / 64.0f; |
| 1410 } |
| 1411 } |
1390 } else if (fStrikeIndex != -1) { // bitmap strike metrics | 1412 } else if (fStrikeIndex != -1) { // bitmap strike metrics |
1391 SkScalar xppem = SkIntToScalar(face->size->metrics.x_ppem); | 1413 SkScalar xppem = SkIntToScalar(face->size->metrics.x_ppem); |
1392 SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem); | 1414 SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem); |
1393 ascent = -SkIntToScalar(face->size->metrics.ascender) / (yppem * 64.0f); | 1415 ascent = -SkIntToScalar(face->size->metrics.ascender) / (yppem * 64.0f); |
1394 descent = -SkIntToScalar(face->size->metrics.descender) / (yppem * 64.0f
); | 1416 descent = -SkIntToScalar(face->size->metrics.descender) / (yppem * 64.0f
); |
1395 leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f)) | 1417 leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f)) |
1396 + ascent - descent; | 1418 + ascent - descent; |
1397 xmin = 0.0f; | 1419 xmin = 0.0f; |
1398 xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem; | 1420 xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem; |
1399 ymin = descent + leading; | 1421 ymin = descent + leading; |
1400 ymax = ascent - descent; | 1422 ymax = ascent - descent; |
1401 if (!x_height) { | |
1402 x_height = -ascent; | |
1403 } | |
1404 if (!avgCharWidth) { | |
1405 avgCharWidth = xmax - xmin; | |
1406 } | |
1407 } else { | 1423 } else { |
1408 goto ERROR; | 1424 goto ERROR; |
1409 } | 1425 } |
1410 | 1426 |
1411 // synthesize elements that were not provided by the os/2 table or format-sp
ecific metrics | 1427 // synthesize elements that were not provided by the os/2 table or format-sp
ecific metrics |
1412 if (!x_height) { | 1428 if (!x_height) { |
1413 x_height = -ascent; | 1429 x_height = -ascent; |
1414 } | 1430 } |
1415 if (!avgCharWidth) { | 1431 if (!avgCharWidth) { |
1416 avgCharWidth = xmax - xmin; | 1432 avgCharWidth = xmax - xmin; |
1417 } | 1433 } |
| 1434 if (!cap_height) { |
| 1435 cap_height = -ascent; |
| 1436 } |
1418 | 1437 |
1419 // disallow negative linespacing | 1438 // disallow negative linespacing |
1420 if (leading < 0.0f) { | 1439 if (leading < 0.0f) { |
1421 leading = 0.0f; | 1440 leading = 0.0f; |
1422 } | 1441 } |
1423 | 1442 |
1424 if (mx) { | 1443 if (mx) { |
1425 mx->fTop = ymax * mxy; | 1444 mx->fTop = ymax * mxy; |
1426 mx->fAscent = ascent * mxy; | 1445 mx->fAscent = ascent * mxy; |
1427 mx->fDescent = descent * mxy; | 1446 mx->fDescent = descent * mxy; |
1428 mx->fBottom = ymin * mxy; | 1447 mx->fBottom = ymin * mxy; |
1429 mx->fLeading = leading * mxy; | 1448 mx->fLeading = leading * mxy; |
1430 mx->fAvgCharWidth = avgCharWidth * mxy; | 1449 mx->fAvgCharWidth = avgCharWidth * mxy; |
1431 mx->fXMin = xmin; | 1450 mx->fXMin = xmin; |
1432 mx->fXMax = xmax; | 1451 mx->fXMax = xmax; |
1433 mx->fXHeight = x_height; | 1452 mx->fXHeight = x_height; |
| 1453 mx->fCapHeight = cap_height; |
1434 } | 1454 } |
1435 if (my) { | 1455 if (my) { |
1436 my->fTop = ymax * myy; | 1456 my->fTop = ymax * myy; |
1437 my->fAscent = ascent * myy; | 1457 my->fAscent = ascent * myy; |
1438 my->fDescent = descent * myy; | 1458 my->fDescent = descent * myy; |
1439 my->fBottom = ymin * myy; | 1459 my->fBottom = ymin * myy; |
1440 my->fLeading = leading * myy; | 1460 my->fLeading = leading * myy; |
1441 my->fAvgCharWidth = avgCharWidth * myy; | 1461 my->fAvgCharWidth = avgCharWidth * myy; |
1442 my->fXMin = xmin; | 1462 my->fXMin = xmin; |
1443 my->fXMax = xmax; | 1463 my->fXMax = xmax; |
1444 my->fXHeight = x_height; | 1464 my->fXHeight = x_height; |
| 1465 my->fCapHeight = cap_height; |
1445 } | 1466 } |
1446 } | 1467 } |
1447 | 1468 |
1448 /////////////////////////////////////////////////////////////////////////////// | 1469 /////////////////////////////////////////////////////////////////////////////// |
1449 | 1470 |
1450 #include "SkUtils.h" | 1471 #include "SkUtils.h" |
1451 | 1472 |
1452 static SkUnichar next_utf8(const void** chars) { | 1473 static SkUnichar next_utf8(const void** chars) { |
1453 return SkUTF8_NextUnichar((const char**)chars); | 1474 return SkUTF8_NextUnichar((const char**)chars); |
1454 } | 1475 } |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1641 *style = (SkTypeface::Style) tempStyle; | 1662 *style = (SkTypeface::Style) tempStyle; |
1642 } | 1663 } |
1643 if (isFixedPitch) { | 1664 if (isFixedPitch) { |
1644 *isFixedPitch = FT_IS_FIXED_WIDTH(face); | 1665 *isFixedPitch = FT_IS_FIXED_WIDTH(face); |
1645 } | 1666 } |
1646 | 1667 |
1647 FT_Done_Face(face); | 1668 FT_Done_Face(face); |
1648 FT_Done_FreeType(library); | 1669 FT_Done_FreeType(library); |
1649 return true; | 1670 return true; |
1650 } | 1671 } |
OLD | NEW |