Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
| 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 | 9 |
| 10 #include <ctype.h> | 10 #include <ctype.h> |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 #include "SkScalar.h" | 24 #include "SkScalar.h" |
| 25 #include "SkStream.h" | 25 #include "SkStream.h" |
| 26 #include "SkTypeface.h" | 26 #include "SkTypeface.h" |
| 27 #include "SkTypes.h" | 27 #include "SkTypes.h" |
| 28 #include "SkUtils.h" | 28 #include "SkUtils.h" |
| 29 | 29 |
| 30 #if defined (SK_SFNTLY_SUBSETTER) | 30 #if defined (SK_SFNTLY_SUBSETTER) |
| 31 #include SK_SFNTLY_SUBSETTER | 31 #include SK_SFNTLY_SUBSETTER |
| 32 #endif | 32 #endif |
| 33 | 33 |
| 34 static SkTypeface* refOrDefault(SkTypeface* face) { | |
| 35 return face ? SkRef(face) : SkTypeface::RefDefault(); | |
| 36 } | |
| 37 | |
| 38 /** | |
| 39 * Always resolves to a non-null typeface, either the value passed to its | |
| 40 * constructor, or the default typeface if null was passed. | |
| 41 */ | |
| 42 class SkAutoResolveDefaultTypeface { | |
| 43 public: | |
| 44 SkAutoResolveDefaultTypeface() : fFace(SkTypeface::RefDefault()) {} | |
| 45 | |
| 46 SkAutoResolveDefaultTypeface(SkTypeface* face) | |
| 47 : fFace(refOrDefault(face)) {} | |
| 48 | |
| 49 ~SkAutoResolveDefaultTypeface() { fFace->unref(); } | |
| 50 | |
| 51 SkTypeface* get() const { return fFace; } | |
| 52 SkTypeface* operator->() { return fFace; } | |
|
bungeman-skia
2013/03/13 21:33:25
Doe we want operator-> and operator SkTypeface* ?
| |
| 53 operator SkTypeface*() { return fFace; } | |
| 54 | |
| 55 private: | |
| 56 SkTypeface* fFace; | |
| 57 }; | |
| 58 | |
| 34 // PDF's notion of symbolic vs non-symbolic is related to the character set, not | 59 // PDF's notion of symbolic vs non-symbolic is related to the character set, not |
| 35 // symbols vs. characters. Rarely is a font the right character set to call it | 60 // symbols vs. characters. Rarely is a font the right character set to call it |
| 36 // non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1) | 61 // non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1) |
| 37 static const int kPdfSymbolic = 4; | 62 static const int kPdfSymbolic = 4; |
| 38 | 63 |
| 39 namespace { | 64 namespace { |
| 40 | 65 |
| 41 /////////////////////////////////////////////////////////////////////////////// | 66 /////////////////////////////////////////////////////////////////////////////// |
| 42 // File-Local Functions | 67 // File-Local Functions |
| 43 /////////////////////////////////////////////////////////////////////////////// | 68 /////////////////////////////////////////////////////////////////////////////// |
| (...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 542 static void sk_delete_array(const void* ptr, size_t, void*) { | 567 static void sk_delete_array(const void* ptr, size_t, void*) { |
| 543 // Use C-style cast to cast away const and cast type simultaneously. | 568 // Use C-style cast to cast away const and cast type simultaneously. |
| 544 delete[] (unsigned char*)ptr; | 569 delete[] (unsigned char*)ptr; |
| 545 } | 570 } |
| 546 #endif | 571 #endif |
| 547 | 572 |
| 548 static int get_subset_font_stream(const char* fontName, | 573 static int get_subset_font_stream(const char* fontName, |
| 549 const SkTypeface* typeface, | 574 const SkTypeface* typeface, |
| 550 const SkTDArray<uint32_t>& subset, | 575 const SkTDArray<uint32_t>& subset, |
| 551 SkPDFStream** fontStream) { | 576 SkPDFStream** fontStream) { |
| 552 SkAutoTUnref<SkStream> fontData( | 577 int ttcIndex; |
| 553 SkFontHost::OpenStream(SkTypeface::UniqueID(typeface))); | 578 SkAutoTUnref<SkStream> fontData(typeface->openStream(&ttcIndex)); |
| 554 | 579 |
| 555 int fontSize = fontData->getLength(); | 580 int fontSize = fontData->getLength(); |
| 556 | 581 |
| 557 #if defined (SK_SFNTLY_SUBSETTER) | 582 #if defined (SK_SFNTLY_SUBSETTER) |
| 558 // Read font into buffer. | 583 // Read font into buffer. |
| 559 SkPDFStream* subsetFontStream = NULL; | 584 SkPDFStream* subsetFontStream = NULL; |
| 560 SkTDArray<unsigned char> originalFont; | 585 SkTDArray<unsigned char> originalFont; |
| 561 originalFont.setCount(fontSize); | 586 originalFont.setCount(fontSize); |
| 562 if (fontData->read(originalFont.begin(), fontSize) == (size_t)fontSize) { | 587 if (fontData->read(originalFont.begin(), fontSize) == (size_t)fontSize) { |
| 563 unsigned char* subsetFont = NULL; | 588 unsigned char* subsetFont = NULL; |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 707 SkAutoMutexAcquire lock(CanonicalFontsMutex()); | 732 SkAutoMutexAcquire lock(CanonicalFontsMutex()); |
| 708 int index = -1; | 733 int index = -1; |
| 709 for (int i = 0 ; i < CanonicalFonts().count() ; i++) { | 734 for (int i = 0 ; i < CanonicalFonts().count() ; i++) { |
| 710 if (CanonicalFonts()[i].fFont == this) { | 735 if (CanonicalFonts()[i].fFont == this) { |
| 711 index = i; | 736 index = i; |
| 712 } | 737 } |
| 713 } | 738 } |
| 714 | 739 |
| 715 SkDEBUGCODE(int indexFound;) | 740 SkDEBUGCODE(int indexFound;) |
| 716 SkASSERT(index == -1 || | 741 SkASSERT(index == -1 || |
| 717 (Find(SkTypeface::UniqueID(fTypeface.get()), | 742 (Find(fTypeface->uniqueID(), |
| 718 fFirstGlyphID, | 743 fFirstGlyphID, |
| 719 &indexFound) && | 744 &indexFound) && |
| 720 index == indexFound)); | 745 index == indexFound)); |
| 721 if (index >= 0) { | 746 if (index >= 0) { |
| 722 CanonicalFonts().removeShuffle(index); | 747 CanonicalFonts().removeShuffle(index); |
| 723 } | 748 } |
| 724 fResources.unrefAll(); | 749 fResources.unrefAll(); |
| 725 } | 750 } |
| 726 | 751 |
| 727 void SkPDFFont::getResources(SkTDArray<SkPDFObject*>* resourceList) { | 752 void SkPDFFont::getResources(SkTDArray<SkPDFObject*>* resourceList) { |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 756 } | 781 } |
| 757 glyphIDs[i] -= (fFirstGlyphID - 1); | 782 glyphIDs[i] -= (fFirstGlyphID - 1); |
| 758 } | 783 } |
| 759 | 784 |
| 760 return numGlyphs; | 785 return numGlyphs; |
| 761 } | 786 } |
| 762 | 787 |
| 763 // static | 788 // static |
| 764 SkPDFFont* SkPDFFont::GetFontResource(SkTypeface* typeface, uint16_t glyphID) { | 789 SkPDFFont* SkPDFFont::GetFontResource(SkTypeface* typeface, uint16_t glyphID) { |
| 765 SkAutoMutexAcquire lock(CanonicalFontsMutex()); | 790 SkAutoMutexAcquire lock(CanonicalFontsMutex()); |
| 766 const uint32_t fontID = SkTypeface::UniqueID(typeface); | 791 |
| 792 SkAutoResolveDefaultTypeface autoResolve(typeface); | |
| 793 typeface = autoResolve.get(); | |
| 794 | |
| 795 const uint32_t fontID = typeface->uniqueID(); | |
| 767 int relatedFontIndex; | 796 int relatedFontIndex; |
| 768 if (Find(fontID, glyphID, &relatedFontIndex)) { | 797 if (Find(fontID, glyphID, &relatedFontIndex)) { |
| 769 CanonicalFonts()[relatedFontIndex].fFont->ref(); | 798 CanonicalFonts()[relatedFontIndex].fFont->ref(); |
| 770 return CanonicalFonts()[relatedFontIndex].fFont; | 799 return CanonicalFonts()[relatedFontIndex].fFont; |
| 771 } | 800 } |
| 772 | 801 |
| 773 SkAutoTUnref<SkAdvancedTypefaceMetrics> fontMetrics; | 802 SkAutoTUnref<SkAdvancedTypefaceMetrics> fontMetrics; |
| 774 SkPDFDict* relatedFontDescriptor = NULL; | 803 SkPDFDict* relatedFontDescriptor = NULL; |
| 775 if (relatedFontIndex >= 0) { | 804 if (relatedFontIndex >= 0) { |
| 776 SkPDFFont* relatedFont = CanonicalFonts()[relatedFontIndex].fFont; | 805 SkPDFFont* relatedFont = CanonicalFonts()[relatedFontIndex].fFont; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 793 } else { | 822 } else { |
| 794 SkAdvancedTypefaceMetrics::PerGlyphInfo info; | 823 SkAdvancedTypefaceMetrics::PerGlyphInfo info; |
| 795 info = SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo; | 824 info = SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo; |
| 796 info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( | 825 info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( |
| 797 info, SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo); | 826 info, SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo); |
| 798 #if !defined (SK_SFNTLY_SUBSETTER) | 827 #if !defined (SK_SFNTLY_SUBSETTER) |
| 799 info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( | 828 info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( |
| 800 info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo); | 829 info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo); |
| 801 #endif | 830 #endif |
| 802 fontMetrics.reset( | 831 fontMetrics.reset( |
| 803 SkFontHost::GetAdvancedTypefaceMetrics(fontID, info, NULL, 0)); | 832 typeface->getAdvancedTypefaceMetrics(info, NULL, 0)); |
| 804 #if defined (SK_SFNTLY_SUBSETTER) | 833 #if defined (SK_SFNTLY_SUBSETTER) |
| 805 if (fontMetrics.get() && | 834 if (fontMetrics.get() && |
| 806 fontMetrics->fType != SkAdvancedTypefaceMetrics::kTrueType_Font) { | 835 fontMetrics->fType != SkAdvancedTypefaceMetrics::kTrueType_Font) { |
| 807 // Font does not support subsetting, get new info with advance. | 836 // Font does not support subsetting, get new info with advance. |
| 808 info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( | 837 info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( |
| 809 info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo); | 838 info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo); |
| 810 fontMetrics.reset( | 839 fontMetrics.reset( |
| 811 SkFontHost::GetAdvancedTypefaceMetrics(fontID, info, NULL, 0)); | 840 typeface->getAdvancedTypefaceMetrics(info, NULL, 0)); |
| 812 } | 841 } |
| 813 #endif | 842 #endif |
| 814 } | 843 } |
| 815 | 844 |
| 816 SkPDFFont* font = Create(fontMetrics.get(), typeface, glyphID, | 845 SkPDFFont* font = Create(fontMetrics.get(), typeface, glyphID, |
| 817 relatedFontDescriptor); | 846 relatedFontDescriptor); |
| 818 FontRec newEntry(font, fontID, font->fFirstGlyphID); | 847 FontRec newEntry(font, fontID, font->fFirstGlyphID); |
| 819 CanonicalFonts().push(newEntry); | 848 CanonicalFonts().push(newEntry); |
| 820 return font; // Return the reference new SkPDFFont() created. | 849 return font; // Return the reference new SkPDFFont() created. |
| 821 } | 850 } |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 848 return true; | 877 return true; |
| 849 } | 878 } |
| 850 search.fGlyphID = 0; | 879 search.fGlyphID = 0; |
| 851 *index = CanonicalFonts().find(search); | 880 *index = CanonicalFonts().find(search); |
| 852 return false; | 881 return false; |
| 853 } | 882 } |
| 854 | 883 |
| 855 SkPDFFont::SkPDFFont(SkAdvancedTypefaceMetrics* info, SkTypeface* typeface, | 884 SkPDFFont::SkPDFFont(SkAdvancedTypefaceMetrics* info, SkTypeface* typeface, |
| 856 SkPDFDict* relatedFontDescriptor) | 885 SkPDFDict* relatedFontDescriptor) |
| 857 : SkPDFDict("Font"), | 886 : SkPDFDict("Font"), |
| 858 fTypeface(typeface), | 887 fTypeface(refOrDefault(typeface)), |
| 859 fFirstGlyphID(1), | 888 fFirstGlyphID(1), |
| 860 fLastGlyphID(info ? info->fLastGlyphID : 0), | 889 fLastGlyphID(info ? info->fLastGlyphID : 0), |
| 861 fFontInfo(info), | 890 fFontInfo(info), |
| 862 fDescriptor(relatedFontDescriptor) { | 891 fDescriptor(relatedFontDescriptor) { |
| 863 SkSafeRef(typeface); | 892 SkSafeRef(typeface); |
| 864 SkSafeRef(info); | 893 SkSafeRef(info); |
| 865 if (info == NULL) { | 894 if (info == NULL) { |
| 866 fFontType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; | 895 fFontType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; |
| 867 } else if (info->fMultiMaster) { | 896 } else if (info->fMultiMaster) { |
| 868 fFontType = SkAdvancedTypefaceMetrics::kOther_Font; | 897 fFontType = SkAdvancedTypefaceMetrics::kOther_Font; |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1092 SkAutoTUnref<SkPDFStream> fontStream(rawStream); | 1121 SkAutoTUnref<SkPDFStream> fontStream(rawStream); |
| 1093 addResource(fontStream.get()); | 1122 addResource(fontStream.get()); |
| 1094 | 1123 |
| 1095 fontStream->insertInt("Length1", fontSize); | 1124 fontStream->insertInt("Length1", fontSize); |
| 1096 descriptor->insert("FontFile2", | 1125 descriptor->insert("FontFile2", |
| 1097 new SkPDFObjRef(fontStream.get()))->unref(); | 1126 new SkPDFObjRef(fontStream.get()))->unref(); |
| 1098 break; | 1127 break; |
| 1099 } | 1128 } |
| 1100 case SkAdvancedTypefaceMetrics::kCFF_Font: | 1129 case SkAdvancedTypefaceMetrics::kCFF_Font: |
| 1101 case SkAdvancedTypefaceMetrics::kType1CID_Font: { | 1130 case SkAdvancedTypefaceMetrics::kType1CID_Font: { |
| 1102 SkAutoTUnref<SkStream> fontData( | 1131 int ttcIndex; |
| 1103 SkFontHost::OpenStream(SkTypeface::UniqueID(typeface()))); | 1132 SkAutoTUnref<SkStream> fontData(typeface()->openStream(&ttcIndex)); |
| 1104 SkAutoTUnref<SkPDFStream> fontStream( | 1133 SkAutoTUnref<SkPDFStream> fontStream( |
| 1105 new SkPDFStream(fontData.get())); | 1134 new SkPDFStream(fontData.get())); |
| 1106 addResource(fontStream.get()); | 1135 addResource(fontStream.get()); |
| 1107 | 1136 |
| 1108 if (getType() == SkAdvancedTypefaceMetrics::kCFF_Font) { | 1137 if (getType() == SkAdvancedTypefaceMetrics::kCFF_Font) { |
| 1109 fontStream->insertName("Subtype", "Type1C"); | 1138 fontStream->insertName("Subtype", "Type1C"); |
| 1110 } else { | 1139 } else { |
| 1111 fontStream->insertName("Subtype", "CIDFontType0c"); | 1140 fontStream->insertName("Subtype", "CIDFontType0c"); |
| 1112 } | 1141 } |
| 1113 descriptor->insert("FontFile3", | 1142 descriptor->insert("FontFile3", |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1132 subset->exportTo(&glyphIDs); | 1161 subset->exportTo(&glyphIDs); |
| 1133 } | 1162 } |
| 1134 | 1163 |
| 1135 SkAdvancedTypefaceMetrics::PerGlyphInfo info; | 1164 SkAdvancedTypefaceMetrics::PerGlyphInfo info; |
| 1136 info = SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo; | 1165 info = SkAdvancedTypefaceMetrics::kGlyphNames_PerGlyphInfo; |
| 1137 info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( | 1166 info = SkTBitOr<SkAdvancedTypefaceMetrics::PerGlyphInfo>( |
| 1138 info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo); | 1167 info, SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo); |
| 1139 uint32_t* glyphs = (glyphIDs.count() == 1) ? NULL : glyphIDs.begin(); | 1168 uint32_t* glyphs = (glyphIDs.count() == 1) ? NULL : glyphIDs.begin(); |
| 1140 uint32_t glyphsCount = glyphs ? glyphIDs.count() : 0; | 1169 uint32_t glyphsCount = glyphs ? glyphIDs.count() : 0; |
| 1141 SkAutoTUnref<SkAdvancedTypefaceMetrics> fontMetrics( | 1170 SkAutoTUnref<SkAdvancedTypefaceMetrics> fontMetrics( |
| 1142 SkFontHost::GetAdvancedTypefaceMetrics( | 1171 typeface()->getAdvancedTypefaceMetrics(info, glyphs, glyphsCount)); |
| 1143 SkTypeface::UniqueID(typeface()), | |
| 1144 info, | |
| 1145 glyphs, | |
| 1146 glyphsCount)); | |
| 1147 setFontInfo(fontMetrics.get()); | 1172 setFontInfo(fontMetrics.get()); |
| 1148 addFontDescriptor(0, &glyphIDs); | 1173 addFontDescriptor(0, &glyphIDs); |
| 1149 } else { | 1174 } else { |
| 1150 // Other CID fonts | 1175 // Other CID fonts |
| 1151 addFontDescriptor(0, NULL); | 1176 addFontDescriptor(0, NULL); |
| 1152 } | 1177 } |
| 1153 | 1178 |
| 1154 insertName("BaseFont", fontInfo()->fFontName); | 1179 insertName("BaseFont", fontInfo()->fFontName); |
| 1155 | 1180 |
| 1156 if (getType() == SkAdvancedTypefaceMetrics::kType1CID_Font) { | 1181 if (getType() == SkAdvancedTypefaceMetrics::kType1CID_Font) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1222 if (getFontDescriptor() != NULL) { | 1247 if (getFontDescriptor() != NULL) { |
| 1223 SkPDFDict* descriptor = getFontDescriptor(); | 1248 SkPDFDict* descriptor = getFontDescriptor(); |
| 1224 addResource(descriptor); | 1249 addResource(descriptor); |
| 1225 insert("FontDescriptor", new SkPDFObjRef(descriptor))->unref(); | 1250 insert("FontDescriptor", new SkPDFObjRef(descriptor))->unref(); |
| 1226 return true; | 1251 return true; |
| 1227 } | 1252 } |
| 1228 | 1253 |
| 1229 SkAutoTUnref<SkPDFDict> descriptor(new SkPDFDict("FontDescriptor")); | 1254 SkAutoTUnref<SkPDFDict> descriptor(new SkPDFDict("FontDescriptor")); |
| 1230 setFontDescriptor(descriptor.get()); | 1255 setFontDescriptor(descriptor.get()); |
| 1231 | 1256 |
| 1257 int ttcIndex; | |
| 1232 size_t header SK_INIT_TO_AVOID_WARNING; | 1258 size_t header SK_INIT_TO_AVOID_WARNING; |
| 1233 size_t data SK_INIT_TO_AVOID_WARNING; | 1259 size_t data SK_INIT_TO_AVOID_WARNING; |
| 1234 size_t trailer SK_INIT_TO_AVOID_WARNING; | 1260 size_t trailer SK_INIT_TO_AVOID_WARNING; |
| 1235 SkAutoTUnref<SkStream> rawFontData( | 1261 SkAutoTUnref<SkStream> rawFontData(typeface()->openStream(&ttcIndex)); |
| 1236 SkFontHost::OpenStream(SkTypeface::UniqueID(typeface()))); | |
| 1237 SkStream* fontData = handleType1Stream(rawFontData.get(), &header, &data, | 1262 SkStream* fontData = handleType1Stream(rawFontData.get(), &header, &data, |
| 1238 &trailer); | 1263 &trailer); |
| 1239 if (fontData == NULL) { | 1264 if (fontData == NULL) { |
| 1240 return false; | 1265 return false; |
| 1241 } | 1266 } |
| 1242 SkAutoTUnref<SkPDFStream> fontStream(new SkPDFStream(fontData)); | 1267 SkAutoTUnref<SkPDFStream> fontStream(new SkPDFStream(fontData)); |
| 1243 addResource(fontStream.get()); | 1268 addResource(fontStream.get()); |
| 1244 fontStream->insertInt("Length1", header); | 1269 fontStream->insertInt("Length1", header); |
| 1245 fontStream->insertInt("Length2", data); | 1270 fontStream->insertInt("Length2", data); |
| 1246 fontStream->insertInt("Length3", trailer); | 1271 fontStream->insertInt("Length3", trailer); |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1409 | 1434 |
| 1410 insert("FontBBox", makeFontBBox(bbox, 1000))->unref(); | 1435 insert("FontBBox", makeFontBBox(bbox, 1000))->unref(); |
| 1411 insertInt("FirstChar", firstGlyphID()); | 1436 insertInt("FirstChar", firstGlyphID()); |
| 1412 insertInt("LastChar", lastGlyphID()); | 1437 insertInt("LastChar", lastGlyphID()); |
| 1413 insert("Widths", widthArray.get()); | 1438 insert("Widths", widthArray.get()); |
| 1414 insertName("CIDToGIDMap", "Identity"); | 1439 insertName("CIDToGIDMap", "Identity"); |
| 1415 | 1440 |
| 1416 populateToUnicodeTable(NULL); | 1441 populateToUnicodeTable(NULL); |
| 1417 return true; | 1442 return true; |
| 1418 } | 1443 } |
| OLD | NEW |