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 |