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 | 9 |
10 #include "SkScalerContext.h" | 10 #include "SkScalerContext.h" |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 SkReadBuffer buffer(data, len); | 76 SkReadBuffer buffer(data, len); |
77 obj = buffer.readFlattenable(ft); | 77 obj = buffer.readFlattenable(ft); |
78 SkASSERT(buffer.offset() == buffer.size()); | 78 SkASSERT(buffer.offset() == buffer.size()); |
79 } | 79 } |
80 return obj; | 80 return obj; |
81 } | 81 } |
82 | 82 |
83 SkScalerContext::SkScalerContext(SkTypeface* typeface, const SkDescriptor* desc) | 83 SkScalerContext::SkScalerContext(SkTypeface* typeface, const SkDescriptor* desc) |
84 : fRec(*static_cast<const Rec*>(desc->findEntry(kRec_SkDescriptorTag, NULL))
) | 84 : fRec(*static_cast<const Rec*>(desc->findEntry(kRec_SkDescriptorTag, NULL))
) |
85 | 85 |
86 , fBaseGlyphCount(0) | |
87 , fTypeface(SkRef(typeface)) | 86 , fTypeface(SkRef(typeface)) |
88 , fPathEffect(static_cast<SkPathEffect*>(load_flattenable(desc, kPathEffect_
SkDescriptorTag, | 87 , fPathEffect(static_cast<SkPathEffect*>(load_flattenable(desc, kPathEffect_
SkDescriptorTag, |
89 SkFlattenable::kSkPathEffect_Type))
) | 88 SkFlattenable::kSkPathEffect_Type))
) |
90 , fMaskFilter(static_cast<SkMaskFilter*>(load_flattenable(desc, kMaskFilter_
SkDescriptorTag, | 89 , fMaskFilter(static_cast<SkMaskFilter*>(load_flattenable(desc, kMaskFilter_
SkDescriptorTag, |
91 SkFlattenable::kSkMaskFilter_Type))
) | 90 SkFlattenable::kSkMaskFilter_Type))
) |
92 , fRasterizer(static_cast<SkRasterizer*>(load_flattenable(desc, kRasterizer_
SkDescriptorTag, | 91 , fRasterizer(static_cast<SkRasterizer*>(load_flattenable(desc, kRasterizer_
SkDescriptorTag, |
93 SkFlattenable::kSkRasterizer_Type))
) | 92 SkFlattenable::kSkRasterizer_Type))
) |
94 // Initialize based on our settings. Subclasses can also force this. | 93 // Initialize based on our settings. Subclasses can also force this. |
95 , fGenerateImageFromPath(fRec.fFrameWidth > 0 || fPathEffect != NULL || fRas
terizer != NULL) | 94 , fGenerateImageFromPath(fRec.fFrameWidth > 0 || fPathEffect != NULL || fRas
terizer != NULL) |
96 | 95 |
97 , fNextContext(NULL) | |
98 | |
99 , fPreBlend(fMaskFilter ? SkMaskGamma::PreBlend() : SkScalerContext::GetMask
PreBlend(fRec)) | 96 , fPreBlend(fMaskFilter ? SkMaskGamma::PreBlend() : SkScalerContext::GetMask
PreBlend(fRec)) |
100 , fPreBlendForFilter(fMaskFilter ? SkScalerContext::GetMaskPreBlend(fRec) | 97 , fPreBlendForFilter(fMaskFilter ? SkScalerContext::GetMaskPreBlend(fRec) |
101 : SkMaskGamma::PreBlend()) | 98 : SkMaskGamma::PreBlend()) |
102 { | 99 { |
103 #ifdef DUMP_REC | 100 #ifdef DUMP_REC |
104 desc->assertChecksum(); | 101 desc->assertChecksum(); |
105 SkDebugf("SkScalerContext checksum %x count %d length %d\n", | 102 SkDebugf("SkScalerContext checksum %x count %d length %d\n", |
106 desc->getChecksum(), desc->getCount(), desc->getLength()); | 103 desc->getChecksum(), desc->getCount(), desc->getLength()); |
107 SkDebugf(" textsize %g prescale %g preskew %g post [%g %g %g %g]\n", | 104 SkDebugf(" textsize %g prescale %g preskew %g post [%g %g %g %g]\n", |
108 rec->fTextSize, rec->fPreScaleX, rec->fPreSkewX, rec->fPost2x2[0][0], | 105 rec->fTextSize, rec->fPreScaleX, rec->fPreSkewX, rec->fPost2x2[0][0], |
(...skipping 10 matching lines...) Expand all Loading... |
119 const void* data = desc->findEntry(kAndroidOpts_SkDescriptorTag, &len); | 116 const void* data = desc->findEntry(kAndroidOpts_SkDescriptorTag, &len); |
120 if (data) { | 117 if (data) { |
121 SkReadBuffer buffer(data, len); | 118 SkReadBuffer buffer(data, len); |
122 fPaintOptionsAndroid.unflatten(buffer); | 119 fPaintOptionsAndroid.unflatten(buffer); |
123 SkASSERT(buffer.offset() == buffer.size()); | 120 SkASSERT(buffer.offset() == buffer.size()); |
124 } | 121 } |
125 #endif | 122 #endif |
126 } | 123 } |
127 | 124 |
128 SkScalerContext::~SkScalerContext() { | 125 SkScalerContext::~SkScalerContext() { |
129 SkDELETE(fNextContext); | |
130 | |
131 SkSafeUnref(fPathEffect); | 126 SkSafeUnref(fPathEffect); |
132 SkSafeUnref(fMaskFilter); | 127 SkSafeUnref(fMaskFilter); |
133 SkSafeUnref(fRasterizer); | 128 SkSafeUnref(fRasterizer); |
134 } | 129 } |
135 | 130 |
136 // Return the context associated with the next logical typeface, or NULL if | |
137 // there are no more entries in the fallback chain. | |
138 SkScalerContext* SkScalerContext::allocNextContext() const { | |
139 #ifdef SK_BUILD_FOR_ANDROID | |
140 SkTypeface* newFace = SkAndroidNextLogicalTypeface(fRec.fFontID, | |
141 fRec.fOrigFontID, | |
142 fPaintOptionsAndroid); | |
143 if (0 == newFace) { | |
144 return NULL; | |
145 } | |
146 | |
147 SkAutoTUnref<SkTypeface> aur(newFace); | |
148 uint32_t newFontID = newFace->uniqueID(); | |
149 | |
150 SkWriteBuffer androidBuffer; | |
151 fPaintOptionsAndroid.flatten(androidBuffer); | |
152 | |
153 SkAutoDescriptor ad(sizeof(fRec) + androidBuffer.bytesWritten() | |
154 + SkDescriptor::ComputeOverhead(2)); | |
155 SkDescriptor* desc = ad.getDesc(); | |
156 | |
157 desc->init(); | |
158 SkScalerContext::Rec* newRec = | |
159 (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag, | |
160 sizeof(fRec), &fRec); | |
161 androidBuffer.writeToMemory(desc->addEntry(kAndroidOpts_SkDescriptorTag, | |
162 androidBuffer.bytesWritten(), NUL
L)); | |
163 | |
164 newRec->fFontID = newFontID; | |
165 desc->computeChecksum(); | |
166 | |
167 return newFace->createScalerContext(desc); | |
168 #else | |
169 return NULL; | |
170 #endif | |
171 } | |
172 | |
173 /* Return the next context, creating it if its not already created, but return | |
174 NULL if the fonthost says there are no more fonts to fallback to. | |
175 */ | |
176 SkScalerContext* SkScalerContext::getNextContext() { | |
177 SkScalerContext* next = fNextContext; | |
178 // if next is null, then either it isn't cached yet, or we're at the | |
179 // end of our possible chain | |
180 if (NULL == next) { | |
181 next = this->allocNextContext(); | |
182 if (NULL == next) { | |
183 return NULL; | |
184 } | |
185 // next's base is our base + our local count | |
186 next->setBaseGlyphCount(fBaseGlyphCount + this->getGlyphCount()); | |
187 // cache the answer | |
188 fNextContext = next; | |
189 } | |
190 return next; | |
191 } | |
192 | |
193 SkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) { | |
194 unsigned glyphID = glyph.getGlyphID(); | |
195 SkScalerContext* ctx = this; | |
196 for (;;) { | |
197 unsigned count = ctx->getGlyphCount(); | |
198 if (glyphID < count) { | |
199 break; | |
200 } | |
201 glyphID -= count; | |
202 ctx = ctx->getNextContext(); | |
203 if (NULL == ctx) { | |
204 // SkDebugf("--- no context for glyph %x\n", glyph.getGlyphID()); | |
205 // just return the original context (this) | |
206 return this; | |
207 } | |
208 } | |
209 return ctx; | |
210 } | |
211 | |
212 SkScalerContext* SkScalerContext::getContextFromChar(SkUnichar uni, | |
213 uint16_t* glyphID) { | |
214 SkScalerContext* ctx = this; | |
215 for (;;) { | |
216 const uint16_t glyph = ctx->generateCharToGlyph(uni); | |
217 if (glyph) { | |
218 if (NULL != glyphID) { | |
219 *glyphID = glyph; | |
220 } | |
221 break; // found it | |
222 } | |
223 ctx = ctx->getNextContext(); | |
224 if (NULL == ctx) { | |
225 return NULL; | |
226 } | |
227 } | |
228 return ctx; | |
229 } | |
230 | |
231 #ifdef SK_BUILD_FOR_ANDROID | |
232 SkFontID SkScalerContext::findTypefaceIdForChar(SkUnichar uni) { | |
233 SkScalerContext* ctx = this->getContextFromChar(uni, NULL); | |
234 if (NULL != ctx) { | |
235 return ctx->fRec.fFontID; | |
236 } else { | |
237 return 0; | |
238 } | |
239 } | |
240 | |
241 /* This loops through all available fallback contexts (if needed) until it | |
242 finds some context that can handle the unichar and return it. | |
243 | |
244 As this is somewhat expensive operation, it should only be done on the first | |
245 char of a run. | |
246 */ | |
247 unsigned SkScalerContext::getBaseGlyphCount(SkUnichar uni) { | |
248 SkScalerContext* ctx = this->getContextFromChar(uni, NULL); | |
249 if (NULL != ctx) { | |
250 return ctx->fBaseGlyphCount; | |
251 } else { | |
252 SkDEBUGF(("--- no context for char %x\n", uni)); | |
253 return this->fBaseGlyphCount; | |
254 } | |
255 } | |
256 #endif | |
257 | |
258 /* This loops through all available fallback contexts (if needed) until it | |
259 finds some context that can handle the unichar. If all fail, returns 0 | |
260 */ | |
261 uint16_t SkScalerContext::charToGlyphID(SkUnichar uni) { | |
262 | |
263 uint16_t tempID; | |
264 SkScalerContext* ctx = this->getContextFromChar(uni, &tempID); | |
265 if (NULL == ctx) { | |
266 return 0; // no more contexts, return missing glyph | |
267 } | |
268 // add the ctx's base, making glyphID unique for chain of contexts | |
269 unsigned glyphID = tempID + ctx->fBaseGlyphCount; | |
270 // check for overflow of 16bits, since our glyphID cannot exceed that | |
271 if (glyphID > 0xFFFF) { | |
272 glyphID = 0; | |
273 } | |
274 return SkToU16(glyphID); | |
275 } | |
276 | |
277 SkUnichar SkScalerContext::glyphIDToChar(uint16_t glyphID) { | |
278 SkScalerContext* ctx = this; | |
279 unsigned rangeEnd = 0; | |
280 do { | |
281 unsigned rangeStart = rangeEnd; | |
282 | |
283 rangeEnd += ctx->getGlyphCount(); | |
284 if (rangeStart <= glyphID && glyphID < rangeEnd) { | |
285 return ctx->generateGlyphToChar(glyphID - rangeStart); | |
286 } | |
287 ctx = ctx->getNextContext(); | |
288 } while (NULL != ctx); | |
289 return 0; | |
290 } | |
291 | |
292 void SkScalerContext::getAdvance(SkGlyph* glyph) { | 131 void SkScalerContext::getAdvance(SkGlyph* glyph) { |
293 // mark us as just having a valid advance | 132 // mark us as just having a valid advance |
294 glyph->fMaskFormat = MASK_FORMAT_JUST_ADVANCE; | 133 glyph->fMaskFormat = MASK_FORMAT_JUST_ADVANCE; |
295 // we mark the format before making the call, in case the impl | 134 // we mark the format before making the call, in case the impl |
296 // internally ends up calling its generateMetrics, which is OK | 135 // internally ends up calling its generateMetrics, which is OK |
297 // albeit slower than strictly necessary | 136 // albeit slower than strictly necessary |
298 this->getGlyphContext(*glyph)->generateAdvance(glyph); | 137 generateAdvance(glyph); |
299 } | 138 } |
300 | 139 |
301 void SkScalerContext::getMetrics(SkGlyph* glyph) { | 140 void SkScalerContext::getMetrics(SkGlyph* glyph) { |
302 this->getGlyphContext(*glyph)->generateMetrics(glyph); | 141 generateMetrics(glyph); |
303 | 142 |
304 // for now we have separate cache entries for devkerning on and off | 143 // for now we have separate cache entries for devkerning on and off |
305 // in the future we might share caches, but make our measure/draw | 144 // in the future we might share caches, but make our measure/draw |
306 // code make the distinction. Thus we zap the values if the caller | 145 // code make the distinction. Thus we zap the values if the caller |
307 // has not asked for them. | 146 // has not asked for them. |
308 if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) { | 147 if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) { |
309 // no devkern, so zap the fields | 148 // no devkern, so zap the fields |
310 glyph->fLsbDelta = glyph->fRsbDelta = 0; | 149 glyph->fLsbDelta = glyph->fRsbDelta = 0; |
311 } | 150 } |
312 | 151 |
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
730 return; | 569 return; |
731 } | 570 } |
732 if (fPreBlend.isApplicable()) { | 571 if (fPreBlend.isApplicable()) { |
733 applyLUTToA8Mask(mask, fPreBlend.fG); | 572 applyLUTToA8Mask(mask, fPreBlend.fG); |
734 } | 573 } |
735 } else { | 574 } else { |
736 SkASSERT(SkMask::kARGB32_Format != mask.fFormat); | 575 SkASSERT(SkMask::kARGB32_Format != mask.fFormat); |
737 generateMask(mask, devPath, fPreBlend); | 576 generateMask(mask, devPath, fPreBlend); |
738 } | 577 } |
739 } else { | 578 } else { |
740 this->getGlyphContext(*glyph)->generateImage(*glyph); | 579 generateImage(*glyph); |
741 } | 580 } |
742 | 581 |
743 if (fMaskFilter) { | 582 if (fMaskFilter) { |
744 SkMask srcM, dstM; | 583 SkMask srcM, dstM; |
745 SkMatrix matrix; | 584 SkMatrix matrix; |
746 | 585 |
747 // the src glyph image shouldn't be 3D | 586 // the src glyph image shouldn't be 3D |
748 SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat); | 587 SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat); |
749 | 588 |
750 SkAutoSMalloc<32*32> a8storage; | 589 SkAutoSMalloc<32*32> a8storage; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
804 | 643 |
805 SkUnichar SkScalerContext::generateGlyphToChar(uint16_t glyph) { | 644 SkUnichar SkScalerContext::generateGlyphToChar(uint16_t glyph) { |
806 return 0; | 645 return 0; |
807 } | 646 } |
808 | 647 |
809 /////////////////////////////////////////////////////////////////////////////// | 648 /////////////////////////////////////////////////////////////////////////////// |
810 | 649 |
811 void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath, | 650 void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath, |
812 SkPath* devPath, SkMatrix* fillToDevMatrix) { | 651 SkPath* devPath, SkMatrix* fillToDevMatrix) { |
813 SkPath path; | 652 SkPath path; |
814 | 653 generatePath(glyph, &path); |
815 this->getGlyphContext(glyph)->generatePath(glyph, &path); | |
816 | 654 |
817 if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { | 655 if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) { |
818 SkFixed dx = glyph.getSubXFixed(); | 656 SkFixed dx = glyph.getSubXFixed(); |
819 SkFixed dy = glyph.getSubYFixed(); | 657 SkFixed dy = glyph.getSubYFixed(); |
820 if (dx | dy) { | 658 if (dx | dy) { |
821 path.offset(SkFixedToScalar(dx), SkFixedToScalar(dy)); | 659 path.offset(SkFixedToScalar(dx), SkFixedToScalar(dy)); |
822 } | 660 } |
823 } | 661 } |
824 | 662 |
825 if (fRec.fFrameWidth > 0 || fPathEffect != NULL) { | 663 if (fRec.fFrameWidth > 0 || fPathEffect != NULL) { |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
967 SkScalerContext* SkTypeface::createScalerContext(const SkDescriptor* desc, | 805 SkScalerContext* SkTypeface::createScalerContext(const SkDescriptor* desc, |
968 bool allowFailure) const { | 806 bool allowFailure) const { |
969 SkScalerContext* c = this->onCreateScalerContext(desc); | 807 SkScalerContext* c = this->onCreateScalerContext(desc); |
970 | 808 |
971 if (!c && !allowFailure) { | 809 if (!c && !allowFailure) { |
972 c = SkNEW_ARGS(SkScalerContext_Empty, | 810 c = SkNEW_ARGS(SkScalerContext_Empty, |
973 (const_cast<SkTypeface*>(this), desc)); | 811 (const_cast<SkTypeface*>(this), desc)); |
974 } | 812 } |
975 return c; | 813 return c; |
976 } | 814 } |
OLD | NEW |