| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2000 Dirk Mueller (mueller@kde.org) | 4 * (C) 2000 Dirk Mueller (mueller@kde.org) |
| 5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved. | 5 * Copyright (C) 2003, 2006, 2010, 2011 Apple Inc. All rights reserved. |
| 6 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. | 6 * Copyright (c) 2007, 2008, 2010 Google Inc. All rights reserved. |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 bool Font::drawText(PaintCanvas* canvas, | 124 bool Font::drawText(PaintCanvas* canvas, |
| 125 const TextRunPaintInfo& runInfo, | 125 const TextRunPaintInfo& runInfo, |
| 126 const FloatPoint& point, | 126 const FloatPoint& point, |
| 127 float deviceScaleFactor, | 127 float deviceScaleFactor, |
| 128 const PaintFlags& flags) const { | 128 const PaintFlags& flags) const { |
| 129 // Don't draw anything while we are using custom fonts that are in the process | 129 // Don't draw anything while we are using custom fonts that are in the process |
| 130 // of loading. | 130 // of loading. |
| 131 if (shouldSkipDrawing()) | 131 if (shouldSkipDrawing()) |
| 132 return false; | 132 return false; |
| 133 | 133 |
| 134 if (runInfo.cachedTextBlob && runInfo.cachedTextBlob->get()) { | |
| 135 // we have a pre-cached blob -- happy joy! | |
| 136 canvas->drawTextBlob(runInfo.cachedTextBlob->get(), point.x(), point.y(), | |
| 137 flags); | |
| 138 return true; | |
| 139 } | |
| 140 | |
| 141 GlyphBuffer glyphBuffer; | 134 GlyphBuffer glyphBuffer; |
| 142 buildGlyphBuffer(runInfo, glyphBuffer); | 135 buildGlyphBuffer(runInfo, glyphBuffer); |
| 143 | 136 |
| 144 drawGlyphBuffer(canvas, flags, runInfo, glyphBuffer, point, | 137 drawGlyphBuffer(canvas, flags, glyphBuffer, point, deviceScaleFactor); |
| 145 deviceScaleFactor); | |
| 146 return true; | 138 return true; |
| 147 } | 139 } |
| 148 | 140 |
| 149 bool Font::drawBidiText(PaintCanvas* canvas, | 141 bool Font::drawBidiText(PaintCanvas* canvas, |
| 150 const TextRunPaintInfo& runInfo, | 142 const TextRunPaintInfo& runInfo, |
| 151 const FloatPoint& point, | 143 const FloatPoint& point, |
| 152 CustomFontNotReadyAction customFontNotReadyAction, | 144 CustomFontNotReadyAction customFontNotReadyAction, |
| 153 float deviceScaleFactor, | 145 float deviceScaleFactor, |
| 154 const PaintFlags& flags) const { | 146 const PaintFlags& flags) const { |
| 155 // Don't draw anything while we are using custom fonts that are in the process | 147 // Don't draw anything while we are using custom fonts that are in the process |
| (...skipping 27 matching lines...) Expand all Loading... |
| 183 subrun.setDirection(isRTL ? TextDirection::kRtl : TextDirection::kLtr); | 175 subrun.setDirection(isRTL ? TextDirection::kRtl : TextDirection::kLtr); |
| 184 subrun.setDirectionalOverride(bidiRun->dirOverride(false)); | 176 subrun.setDirectionalOverride(bidiRun->dirOverride(false)); |
| 185 | 177 |
| 186 TextRunPaintInfo subrunInfo(subrun); | 178 TextRunPaintInfo subrunInfo(subrun); |
| 187 subrunInfo.bounds = runInfo.bounds; | 179 subrunInfo.bounds = runInfo.bounds; |
| 188 | 180 |
| 189 // TODO: investigate blob consolidation/caching (technically, | 181 // TODO: investigate blob consolidation/caching (technically, |
| 190 // all subruns could be part of the same blob). | 182 // all subruns could be part of the same blob). |
| 191 GlyphBuffer glyphBuffer; | 183 GlyphBuffer glyphBuffer; |
| 192 float runWidth = buildGlyphBuffer(subrunInfo, glyphBuffer); | 184 float runWidth = buildGlyphBuffer(subrunInfo, glyphBuffer); |
| 193 drawGlyphBuffer(canvas, flags, subrunInfo, glyphBuffer, currPoint, | 185 drawGlyphBuffer(canvas, flags, glyphBuffer, currPoint, deviceScaleFactor); |
| 194 deviceScaleFactor); | |
| 195 | 186 |
| 196 bidiRun = bidiRun->next(); | 187 bidiRun = bidiRun->next(); |
| 197 currPoint.move(runWidth, 0); | 188 currPoint.move(runWidth, 0); |
| 198 } | 189 } |
| 199 | 190 |
| 200 bidiRuns.deleteRuns(); | 191 bidiRuns.deleteRuns(); |
| 201 return true; | 192 return true; |
| 202 } | 193 } |
| 203 | 194 |
| 204 void Font::drawEmphasisMarks(PaintCanvas* canvas, | 195 void Font::drawEmphasisMarks(PaintCanvas* canvas, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 219 ASSERT(emphasisGlyphData.fontData); | 210 ASSERT(emphasisGlyphData.fontData); |
| 220 if (!emphasisGlyphData.fontData) | 211 if (!emphasisGlyphData.fontData) |
| 221 return; | 212 return; |
| 222 | 213 |
| 223 GlyphBuffer glyphBuffer; | 214 GlyphBuffer glyphBuffer; |
| 224 buildGlyphBuffer(runInfo, glyphBuffer, &emphasisGlyphData); | 215 buildGlyphBuffer(runInfo, glyphBuffer, &emphasisGlyphData); |
| 225 | 216 |
| 226 if (glyphBuffer.isEmpty()) | 217 if (glyphBuffer.isEmpty()) |
| 227 return; | 218 return; |
| 228 | 219 |
| 229 drawGlyphBuffer(canvas, flags, runInfo, glyphBuffer, point, | 220 drawGlyphBuffer(canvas, flags, glyphBuffer, point, deviceScaleFactor); |
| 230 deviceScaleFactor); | |
| 231 } | 221 } |
| 232 | 222 |
| 233 float Font::width(const TextRun& run, | 223 float Font::width(const TextRun& run, |
| 234 HashSet<const SimpleFontData*>* fallbackFonts, | 224 HashSet<const SimpleFontData*>* fallbackFonts, |
| 235 FloatRect* glyphBounds) const { | 225 FloatRect* glyphBounds) const { |
| 236 FontCachePurgePreventer purgePreventer; | 226 FontCachePurgePreventer purgePreventer; |
| 237 CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription)); | 227 CachingWordShaper shaper(m_fontFallbackList->shapeCache(m_fontDescription)); |
| 238 float width = shaper.width(this, run, fallbackFonts, glyphBounds); | 228 float width = shaper.width(this, run, fallbackFonts, glyphBounds); |
| 239 return width; | 229 return width; |
| 240 } | 230 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 251 public: | 241 public: |
| 252 GlyphBufferBloberizer(const GlyphBuffer& buffer, | 242 GlyphBufferBloberizer(const GlyphBuffer& buffer, |
| 253 const Font* font, | 243 const Font* font, |
| 254 float deviceScaleFactor) | 244 float deviceScaleFactor) |
| 255 : m_buffer(buffer), | 245 : m_buffer(buffer), |
| 256 m_font(font), | 246 m_font(font), |
| 257 m_deviceScaleFactor(deviceScaleFactor), | 247 m_deviceScaleFactor(deviceScaleFactor), |
| 258 m_hasVerticalOffsets(buffer.hasVerticalOffsets()), | 248 m_hasVerticalOffsets(buffer.hasVerticalOffsets()), |
| 259 m_index(0), | 249 m_index(0), |
| 260 m_endIndex(m_buffer.size()), | 250 m_endIndex(m_buffer.size()), |
| 261 m_blobCount(0), | |
| 262 m_rotation(buffer.isEmpty() ? NoRotation : computeBlobRotation( | 251 m_rotation(buffer.isEmpty() ? NoRotation : computeBlobRotation( |
| 263 buffer.fontDataAt(0))) {} | 252 buffer.fontDataAt(0))) {} |
| 264 | 253 |
| 265 bool done() const { return m_index >= m_endIndex; } | 254 bool done() const { return m_index >= m_endIndex; } |
| 266 unsigned blobCount() const { return m_blobCount; } | |
| 267 | 255 |
| 268 std::pair<sk_sp<SkTextBlob>, BlobRotation> next() { | 256 std::pair<sk_sp<SkTextBlob>, BlobRotation> next() { |
| 269 ASSERT(!done()); | 257 ASSERT(!done()); |
| 270 const BlobRotation currentRotation = m_rotation; | 258 const BlobRotation currentRotation = m_rotation; |
| 271 | 259 |
| 272 while (m_index < m_endIndex) { | 260 while (m_index < m_endIndex) { |
| 273 const SimpleFontData* fontData = m_buffer.fontDataAt(m_index); | 261 const SimpleFontData* fontData = m_buffer.fontDataAt(m_index); |
| 274 ASSERT(fontData); | 262 ASSERT(fontData); |
| 275 | 263 |
| 276 const BlobRotation newRotation = computeBlobRotation(fontData); | 264 const BlobRotation newRotation = computeBlobRotation(fontData); |
| 277 if (newRotation != m_rotation) { | 265 if (newRotation != m_rotation) { |
| 278 // We're switching to an orientation which requires a different rotation | 266 // We're switching to an orientation which requires a different rotation |
| 279 // => emit the pending blob (and start a new one with the new | 267 // => emit the pending blob (and start a new one with the new |
| 280 // rotation). | 268 // rotation). |
| 281 m_rotation = newRotation; | 269 m_rotation = newRotation; |
| 282 break; | 270 break; |
| 283 } | 271 } |
| 284 | 272 |
| 285 const unsigned start = m_index++; | 273 const unsigned start = m_index++; |
| 286 while (m_index < m_endIndex && m_buffer.fontDataAt(m_index) == fontData) | 274 while (m_index < m_endIndex && m_buffer.fontDataAt(m_index) == fontData) |
| 287 m_index++; | 275 m_index++; |
| 288 | 276 |
| 289 appendRun(start, m_index - start, fontData); | 277 appendRun(start, m_index - start, fontData); |
| 290 } | 278 } |
| 291 | 279 |
| 292 m_blobCount++; | |
| 293 return std::make_pair(m_builder.make(), currentRotation); | 280 return std::make_pair(m_builder.make(), currentRotation); |
| 294 } | 281 } |
| 295 | 282 |
| 296 private: | 283 private: |
| 297 static BlobRotation computeBlobRotation(const SimpleFontData* font) { | 284 static BlobRotation computeBlobRotation(const SimpleFontData* font) { |
| 298 // For vertical upright text we need to compensate the inherited 90deg CW | 285 // For vertical upright text we need to compensate the inherited 90deg CW |
| 299 // rotation (using a 90deg CCW rotation). | 286 // rotation (using a 90deg CCW rotation). |
| 300 return (font->platformData().isVerticalAnyUpright() && font->verticalData()) | 287 return (font->platformData().isVerticalAnyUpright() && font->verticalData()) |
| 301 ? CCWRotation | 288 ? CCWRotation |
| 302 : NoRotation; | 289 : NoRotation; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 } | 324 } |
| 338 | 325 |
| 339 const GlyphBuffer& m_buffer; | 326 const GlyphBuffer& m_buffer; |
| 340 const Font* m_font; | 327 const Font* m_font; |
| 341 const float m_deviceScaleFactor; | 328 const float m_deviceScaleFactor; |
| 342 const bool m_hasVerticalOffsets; | 329 const bool m_hasVerticalOffsets; |
| 343 | 330 |
| 344 SkTextBlobBuilder m_builder; | 331 SkTextBlobBuilder m_builder; |
| 345 unsigned m_index; | 332 unsigned m_index; |
| 346 unsigned m_endIndex; | 333 unsigned m_endIndex; |
| 347 unsigned m_blobCount; | |
| 348 BlobRotation m_rotation; | 334 BlobRotation m_rotation; |
| 349 }; | 335 }; |
| 350 | 336 |
| 351 } // anonymous namespace | 337 } // anonymous namespace |
| 352 | 338 |
| 353 void Font::drawGlyphBuffer(PaintCanvas* canvas, | 339 void Font::drawGlyphBuffer(PaintCanvas* canvas, |
| 354 const PaintFlags& flags, | 340 const PaintFlags& flags, |
| 355 const TextRunPaintInfo& runInfo, | |
| 356 const GlyphBuffer& glyphBuffer, | 341 const GlyphBuffer& glyphBuffer, |
| 357 const FloatPoint& point, | 342 const FloatPoint& point, |
| 358 float deviceScaleFactor) const { | 343 float deviceScaleFactor) const { |
| 359 GlyphBufferBloberizer bloberizer(glyphBuffer, this, deviceScaleFactor); | 344 GlyphBufferBloberizer bloberizer(glyphBuffer, this, deviceScaleFactor); |
| 360 std::pair<sk_sp<SkTextBlob>, BlobRotation> blob; | |
| 361 | 345 |
| 362 while (!bloberizer.done()) { | 346 while (!bloberizer.done()) { |
| 363 blob = bloberizer.next(); | 347 auto blob = bloberizer.next(); |
| 364 ASSERT(blob.first); | 348 ASSERT(blob.first); |
| 365 | 349 |
| 366 PaintCanvasAutoRestore autoRestore(canvas, false); | 350 PaintCanvasAutoRestore autoRestore(canvas, false); |
| 367 if (blob.second == CCWRotation) { | 351 if (blob.second == CCWRotation) { |
| 368 canvas->save(); | 352 canvas->save(); |
| 369 | 353 |
| 370 SkMatrix m; | 354 SkMatrix m; |
| 371 m.setSinCos(-1, 0, point.x(), point.y()); | 355 m.setSinCos(-1, 0, point.x(), point.y()); |
| 372 canvas->concat(m); | 356 canvas->concat(m); |
| 373 } | 357 } |
| 374 | 358 |
| 375 canvas->drawTextBlob(blob.first, point.x(), point.y(), flags); | 359 canvas->drawTextBlob(blob.first, point.x(), point.y(), flags); |
| 376 } | 360 } |
| 377 | |
| 378 // Cache results when | |
| 379 // 1) requested by clients, and | |
| 380 // 2) the glyph buffer is encoded as a single blob, and | |
| 381 // 3) the blob is not upright/rotated | |
| 382 if (runInfo.cachedTextBlob && bloberizer.blobCount() == 1 && | |
| 383 blob.second == NoRotation) { | |
| 384 ASSERT(!*runInfo.cachedTextBlob); | |
| 385 *runInfo.cachedTextBlob = std::move(blob.first); | |
| 386 ASSERT(*runInfo.cachedTextBlob); | |
| 387 } | |
| 388 } | 361 } |
| 389 | 362 |
| 390 static int getInterceptsFromBloberizer(const GlyphBuffer& glyphBuffer, | 363 static int getInterceptsFromBloberizer(const GlyphBuffer& glyphBuffer, |
| 391 const Font* font, | 364 const Font* font, |
| 392 const PaintFlags& flags, | 365 const PaintFlags& flags, |
| 393 float deviceScaleFactor, | 366 float deviceScaleFactor, |
| 394 const std::tuple<float, float>& bounds, | 367 const std::tuple<float, float>& bounds, |
| 395 SkScalar* interceptsBuffer) { | 368 SkScalar* interceptsBuffer) { |
| 396 SkScalar boundsArray[2] = {std::get<0>(bounds), std::get<1>(bounds)}; | 369 SkScalar boundsArray[2] = {std::get<0>(bounds), std::get<1>(bounds)}; |
| 397 GlyphBufferBloberizer bloberizer(glyphBuffer, font, deviceScaleFactor); | 370 GlyphBufferBloberizer bloberizer(glyphBuffer, font, deviceScaleFactor); |
| 398 std::pair<sk_sp<SkTextBlob>, BlobRotation> blob; | |
| 399 | 371 |
| 400 int numIntervals = 0; | 372 int numIntervals = 0; |
| 401 while (!bloberizer.done()) { | 373 while (!bloberizer.done()) { |
| 402 blob = bloberizer.next(); | 374 auto blob = bloberizer.next(); |
| 403 DCHECK(blob.first); | 375 DCHECK(blob.first); |
| 404 | 376 |
| 405 // GlyphBufferBloberizer splits for a new blob rotation, but does not split | 377 // GlyphBufferBloberizer splits for a new blob rotation, but does not split |
| 406 // for a change in font. A TextBlob can contain runs with differing fonts | 378 // for a change in font. A TextBlob can contain runs with differing fonts |
| 407 // and the getTextBlobIntercepts method handles multiple fonts for us. For | 379 // and the getTextBlobIntercepts method handles multiple fonts for us. For |
| 408 // upright in vertical blobs we currently have to bail, see crbug.com/655154 | 380 // upright in vertical blobs we currently have to bail, see crbug.com/655154 |
| 409 if (blob.second == BlobRotation::CCWRotation) | 381 if (blob.second == BlobRotation::CCWRotation) |
| 410 continue; | 382 continue; |
| 411 | 383 |
| 412 SkScalar* offsetInterceptsBuffer = nullptr; | 384 SkScalar* offsetInterceptsBuffer = nullptr; |
| 413 if (interceptsBuffer) | 385 if (interceptsBuffer) |
| 414 offsetInterceptsBuffer = &interceptsBuffer[numIntervals]; | 386 offsetInterceptsBuffer = &interceptsBuffer[numIntervals]; |
| 415 numIntervals += flags.getTextBlobIntercepts(blob.first.get(), boundsArray, | 387 numIntervals += flags.getTextBlobIntercepts(blob.first.get(), boundsArray, |
| 416 offsetInterceptsBuffer); | 388 offsetInterceptsBuffer); |
| 417 } | 389 } |
| 418 return numIntervals; | 390 return numIntervals; |
| 419 } | 391 } |
| 420 | 392 |
| 421 void Font::getTextIntercepts(const TextRunPaintInfo& runInfo, | 393 void Font::getTextIntercepts(const TextRunPaintInfo& runInfo, |
| 422 float deviceScaleFactor, | 394 float deviceScaleFactor, |
| 423 const PaintFlags& flags, | 395 const PaintFlags& flags, |
| 424 const std::tuple<float, float>& bounds, | 396 const std::tuple<float, float>& bounds, |
| 425 Vector<TextIntercept>& intercepts) const { | 397 Vector<TextIntercept>& intercepts) const { |
| 426 if (shouldSkipDrawing()) | 398 if (shouldSkipDrawing()) |
| 427 return; | 399 return; |
| 428 | 400 |
| 429 DCHECK(!runInfo.cachedTextBlob); | |
| 430 | |
| 431 GlyphBuffer glyphBuffer(GlyphBuffer::Type::TextIntercepts); | 401 GlyphBuffer glyphBuffer(GlyphBuffer::Type::TextIntercepts); |
| 432 buildGlyphBuffer(runInfo, glyphBuffer); | 402 buildGlyphBuffer(runInfo, glyphBuffer); |
| 433 | 403 |
| 434 // Get the number of intervals, without copying the actual values by | 404 // Get the number of intervals, without copying the actual values by |
| 435 // specifying nullptr for the buffer, following the Skia allocation model for | 405 // specifying nullptr for the buffer, following the Skia allocation model for |
| 436 // retrieving text intercepts. | 406 // retrieving text intercepts. |
| 437 int numIntervals = getInterceptsFromBloberizer( | 407 int numIntervals = getInterceptsFromBloberizer( |
| 438 glyphBuffer, this, flags, deviceScaleFactor, bounds, nullptr); | 408 glyphBuffer, this, flags, deviceScaleFactor, bounds, nullptr); |
| 439 if (!numIntervals) | 409 if (!numIntervals) |
| 440 return; | 410 return; |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 610 | 580 |
| 611 bool Font::loadingCustomFonts() const { | 581 bool Font::loadingCustomFonts() const { |
| 612 return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); | 582 return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); |
| 613 } | 583 } |
| 614 | 584 |
| 615 bool Font::isFallbackValid() const { | 585 bool Font::isFallbackValid() const { |
| 616 return !m_fontFallbackList || m_fontFallbackList->isValid(); | 586 return !m_fontFallbackList || m_fontFallbackList->isValid(); |
| 617 } | 587 } |
| 618 | 588 |
| 619 } // namespace blink | 589 } // namespace blink |
| OLD | NEW |