Chromium Code Reviews| 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 = |
| 586 (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) { | 588 (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) && |
|
bungeman-skia
2013/12/12 17:12:35
Note that Skia now has an 80 soft / 100 hard colum
Yuki
2013/12/13 09:32:14
Done.
| |
| 589 // sCapHeight is available only when version 2 or later. | |
| 590 os2_table->version != 0xFFFF && | |
| 591 os2_table->version >= 2) { | |
| 587 info->fCapHeight = os2_table->sCapHeight; | 592 info->fCapHeight = os2_table->sCapHeight; |
| 588 } else { | 593 } else { |
| 589 // Figure out a good guess for CapHeight: average the height of M and X. | 594 // Figure out a good guess for CapHeight: average the height of M and X. |
| 590 FT_BBox m_bbox, x_bbox; | 595 FT_BBox m_bbox, x_bbox; |
| 591 bool got_m, got_x; | 596 bool got_m, got_x; |
| 592 got_m = GetLetterCBox(face, 'M', &m_bbox); | 597 got_m = GetLetterCBox(face, 'M', &m_bbox); |
| 593 got_x = GetLetterCBox(face, 'X', &x_bbox); | 598 got_x = GetLetterCBox(face, 'X', &x_bbox); |
| 594 if (got_m && got_x) { | 599 if (got_m && got_x) { |
| 595 info->fCapHeight = (m_bbox.yMax - m_bbox.yMin + x_bbox.yMax - | 600 info->fCapHeight = (m_bbox.yMax - m_bbox.yMin + x_bbox.yMax - |
| 596 x_bbox.yMin) / 2; | 601 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; | 1124 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.ho riBearingX; |
| 1120 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.h oriBearingY; | 1125 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.h oriBearingY; |
| 1121 FT_Vector_Transform(&vector, &fMatrix22); | 1126 FT_Vector_Transform(&vector, &fMatrix22); |
| 1122 bbox->xMin += vector.x; | 1127 bbox->xMin += vector.x; |
| 1123 bbox->xMax += vector.x; | 1128 bbox->xMax += vector.x; |
| 1124 bbox->yMin += vector.y; | 1129 bbox->yMin += vector.y; |
| 1125 bbox->yMax += vector.y; | 1130 bbox->yMax += vector.y; |
| 1126 } | 1131 } |
| 1127 } | 1132 } |
| 1128 | 1133 |
| 1134 bool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) { | |
| 1135 const FT_UInt glyph_id = FT_Get_Char_Index(fFace, letter); | |
| 1136 if (!glyph_id) | |
| 1137 return false; | |
| 1138 if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0) | |
| 1139 return false; | |
| 1140 if ((fRec.fFlags & kEmbolden_Flag) && | |
| 1141 !(fFace->style_flags & FT_STYLE_FLAG_BOLD)) { | |
| 1142 emboldenOutline(fFace, &fFace->glyph->outline); | |
| 1143 } | |
| 1144 FT_Outline_Get_CBox(&fFace->glyph->outline, bbox); | |
| 1145 return true; | |
| 1146 } | |
| 1147 | |
| 1129 void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) { | 1148 void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) { |
| 1130 if (isLCD(fRec)) { | 1149 if (isLCD(fRec)) { |
| 1131 if (fLCDIsVert) { | 1150 if (fLCDIsVert) { |
| 1132 glyph->fHeight += gLCDExtra; | 1151 glyph->fHeight += gLCDExtra; |
| 1133 glyph->fTop -= gLCDExtra >> 1; | 1152 glyph->fTop -= gLCDExtra >> 1; |
| 1134 } else { | 1153 } else { |
| 1135 glyph->fWidth += gLCDExtra; | 1154 glyph->fWidth += gLCDExtra; |
| 1136 glyph->fLeft -= gLCDExtra >> 1; | 1155 glyph->fLeft -= gLCDExtra >> 1; |
| 1137 } | 1156 } |
| 1138 } | 1157 } |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1351 if (!upem) { | 1370 if (!upem) { |
| 1352 TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head); | 1371 TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head); |
| 1353 if (ttHeader) { | 1372 if (ttHeader) { |
| 1354 upem = SkIntToScalar(ttHeader->Units_Per_EM); | 1373 upem = SkIntToScalar(ttHeader->Units_Per_EM); |
| 1355 } | 1374 } |
| 1356 } | 1375 } |
| 1357 | 1376 |
| 1358 // use the os/2 table as a source of reasonable defaults. | 1377 // use the os/2 table as a source of reasonable defaults. |
| 1359 SkScalar x_height = 0.0f; | 1378 SkScalar x_height = 0.0f; |
| 1360 SkScalar avgCharWidth = 0.0f; | 1379 SkScalar avgCharWidth = 0.0f; |
| 1380 SkScalar cap_height = 0.0f; | |
| 1361 TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); | 1381 TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); |
| 1362 if (os2) { | 1382 if (os2) { |
| 1363 x_height = scaleX * SkIntToScalar(os2->sxHeight) / upem; | 1383 x_height = scaleX * SkIntToScalar(os2->sxHeight) / upem; |
| 1364 avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem; | 1384 avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem; |
| 1385 if (os2->version != 0xFFFF && os2->version >= 2) { | |
| 1386 cap_height = scaleX * SkIntToScalar(os2->sCapHeight) / upem; | |
| 1387 } | |
| 1365 } | 1388 } |
| 1366 | 1389 |
| 1367 // pull from format-specific metrics as needed | 1390 // pull from format-specific metrics as needed |
| 1368 SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax; | 1391 SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax; |
| 1369 if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font | 1392 if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font |
| 1370 ascent = -SkIntToScalar(face->ascender) / upem; | 1393 ascent = -SkIntToScalar(face->ascender) / upem; |
| 1371 descent = -SkIntToScalar(face->descender) / upem; | 1394 descent = -SkIntToScalar(face->descender) / upem; |
| 1372 leading = SkIntToScalar(face->height + (face->descender - face->ascender )) / upem; | 1395 leading = SkIntToScalar(face->height + (face->descender - face->ascender )) / upem; |
| 1373 xmin = SkIntToScalar(face->bbox.xMin) / upem; | 1396 xmin = SkIntToScalar(face->bbox.xMin) / upem; |
| 1374 xmax = SkIntToScalar(face->bbox.xMax) / upem; | 1397 xmax = SkIntToScalar(face->bbox.xMax) / upem; |
| 1375 ymin = -SkIntToScalar(face->bbox.yMin) / upem; | 1398 ymin = -SkIntToScalar(face->bbox.yMin) / upem; |
| 1376 ymax = -SkIntToScalar(face->bbox.yMax) / upem; | 1399 ymax = -SkIntToScalar(face->bbox.yMax) / upem; |
| 1377 // we may be able to synthesize x_height from outline | 1400 // we may be able to synthesize x_height and cap_height from outline |
| 1378 if (!x_height) { | 1401 if (!x_height) { |
| 1379 const FT_UInt x_glyph = FT_Get_Char_Index(fFace, 'x'); | 1402 FT_BBox bbox; |
| 1380 if (x_glyph) { | 1403 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; | 1404 x_height = SkIntToScalar(bbox.yMax) / 64.0f; |
| 1388 } | 1405 } |
| 1389 } | 1406 } |
| 1407 if (!cap_height) { | |
| 1408 FT_BBox m_bbox, x_bbox; | |
| 1409 bool got_m, got_x; | |
| 1410 FT_Pos avg_height = 0; | |
| 1411 got_m = getCBoxForLetter('M', &m_bbox); | |
|
bungeman-skia
2013/12/12 17:12:35
I think traditionally H is used if available. If t
Yuki
2013/12/13 09:32:14
Following your recommendation and tradition, I use
| |
| 1412 got_x = getCBoxForLetter('X', &x_bbox); | |
| 1413 if (got_m && got_x) { | |
| 1414 avg_height = (m_bbox.yMax - m_bbox.yMin + | |
| 1415 x_bbox.yMax - x_bbox.yMin) / 2; | |
| 1416 } else if (got_m) { | |
| 1417 avg_height = m_bbox.yMax - m_bbox.yMin; | |
| 1418 } else if (got_x) { | |
| 1419 avg_height = x_bbox.yMax - x_bbox.yMin; | |
| 1420 } | |
| 1421 if (avg_height) | |
| 1422 cap_height = SkIntToScalar(avg_height) / 64.0f; | |
| 1423 } | |
| 1390 } else if (fStrikeIndex != -1) { // bitmap strike metrics | 1424 } else if (fStrikeIndex != -1) { // bitmap strike metrics |
| 1391 SkScalar xppem = SkIntToScalar(face->size->metrics.x_ppem); | 1425 SkScalar xppem = SkIntToScalar(face->size->metrics.x_ppem); |
| 1392 SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem); | 1426 SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem); |
| 1393 ascent = -SkIntToScalar(face->size->metrics.ascender) / (yppem * 64.0f); | 1427 ascent = -SkIntToScalar(face->size->metrics.ascender) / (yppem * 64.0f); |
| 1394 descent = -SkIntToScalar(face->size->metrics.descender) / (yppem * 64.0f ); | 1428 descent = -SkIntToScalar(face->size->metrics.descender) / (yppem * 64.0f ); |
| 1395 leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f)) | 1429 leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f)) |
| 1396 + ascent - descent; | 1430 + ascent - descent; |
| 1397 xmin = 0.0f; | 1431 xmin = 0.0f; |
| 1398 xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem; | 1432 xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem; |
| 1399 ymin = descent + leading; | 1433 ymin = descent + leading; |
| 1400 ymax = ascent - descent; | 1434 ymax = ascent - descent; |
| 1401 if (!x_height) { | |
| 1402 x_height = -ascent; | |
| 1403 } | |
| 1404 if (!avgCharWidth) { | |
| 1405 avgCharWidth = xmax - xmin; | |
| 1406 } | |
| 1407 } else { | 1435 } else { |
| 1408 goto ERROR; | 1436 goto ERROR; |
| 1409 } | 1437 } |
| 1410 | 1438 |
| 1411 // synthesize elements that were not provided by the os/2 table or format-sp ecific metrics | 1439 // synthesize elements that were not provided by the os/2 table or format-sp ecific metrics |
| 1412 if (!x_height) { | 1440 if (!x_height) { |
| 1413 x_height = -ascent; | 1441 x_height = -ascent; |
| 1414 } | 1442 } |
| 1415 if (!avgCharWidth) { | 1443 if (!avgCharWidth) { |
| 1416 avgCharWidth = xmax - xmin; | 1444 avgCharWidth = xmax - xmin; |
| 1417 } | 1445 } |
| 1446 if (!cap_height) { | |
| 1447 cap_height = -ascent; | |
| 1448 } | |
| 1418 | 1449 |
| 1419 // disallow negative linespacing | 1450 // disallow negative linespacing |
| 1420 if (leading < 0.0f) { | 1451 if (leading < 0.0f) { |
| 1421 leading = 0.0f; | 1452 leading = 0.0f; |
| 1422 } | 1453 } |
| 1423 | 1454 |
| 1424 if (mx) { | 1455 if (mx) { |
| 1425 mx->fTop = ymax * mxy; | 1456 mx->fTop = ymax * mxy; |
| 1426 mx->fAscent = ascent * mxy; | 1457 mx->fAscent = ascent * mxy; |
| 1427 mx->fDescent = descent * mxy; | 1458 mx->fDescent = descent * mxy; |
| 1428 mx->fBottom = ymin * mxy; | 1459 mx->fBottom = ymin * mxy; |
| 1429 mx->fLeading = leading * mxy; | 1460 mx->fLeading = leading * mxy; |
| 1430 mx->fAvgCharWidth = avgCharWidth * mxy; | 1461 mx->fAvgCharWidth = avgCharWidth * mxy; |
| 1431 mx->fXMin = xmin; | 1462 mx->fXMin = xmin; |
| 1432 mx->fXMax = xmax; | 1463 mx->fXMax = xmax; |
| 1433 mx->fXHeight = x_height; | 1464 mx->fXHeight = x_height; |
| 1465 mx->fCapHeight = cap_height; | |
| 1434 } | 1466 } |
| 1435 if (my) { | 1467 if (my) { |
| 1436 my->fTop = ymax * myy; | 1468 my->fTop = ymax * myy; |
| 1437 my->fAscent = ascent * myy; | 1469 my->fAscent = ascent * myy; |
| 1438 my->fDescent = descent * myy; | 1470 my->fDescent = descent * myy; |
| 1439 my->fBottom = ymin * myy; | 1471 my->fBottom = ymin * myy; |
| 1440 my->fLeading = leading * myy; | 1472 my->fLeading = leading * myy; |
| 1441 my->fAvgCharWidth = avgCharWidth * myy; | 1473 my->fAvgCharWidth = avgCharWidth * myy; |
| 1442 my->fXMin = xmin; | 1474 my->fXMin = xmin; |
| 1443 my->fXMax = xmax; | 1475 my->fXMax = xmax; |
| 1444 my->fXHeight = x_height; | 1476 my->fXHeight = x_height; |
| 1477 my->fCapHeight = cap_height; | |
| 1445 } | 1478 } |
| 1446 } | 1479 } |
| 1447 | 1480 |
| 1448 /////////////////////////////////////////////////////////////////////////////// | 1481 /////////////////////////////////////////////////////////////////////////////// |
| 1449 | 1482 |
| 1450 #include "SkUtils.h" | 1483 #include "SkUtils.h" |
| 1451 | 1484 |
| 1452 static SkUnichar next_utf8(const void** chars) { | 1485 static SkUnichar next_utf8(const void** chars) { |
| 1453 return SkUTF8_NextUnichar((const char**)chars); | 1486 return SkUTF8_NextUnichar((const char**)chars); |
| 1454 } | 1487 } |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1641 *style = (SkTypeface::Style) tempStyle; | 1674 *style = (SkTypeface::Style) tempStyle; |
| 1642 } | 1675 } |
| 1643 if (isFixedPitch) { | 1676 if (isFixedPitch) { |
| 1644 *isFixedPitch = FT_IS_FIXED_WIDTH(face); | 1677 *isFixedPitch = FT_IS_FIXED_WIDTH(face); |
| 1645 } | 1678 } |
| 1646 | 1679 |
| 1647 FT_Done_Face(face); | 1680 FT_Done_Face(face); |
| 1648 FT_Done_FreeType(library); | 1681 FT_Done_FreeType(library); |
| 1649 return true; | 1682 return true; |
| 1650 } | 1683 } |
| OLD | NEW |