| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. | 2 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * 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 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 verticalData->getVerticalTranslationsForGlyphs(font, &glyphs[0], chu
nkLength, reinterpret_cast<float*>(&translations[0])); | 150 verticalData->getVerticalTranslationsForGlyphs(font, &glyphs[0], chu
nkLength, reinterpret_cast<float*>(&translations[0])); |
| 151 | 151 |
| 152 x = verticalOriginX; | 152 x = verticalOriginX; |
| 153 y = SkFloatToScalar(point.y() + horizontalOffset - point.x()); | 153 y = SkFloatToScalar(point.y() + horizontalOffset - point.x()); |
| 154 | 154 |
| 155 float currentWidth = 0; | 155 float currentWidth = 0; |
| 156 for (unsigned i = 0; i < chunkLength; ++i, ++glyphIndex) { | 156 for (unsigned i = 0; i < chunkLength; ++i, ++glyphIndex) { |
| 157 pos[i].set( | 157 pos[i].set( |
| 158 x + SkIntToScalar(lroundf(translations[i].x())), | 158 x + SkIntToScalar(lroundf(translations[i].x())), |
| 159 y + -SkIntToScalar(-lroundf(currentWidth - translations[i].y
()))); | 159 y + -SkIntToScalar(-lroundf(currentWidth - translations[i].y
()))); |
| 160 currentWidth += glyphBuffer.advanceAt(from + glyphIndex).width()
; | 160 currentWidth += glyphBuffer.advanceAt(from + glyphIndex); |
| 161 } | 161 } |
| 162 horizontalOffset += currentWidth; | 162 horizontalOffset += currentWidth; |
| 163 paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect); | 163 paintGlyphs(gc, font, glyphs, chunkLength, pos, textRect); |
| 164 } | 164 } |
| 165 | 165 |
| 166 gc->setCTM(savedMatrix); | 166 gc->setCTM(savedMatrix); |
| 167 return; | 167 return; |
| 168 } | 168 } |
| 169 | 169 |
| 170 if (!glyphBuffer.hasVerticalAdvances()) { | 170 if (!glyphBuffer.hasOffsets()) { |
| 171 SkAutoSTMalloc<64, SkScalar> storage(numGlyphs); | 171 SkAutoSTMalloc<64, SkScalar> storage(numGlyphs); |
| 172 SkScalar* xpos = storage.get(); | 172 SkScalar* xpos = storage.get(); |
| 173 const FloatSize* adv = glyphBuffer.advances(from); | 173 const float* adv = glyphBuffer.advances(from); |
| 174 for (unsigned i = 0; i < numGlyphs; i++) { | 174 for (unsigned i = 0; i < numGlyphs; i++) { |
| 175 xpos[i] = x; | 175 xpos[i] = x; |
| 176 x += SkFloatToScalar(adv[i].width()); | 176 x += SkFloatToScalar(adv[i]); |
| 177 } | 177 } |
| 178 const Glyph* glyphs = glyphBuffer.glyphs(from); | 178 const Glyph* glyphs = glyphBuffer.glyphs(from); |
| 179 paintGlyphsHorizontal(gc, font, glyphs, numGlyphs, xpos, SkFloatToScalar
(y), textRect); | 179 paintGlyphsHorizontal(gc, font, glyphs, numGlyphs, xpos, SkFloatToScalar
(y), textRect); |
| 180 return; | 180 return; |
| 181 } | 181 } |
| 182 | 182 |
| 183 // FIXME: text rendering speed: | 183 ASSERT(glyphBuffer.hasOffsets()); |
| 184 // Android has code in their WebCore fork to special case when the | 184 const GlyphBufferWithOffsets& glyphBufferWithOffsets = |
| 185 // GlyphBuffer has no advances other than the defaults. In that case the | 185 static_cast<const GlyphBufferWithOffsets&>(glyphBuffer); |
| 186 // text drawing can proceed faster. However, it's unclear when those | |
| 187 // patches may be upstreamed to WebKit so we always use the slower path | |
| 188 // here. | |
| 189 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); | 186 SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); |
| 190 SkPoint* pos = storage.get(); | 187 SkPoint* pos = storage.get(); |
| 191 const FloatSize* adv = glyphBuffer.advances(from); | 188 const FloatSize* offsets = glyphBufferWithOffsets.offsets(from); |
| 189 const float* advances = glyphBufferWithOffsets.advances(from); |
| 190 SkScalar advanceSoFar = SkFloatToScalar(0); |
| 192 for (unsigned i = 0; i < numGlyphs; i++) { | 191 for (unsigned i = 0; i < numGlyphs; i++) { |
| 193 pos[i].set(x, y); | 192 pos[i].set( |
| 194 x += SkFloatToScalar(adv[i].width()); | 193 x + SkFloatToScalar(offsets[i].width()) + advanceSoFar, |
| 195 y += SkFloatToScalar(adv[i].height()); | 194 y + SkFloatToScalar(offsets[i].height())); |
| 195 advanceSoFar += SkFloatToScalar(advances[i]); |
| 196 } | 196 } |
| 197 | 197 |
| 198 const Glyph* glyphs = glyphBuffer.glyphs(from); | 198 const Glyph* glyphs = glyphBufferWithOffsets.glyphs(from); |
| 199 paintGlyphs(gc, font, glyphs, numGlyphs, pos, textRect); | 199 paintGlyphs(gc, font, glyphs, numGlyphs, pos, textRect); |
| 200 } | 200 } |
| 201 | 201 |
| 202 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi
nt& origin) const | 202 void Font::drawTextBlob(GraphicsContext* gc, const SkTextBlob* blob, const SkPoi
nt& origin) const |
| 203 { | 203 { |
| 204 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); | 204 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); |
| 205 | 205 |
| 206 // FIXME: It would be good to move this to Font.cpp, if we're sure that none | 206 // FIXME: It would be good to move this to Font.cpp, if we're sure that none |
| 207 // of the things in FontMac's setupPaint need to apply here. | 207 // of the things in FontMac's setupPaint need to apply here. |
| 208 // See also paintGlyphs. | 208 // See also paintGlyphs. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 224 if (!runInfo.run.length()) | 224 if (!runInfo.run.length()) |
| 225 return 0; | 225 return 0; |
| 226 | 226 |
| 227 TextDrawingModeFlags textMode = gc->textDrawingMode(); | 227 TextDrawingModeFlags textMode = gc->textDrawingMode(); |
| 228 bool fill = textMode & TextModeFill; | 228 bool fill = textMode & TextModeFill; |
| 229 bool stroke = (textMode & TextModeStroke) && gc->hasStroke(); | 229 bool stroke = (textMode & TextModeStroke) && gc->hasStroke(); |
| 230 | 230 |
| 231 if (!fill && !stroke) | 231 if (!fill && !stroke) |
| 232 return 0; | 232 return 0; |
| 233 | 233 |
| 234 GlyphBuffer glyphBuffer; | 234 GlyphBufferWithOffsets glyphBuffer; |
| 235 HarfBuzzShaper shaper(this, runInfo.run); | 235 HarfBuzzShaper shaper(this, runInfo.run); |
| 236 shaper.setDrawRange(runInfo.from, runInfo.to); | 236 shaper.setDrawRange(runInfo.from, runInfo.to); |
| 237 if (!shaper.shape(&glyphBuffer) || glyphBuffer.isEmpty()) | 237 if (!shaper.shape(&glyphBuffer) || glyphBuffer.isEmpty()) |
| 238 return 0; | 238 return 0; |
| 239 FloatPoint adjustedPoint = shaper.adjustStartPoint(point); | 239 return drawGlyphBuffer(gc, runInfo, glyphBuffer, point); |
| 240 return drawGlyphBuffer(gc, runInfo, glyphBuffer, adjustedPoint); | |
| 241 } | 240 } |
| 242 | 241 |
| 243 void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextR
unPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const | 242 void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextR
unPaintInfo& runInfo, const AtomicString& mark, const FloatPoint& point) const |
| 244 { | 243 { |
| 245 GlyphBuffer glyphBuffer; | 244 GlyphBuffer glyphBuffer; |
| 246 | 245 |
| 247 float initialAdvance = getGlyphsAndAdvancesForComplexText(runInfo, glyphBuff
er, ForTextEmphasis); | 246 float initialAdvance = getGlyphsAndAdvancesForComplexText(runInfo, glyphBuff
er, ForTextEmphasis); |
| 248 | 247 |
| 249 if (glyphBuffer.isEmpty()) | 248 if (glyphBuffer.isEmpty()) |
| 250 return; | 249 return; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 return shaper.selectionRect(point, height, from, to); | 294 return shaper.selectionRect(point, height, from, to); |
| 296 } | 295 } |
| 297 | 296 |
| 298 PassTextBlobPtr Font::buildTextBlob(const GlyphBuffer& glyphBuffer, float initia
lAdvance, | 297 PassTextBlobPtr Font::buildTextBlob(const GlyphBuffer& glyphBuffer, float initia
lAdvance, |
| 299 const FloatRect& bounds, float& advance, bool couldUseLCD) const | 298 const FloatRect& bounds, float& advance, bool couldUseLCD) const |
| 300 { | 299 { |
| 301 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); | 300 ASSERT(RuntimeEnabledFeatures::textBlobEnabled()); |
| 302 | 301 |
| 303 // FIXME: Except for setupPaint, this is not specific to FontHarfBuzz. | 302 // FIXME: Except for setupPaint, this is not specific to FontHarfBuzz. |
| 304 // FIXME: Also implement the more general full-positioning path. | 303 // FIXME: Also implement the more general full-positioning path. |
| 305 ASSERT(!glyphBuffer.hasVerticalAdvances()); | 304 ASSERT(!glyphBuffer.hasOffsets()); |
| 306 | 305 |
| 307 SkTextBlobBuilder builder; | 306 SkTextBlobBuilder builder; |
| 308 SkScalar x = SkFloatToScalar(initialAdvance); | 307 SkScalar x = SkFloatToScalar(initialAdvance); |
| 309 SkRect skBounds = bounds; | 308 SkRect skBounds = bounds; |
| 310 | 309 |
| 311 unsigned i = 0; | 310 unsigned i = 0; |
| 312 while (i < glyphBuffer.size()) { | 311 while (i < glyphBuffer.size()) { |
| 313 const SimpleFontData* fontData = glyphBuffer.fontDataAt(i); | 312 const SimpleFontData* fontData = glyphBuffer.fontDataAt(i); |
| 314 | 313 |
| 315 // FIXME: Handle vertical text. | 314 // FIXME: Handle vertical text. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 333 unsigned start = i++; | 332 unsigned start = i++; |
| 334 while (i < glyphBuffer.size() && glyphBuffer.fontDataAt(i) == fontData) | 333 while (i < glyphBuffer.size() && glyphBuffer.fontDataAt(i) == fontData) |
| 335 i++; | 334 i++; |
| 336 unsigned count = i - start; | 335 unsigned count = i - start; |
| 337 | 336 |
| 338 const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPosH(paint,
count, 0, &skBounds); | 337 const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPosH(paint,
count, 0, &skBounds); |
| 339 | 338 |
| 340 const uint16_t* glyphs = glyphBuffer.glyphs(start); | 339 const uint16_t* glyphs = glyphBuffer.glyphs(start); |
| 341 std::copy(glyphs, glyphs + count, buffer.glyphs); | 340 std::copy(glyphs, glyphs + count, buffer.glyphs); |
| 342 | 341 |
| 343 const FloatSize* advances = glyphBuffer.advances(start); | 342 const float* advances = glyphBuffer.advances(start); |
| 344 for (unsigned j = 0; j < count; j++) { | 343 for (unsigned j = 0; j < count; j++) { |
| 345 buffer.pos[j] = x; | 344 buffer.pos[j] = x; |
| 346 x += SkFloatToScalar(advances[j].width()); | 345 x += SkFloatToScalar(advances[j]); |
| 347 } | 346 } |
| 348 } | 347 } |
| 349 | 348 |
| 350 advance = x; | 349 advance = x; |
| 351 return adoptRef(builder.build()); | 350 return adoptRef(builder.build()); |
| 352 } | 351 } |
| 353 | 352 |
| 354 } // namespace blink | 353 } // namespace blink |
| OLD | NEW |