OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (C) 2005, 2006, 2012 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2006 Alexey Proskuryakov |
| 4 * |
| 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions |
| 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright |
| 11 * notice, this list of conditions and the following disclaimer in the |
| 12 * documentation and/or other materials provided with the distribution. |
| 13 * |
| 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, |
| 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| 18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 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 |
| 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 |
| 24 * THE POSSIBILITY OF SUCH DAMAGE. |
| 25 */ |
| 26 |
| 27 #include "config.h" |
| 28 #include "platform/fonts/SimpleFontData.h" |
| 29 |
| 30 #include "platform/fonts/Character.h" |
| 31 #include "platform/fonts/Font.h" |
| 32 #include "platform/fonts/GlyphPage.h" |
| 33 #include <ApplicationServices/ApplicationServices.h> |
| 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 |
| 41 namespace blink { |
| 42 |
| 43 CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typese
ttingFeatures, FontOrientation orientation) const |
| 44 { |
| 45 unsigned key = typesettingFeatures + 1; |
| 46 HashMap<unsigned, RetainPtr<CFDictionaryRef> >::AddResult addResult = m_CFSt
ringAttributes.add(key, RetainPtr<CFDictionaryRef>()); |
| 47 RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.storedValue->va
lue; |
| 48 if (!addResult.isNewEntry) |
| 49 return attributesDictionary.get(); |
| 50 |
| 51 attributesDictionary.adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault,
4, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); |
| 52 CFMutableDictionaryRef mutableAttributes = (CFMutableDictionaryRef)attribute
sDictionary.get(); |
| 53 |
| 54 CFDictionarySetValue(mutableAttributes, kCTFontAttributeName, platformData()
.ctFont()); |
| 55 |
| 56 if (!(typesettingFeatures & Kerning)) { |
| 57 const float zero = 0; |
| 58 static CFNumberRef zeroKerningValue = CFNumberCreate(kCFAllocatorDefault
, kCFNumberFloatType, &zero); |
| 59 CFDictionarySetValue(mutableAttributes, kCTKernAttributeName, zeroKernin
gValue); |
| 60 } |
| 61 |
| 62 bool allowLigatures = (orientation == Horizontal && platformData().allowsLig
atures()) || (typesettingFeatures & Ligatures); |
| 63 if (!allowLigatures) { |
| 64 const int zero = 0; |
| 65 static CFNumberRef essentialLigaturesValue = CFNumberCreate(kCFAllocator
Default, kCFNumberIntType, &zero); |
| 66 CFDictionarySetValue(mutableAttributes, kCTLigatureAttributeName, essent
ialLigaturesValue); |
| 67 } |
| 68 |
| 69 if (orientation == Vertical) |
| 70 CFDictionarySetValue(mutableAttributes, kCTVerticalFormsAttributeName, k
CFBooleanTrue); |
| 71 |
| 72 return attributesDictionary.get(); |
| 73 } |
| 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, glyphs[i], this); |
| 110 haveGlyphs = true; |
| 111 } |
| 112 } |
| 113 } else if (!platformData().isCompositeFontReference() && platformData().widt
hVariant() != RegularWidth |
| 114 && CTFontGetGlyphsForCharacters(platformData().ctFont(), buffer, glyphs.
data(), bufferLength)) { |
| 115 // When buffer consists of surrogate pairs, CTFontGetGlyphsForCharacters |
| 116 // places the glyphs at indices corresponding to the first character of
each pair. |
| 117 unsigned glyphStep = bufferLength / length; |
| 118 for (unsigned i = 0; i < length; ++i) { |
| 119 if (glyphs[i * glyphStep]) { |
| 120 pageToFill->setGlyphDataForIndex(offset + i, glyphs[i * glyphSte
p], this); |
| 121 haveGlyphs = true; |
| 122 } |
| 123 } |
| 124 } else { |
| 125 // We ask CoreText for possible vertical variant glyphs |
| 126 RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCop
y(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull)); |
| 127 RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedS
tringCreate(kCFAllocatorDefault, string.get(), getCFStringAttributes(0, hasVerti
calGlyphs() ? Vertical : Horizontal))); |
| 128 RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attr
ibutedString.get())); |
| 129 |
| 130 CFArrayRef runArray = CTLineGetGlyphRuns(line.get()); |
| 131 CFIndex runCount = CFArrayGetCount(runArray); |
| 132 |
| 133 Vector<CGGlyph, 512> glyphVector; |
| 134 Vector<CFIndex, 512> indexVector; |
| 135 bool done = false; |
| 136 |
| 137 // For the CGFont comparison in the loop, use the CGFont that Core Text
assigns to the CTFont. This may |
| 138 // be non-CFEqual to platformData().cgFont(). |
| 139 RetainPtr<CGFontRef> cgFont(AdoptCF, CTFontCopyGraphicsFont(platformData
().ctFont(), 0)); |
| 140 |
| 141 for (CFIndex r = 0; r < runCount && !done ; ++r) { |
| 142 // CTLine could map characters over multiple fonts using its own fon
t fallback list. |
| 143 // We need to pick runs that use the exact font we need, i.e., platf
ormData().ctFont(). |
| 144 CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArr
ay, r)); |
| 145 ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID()); |
| 146 |
| 147 CFDictionaryRef attributes = CTRunGetAttributes(ctRun); |
| 148 CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attr
ibutes, kCTFontAttributeName)); |
| 149 RetainPtr<CGFontRef> runCGFont(AdoptCF, CTFontCopyGraphicsFont(runFo
nt, 0)); |
| 150 // Use CGFont here as CFEqual for CTFont counts all attributes for f
ont. |
| 151 bool gotBaseFont = CFEqual(cgFont.get(), runCGFont.get()); |
| 152 if (gotBaseFont || platformData().isCompositeFontReference()) { |
| 153 // This run uses the font we want. Extract glyphs. |
| 154 CFIndex glyphCount = CTRunGetGlyphCount(ctRun); |
| 155 const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun); |
| 156 if (!glyphs) { |
| 157 glyphVector.resize(glyphCount); |
| 158 CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data())
; |
| 159 glyphs = glyphVector.data(); |
| 160 } |
| 161 const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun); |
| 162 if (!stringIndices) { |
| 163 indexVector.resize(glyphCount); |
| 164 CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.
data()); |
| 165 stringIndices = indexVector.data(); |
| 166 } |
| 167 |
| 168 if (gotBaseFont) { |
| 169 for (CFIndex i = 0; i < glyphCount; ++i) { |
| 170 if (stringIndices[i] >= static_cast<CFIndex>(length)) { |
| 171 done = true; |
| 172 break; |
| 173 } |
| 174 if (glyphs[i]) { |
| 175 pageToFill->setGlyphDataForIndex(offset + stringIndi
ces[i], glyphs[i], this); |
| 176 haveGlyphs = true; |
| 177 } |
| 178 } |
| 179 } else { |
| 180 const SimpleFontData* runSimple = getCompositeFontReferenceF
ontData((NSFont *)runFont); |
| 181 if (runSimple) { |
| 182 for (CFIndex i = 0; i < glyphCount; ++i) { |
| 183 if (stringIndices[i] >= static_cast<CFIndex>(length)
) { |
| 184 done = true; |
| 185 break; |
| 186 } |
| 187 if (glyphs[i]) { |
| 188 pageToFill->setGlyphDataForIndex(offset + string
Indices[i], glyphs[i], runSimple); |
| 189 haveGlyphs = true; |
| 190 } |
| 191 } |
| 192 } |
| 193 } |
| 194 } |
| 195 } |
| 196 } |
| 197 |
| 198 return haveGlyphs; |
| 199 } |
| 200 |
| 201 } // namespace blink |
OLD | NEW |