OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2005, 2006, 2012 Apple Inc. All rights reserved. | 2 * Copyright (C) 2005, 2006, 2012 Apple Inc. All rights reserved. |
3 * Copyright (C) 2006 Alexey Proskuryakov | 3 * Copyright (C) 2006 Alexey Proskuryakov |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
11 * notice, this list of conditions and the following disclaimer in the | 11 * notice, this list of conditions and the following disclaimer in the |
12 * documentation and/or other materials provided with the distribution. | 12 * documentation and/or other materials provided with the distribution. |
13 * | 13 * |
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | 23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
24 * THE POSSIBILITY OF SUCH DAMAGE. | 24 * THE POSSIBILITY OF SUCH DAMAGE. |
25 */ | 25 */ |
26 | 26 |
27 #include "config.h" | 27 #include "config.h" |
28 #include "platform/fonts/SimpleFontData.h" | 28 #include "platform/fonts/SimpleFontData.h" |
29 | 29 |
| 30 #include "platform/fonts/Character.h" |
| 31 #include "platform/fonts/Font.h" |
| 32 #include "platform/fonts/GlyphPage.h" |
30 #include <ApplicationServices/ApplicationServices.h> | 33 #include <ApplicationServices/ApplicationServices.h> |
31 | 34 |
| 35 // Forward declare Mac SPIs. |
| 36 // Request for public API: rdar://13787589 |
| 37 extern "C" { |
| 38 void CGFontGetGlyphsForUnichars(CGFontRef, const UniChar chars[], CGGlyph glyphs
[], size_t length); |
| 39 } |
| 40 |
32 namespace WebCore { | 41 namespace WebCore { |
33 | 42 |
34 CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typese
ttingFeatures, FontOrientation orientation) const | 43 CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typese
ttingFeatures, FontOrientation orientation) const |
35 { | 44 { |
36 unsigned key = typesettingFeatures + 1; | 45 unsigned key = typesettingFeatures + 1; |
37 HashMap<unsigned, RetainPtr<CFDictionaryRef> >::AddResult addResult = m_CFSt
ringAttributes.add(key, RetainPtr<CFDictionaryRef>()); | 46 HashMap<unsigned, RetainPtr<CFDictionaryRef> >::AddResult addResult = m_CFSt
ringAttributes.add(key, RetainPtr<CFDictionaryRef>()); |
38 RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.storedValue->va
lue; | 47 RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.storedValue->va
lue; |
39 if (!addResult.isNewEntry) | 48 if (!addResult.isNewEntry) |
40 return attributesDictionary.get(); | 49 return attributesDictionary.get(); |
41 | 50 |
(...skipping 14 matching lines...) Expand all Loading... |
56 static CFNumberRef essentialLigaturesValue = CFNumberCreate(kCFAllocator
Default, kCFNumberIntType, &zero); | 65 static CFNumberRef essentialLigaturesValue = CFNumberCreate(kCFAllocator
Default, kCFNumberIntType, &zero); |
57 CFDictionarySetValue(mutableAttributes, kCTLigatureAttributeName, essent
ialLigaturesValue); | 66 CFDictionarySetValue(mutableAttributes, kCTLigatureAttributeName, essent
ialLigaturesValue); |
58 } | 67 } |
59 | 68 |
60 if (orientation == Vertical) | 69 if (orientation == Vertical) |
61 CFDictionarySetValue(mutableAttributes, kCTVerticalFormsAttributeName, k
CFBooleanTrue); | 70 CFDictionarySetValue(mutableAttributes, kCTVerticalFormsAttributeName, k
CFBooleanTrue); |
62 | 71 |
63 return attributesDictionary.get(); | 72 return attributesDictionary.get(); |
64 } | 73 } |
65 | 74 |
| 75 static bool shouldUseCoreText(UChar* buffer, unsigned bufferLength, const Simple
FontData* fontData) |
| 76 { |
| 77 if (fontData->platformData().isCompositeFontReference()) |
| 78 return true; |
| 79 |
| 80 // CoreText doesn't have vertical glyphs of surrogate pair characters. |
| 81 // Therefore, we should not use CoreText, but this always returns horizontal
glyphs. |
| 82 // FIXME: We should use vertical glyphs. https://code.google.com/p/chromium/
issues/detail?id=340173 |
| 83 if (bufferLength >= 2 && U_IS_SURROGATE(buffer[0]) && fontData->hasVerticalG
lyphs()) { |
| 84 ASSERT(U_IS_SURROGATE_LEAD(buffer[0])); |
| 85 ASSERT(U_IS_TRAIL(buffer[1])); |
| 86 return false; |
| 87 } |
| 88 |
| 89 if (fontData->platformData().widthVariant() != RegularWidth || fontData->has
VerticalGlyphs()) { |
| 90 // Ideographs don't have a vertical variant or width variants. |
| 91 for (unsigned i = 0; i < bufferLength; ++i) { |
| 92 if (!Character::isCJKIdeograph(buffer[i])) |
| 93 return true; |
| 94 } |
| 95 } |
| 96 |
| 97 return false; |
| 98 } |
| 99 |
| 100 bool SimpleFontData::fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsig
ned length, UChar* buffer, unsigned bufferLength) const |
| 101 { |
| 102 bool haveGlyphs = false; |
| 103 |
| 104 Vector<CGGlyph, 512> glyphs(bufferLength); |
| 105 if (!shouldUseCoreText(buffer, bufferLength, this)) { |
| 106 CGFontGetGlyphsForUnichars(platformData().cgFont(), buffer, glyphs.data(
), bufferLength); |
| 107 for (unsigned i = 0; i < length; ++i) { |
| 108 if (!glyphs[i]) { |
| 109 pageToFill->setGlyphDataForIndex(offset + i, 0, 0); |
| 110 } else { |
| 111 pageToFill->setGlyphDataForIndex(offset + i, glyphs[i], this); |
| 112 haveGlyphs = true; |
| 113 } |
| 114 } |
| 115 } else if (!platformData().isCompositeFontReference() && platformData().widt
hVariant() != RegularWidth |
| 116 && CTFontGetGlyphsForCharacters(platformData().ctFont(), buffer, glyphs.
data(), bufferLength)) { |
| 117 // When buffer consists of surrogate pairs, CTFontGetGlyphsForCharacters |
| 118 // places the glyphs at indices corresponding to the first character of
each pair. |
| 119 unsigned glyphStep = bufferLength / length; |
| 120 for (unsigned i = 0; i < length; ++i) { |
| 121 if (!glyphs[i * glyphStep]) { |
| 122 pageToFill->setGlyphDataForIndex(offset + i, 0, 0); |
| 123 } else { |
| 124 pageToFill->setGlyphDataForIndex(offset + i, glyphs[i * glyphSte
p], this); |
| 125 haveGlyphs = true; |
| 126 } |
| 127 } |
| 128 } else { |
| 129 // We ask CoreText for possible vertical variant glyphs |
| 130 RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCop
y(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull)); |
| 131 RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedS
tringCreate(kCFAllocatorDefault, string.get(), getCFStringAttributes(0, hasVerti
calGlyphs() ? Vertical : Horizontal))); |
| 132 RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attr
ibutedString.get())); |
| 133 |
| 134 CFArrayRef runArray = CTLineGetGlyphRuns(line.get()); |
| 135 CFIndex runCount = CFArrayGetCount(runArray); |
| 136 |
| 137 // Initialize glyph entries |
| 138 for (unsigned index = 0; index < length; ++index) |
| 139 pageToFill->setGlyphDataForIndex(offset + index, 0, 0); |
| 140 |
| 141 Vector<CGGlyph, 512> glyphVector; |
| 142 Vector<CFIndex, 512> indexVector; |
| 143 bool done = false; |
| 144 |
| 145 // For the CGFont comparison in the loop, use the CGFont that Core Text
assigns to the CTFont. This may |
| 146 // be non-CFEqual to platformData().cgFont(). |
| 147 RetainPtr<CGFontRef> cgFont(AdoptCF, CTFontCopyGraphicsFont(platformData
().ctFont(), 0)); |
| 148 |
| 149 for (CFIndex r = 0; r < runCount && !done ; ++r) { |
| 150 // CTLine could map characters over multiple fonts using its own fon
t fallback list. |
| 151 // We need to pick runs that use the exact font we need, i.e., platf
ormData().ctFont(). |
| 152 CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArr
ay, r)); |
| 153 ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID()); |
| 154 |
| 155 CFDictionaryRef attributes = CTRunGetAttributes(ctRun); |
| 156 CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attr
ibutes, kCTFontAttributeName)); |
| 157 RetainPtr<CGFontRef> runCGFont(AdoptCF, CTFontCopyGraphicsFont(runFo
nt, 0)); |
| 158 // Use CGFont here as CFEqual for CTFont counts all attributes for f
ont. |
| 159 bool gotBaseFont = CFEqual(cgFont.get(), runCGFont.get()); |
| 160 if (gotBaseFont || platformData().isCompositeFontReference()) { |
| 161 // This run uses the font we want. Extract glyphs. |
| 162 CFIndex glyphCount = CTRunGetGlyphCount(ctRun); |
| 163 const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun); |
| 164 if (!glyphs) { |
| 165 glyphVector.resize(glyphCount); |
| 166 CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data())
; |
| 167 glyphs = glyphVector.data(); |
| 168 } |
| 169 const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun); |
| 170 if (!stringIndices) { |
| 171 indexVector.resize(glyphCount); |
| 172 CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.
data()); |
| 173 stringIndices = indexVector.data(); |
| 174 } |
| 175 |
| 176 if (gotBaseFont) { |
| 177 for (CFIndex i = 0; i < glyphCount; ++i) { |
| 178 if (stringIndices[i] >= static_cast<CFIndex>(length)) { |
| 179 done = true; |
| 180 break; |
| 181 } |
| 182 if (glyphs[i]) { |
| 183 pageToFill->setGlyphDataForIndex(offset + stringIndi
ces[i], glyphs[i], this); |
| 184 haveGlyphs = true; |
| 185 } |
| 186 } |
| 187 } else { |
| 188 const SimpleFontData* runSimple = getCompositeFontReferenceF
ontData((NSFont *)runFont); |
| 189 if (runSimple) { |
| 190 for (CFIndex i = 0; i < glyphCount; ++i) { |
| 191 if (stringIndices[i] >= static_cast<CFIndex>(length)
) { |
| 192 done = true; |
| 193 break; |
| 194 } |
| 195 if (glyphs[i]) { |
| 196 pageToFill->setGlyphDataForIndex(offset + string
Indices[i], glyphs[i], runSimple); |
| 197 haveGlyphs = true; |
| 198 } |
| 199 } |
| 200 } |
| 201 } |
| 202 } |
| 203 } |
| 204 } |
| 205 |
| 206 return haveGlyphs; |
| 207 } |
| 208 |
66 } // namespace WebCore | 209 } // namespace WebCore |
OLD | NEW |