Chromium Code Reviews| 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 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 250 STACK_ALLOCATED() | 250 STACK_ALLOCATED() |
| 251 public: | 251 public: |
| 252 GlyphBufferBloberizer(const GlyphBuffer& buffer, | 252 GlyphBufferBloberizer(const GlyphBuffer& buffer, |
| 253 const Font* font, | 253 const Font* font, |
| 254 float deviceScaleFactor) | 254 float deviceScaleFactor) |
| 255 : m_buffer(buffer), | 255 : m_buffer(buffer), |
| 256 m_font(font), | 256 m_font(font), |
| 257 m_deviceScaleFactor(deviceScaleFactor), | 257 m_deviceScaleFactor(deviceScaleFactor), |
| 258 m_hasVerticalOffsets(buffer.hasVerticalOffsets()), | 258 m_hasVerticalOffsets(buffer.hasVerticalOffsets()), |
| 259 m_index(0), | 259 m_index(0), |
| 260 m_endIndex(m_buffer.size()), | |
| 260 m_blobCount(0), | 261 m_blobCount(0), |
| 261 m_rotation(buffer.isEmpty() ? NoRotation : computeBlobRotation( | 262 m_rotation(buffer.isEmpty() ? NoRotation : computeBlobRotation( |
| 262 buffer.fontDataAt(0))) {} | 263 buffer.fontDataAt(0))), |
| 264 m_skipGlyphs(nullptr) {} | |
| 263 | 265 |
| 264 bool done() const { return m_index >= m_buffer.size(); } | 266 bool done() const { return m_index >= m_endIndex; } |
| 265 unsigned blobCount() const { return m_blobCount; } | 267 unsigned blobCount() const { return m_blobCount; } |
| 266 | 268 |
| 267 std::pair<sk_sp<SkTextBlob>, BlobRotation> next() { | 269 std::pair<sk_sp<SkTextBlob>, BlobRotation> next() { |
| 268 ASSERT(!done()); | 270 ASSERT(!done()); |
| 269 const BlobRotation currentRotation = m_rotation; | 271 const BlobRotation currentRotation = m_rotation; |
| 270 | 272 |
| 271 while (m_index < m_buffer.size()) { | 273 while (m_index < m_endIndex) { |
| 274 if (m_skipGlyphs) { | |
| 275 while (m_index < m_endIndex && (*m_skipGlyphs)[m_index]) | |
| 276 m_index++; | |
| 277 } | |
| 278 | |
| 272 const SimpleFontData* fontData = m_buffer.fontDataAt(m_index); | 279 const SimpleFontData* fontData = m_buffer.fontDataAt(m_index); |
| 273 ASSERT(fontData); | 280 ASSERT(fontData); |
| 274 | 281 |
| 275 const BlobRotation newRotation = computeBlobRotation(fontData); | 282 const BlobRotation newRotation = computeBlobRotation(fontData); |
| 276 if (newRotation != m_rotation) { | 283 if (newRotation != m_rotation) { |
| 277 // We're switching to an orientation which requires a different rotation | 284 // We're switching to an orientation which requires a different rotation |
| 278 // => emit the pending blob (and start a new one with the new | 285 // => emit the pending blob (and start a new one with the new |
| 279 // rotation). | 286 // rotation). |
| 280 m_rotation = newRotation; | 287 m_rotation = newRotation; |
| 281 break; | 288 break; |
| 282 } | 289 } |
| 283 | 290 |
| 284 const unsigned start = m_index++; | 291 const unsigned start = m_index++; |
| 285 while (m_index < m_buffer.size() && | 292 while (m_index < m_endIndex && m_buffer.fontDataAt(m_index) == fontData && |
| 286 m_buffer.fontDataAt(m_index) == fontData) | 293 !(m_skipGlyphs && (*m_skipGlyphs)[m_index])) |
| 287 m_index++; | 294 m_index++; |
| 288 | 295 |
| 289 appendRun(start, m_index - start, fontData); | 296 appendRun(start, m_index - start, fontData); |
| 290 } | 297 } |
| 291 | 298 |
| 292 m_blobCount++; | 299 m_blobCount++; |
| 293 return std::make_pair(m_builder.make(), currentRotation); | 300 return std::make_pair(m_builder.make(), currentRotation); |
| 294 } | 301 } |
| 295 | 302 |
| 303 void setSkipGlyphs(const Vector<bool>* skipGlyphs) { | |
|
drott
2017/01/02 15:07:46
As mentioned below, I'd prefer if we use the glyph
| |
| 304 m_skipGlyphs = skipGlyphs; | |
| 305 m_endIndex = m_buffer.size(); | |
| 306 if (m_skipGlyphs) { | |
| 307 while (m_endIndex > 0 && (*m_skipGlyphs)[m_endIndex - 1]) | |
| 308 m_endIndex--; | |
| 309 } | |
| 310 } | |
| 311 | |
| 296 private: | 312 private: |
| 297 static BlobRotation computeBlobRotation(const SimpleFontData* font) { | 313 static BlobRotation computeBlobRotation(const SimpleFontData* font) { |
| 298 // For vertical upright text we need to compensate the inherited 90deg CW | 314 // For vertical upright text we need to compensate the inherited 90deg CW |
| 299 // rotation (using a 90deg CCW rotation). | 315 // rotation (using a 90deg CCW rotation). |
| 300 return (font->platformData().isVerticalAnyUpright() && font->verticalData()) | 316 return (font->platformData().isVerticalAnyUpright() && font->verticalData()) |
| 301 ? CCWRotation | 317 ? CCWRotation |
| 302 : NoRotation; | 318 : NoRotation; |
| 303 } | 319 } |
| 304 | 320 |
| 305 void appendRun(unsigned start, | 321 void appendRun(unsigned start, |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 336 } | 352 } |
| 337 } | 353 } |
| 338 | 354 |
| 339 const GlyphBuffer& m_buffer; | 355 const GlyphBuffer& m_buffer; |
| 340 const Font* m_font; | 356 const Font* m_font; |
| 341 const float m_deviceScaleFactor; | 357 const float m_deviceScaleFactor; |
| 342 const bool m_hasVerticalOffsets; | 358 const bool m_hasVerticalOffsets; |
| 343 | 359 |
| 344 SkTextBlobBuilder m_builder; | 360 SkTextBlobBuilder m_builder; |
| 345 unsigned m_index; | 361 unsigned m_index; |
| 362 unsigned m_endIndex; | |
| 346 unsigned m_blobCount; | 363 unsigned m_blobCount; |
| 347 BlobRotation m_rotation; | 364 BlobRotation m_rotation; |
| 365 const Vector<bool>* m_skipGlyphs; | |
|
drott
2017/01/02 15:07:46
I believe we can use this from m_buffer directly?
| |
| 348 }; | 366 }; |
| 349 | 367 |
| 350 } // anonymous namespace | 368 } // anonymous namespace |
| 351 | 369 |
| 352 void Font::drawGlyphBuffer(SkCanvas* canvas, | 370 void Font::drawGlyphBuffer(SkCanvas* canvas, |
| 353 const SkPaint& paint, | 371 const SkPaint& paint, |
| 354 const TextRunPaintInfo& runInfo, | 372 const TextRunPaintInfo& runInfo, |
| 355 const GlyphBuffer& glyphBuffer, | 373 const GlyphBuffer& glyphBuffer, |
| 356 const FloatPoint& point, | 374 const FloatPoint& point, |
| 357 float deviceScaleFactor) const { | 375 float deviceScaleFactor) const { |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 384 *runInfo.cachedTextBlob = std::move(blob.first); | 402 *runInfo.cachedTextBlob = std::move(blob.first); |
| 385 ASSERT(*runInfo.cachedTextBlob); | 403 ASSERT(*runInfo.cachedTextBlob); |
| 386 } | 404 } |
| 387 } | 405 } |
| 388 | 406 |
| 389 static int getInterceptsFromBloberizer(const GlyphBuffer& glyphBuffer, | 407 static int getInterceptsFromBloberizer(const GlyphBuffer& glyphBuffer, |
| 390 const Font* font, | 408 const Font* font, |
| 391 const SkPaint& paint, | 409 const SkPaint& paint, |
| 392 float deviceScaleFactor, | 410 float deviceScaleFactor, |
| 393 const std::tuple<float, float>& bounds, | 411 const std::tuple<float, float>& bounds, |
| 412 const Vector<bool>* skipGlyphs, | |
|
drott
2017/01/02 15:07:46
See below, I think we can remove this argument...
| |
| 394 SkScalar* interceptsBuffer) { | 413 SkScalar* interceptsBuffer) { |
| 395 SkScalar boundsArray[2] = {std::get<0>(bounds), std::get<1>(bounds)}; | 414 SkScalar boundsArray[2] = {std::get<0>(bounds), std::get<1>(bounds)}; |
| 396 GlyphBufferBloberizer bloberizer(glyphBuffer, font, deviceScaleFactor); | 415 GlyphBufferBloberizer bloberizer(glyphBuffer, font, deviceScaleFactor); |
| 416 bloberizer.setSkipGlyphs(skipGlyphs); | |
|
drott
2017/01/02 15:07:46
and this explicit transfer of the skipExceptions v
| |
| 397 std::pair<sk_sp<SkTextBlob>, BlobRotation> blob; | 417 std::pair<sk_sp<SkTextBlob>, BlobRotation> blob; |
| 398 | 418 |
| 399 int numIntervals = 0; | 419 int numIntervals = 0; |
| 400 while (!bloberizer.done()) { | 420 while (!bloberizer.done()) { |
| 401 blob = bloberizer.next(); | 421 blob = bloberizer.next(); |
| 402 DCHECK(blob.first); | 422 DCHECK(blob.first); |
| 403 | 423 |
| 404 // GlyphBufferBloberizer splits for a new blob rotation, but does not split | 424 // GlyphBufferBloberizer splits for a new blob rotation, but does not split |
| 405 // for a change in font. A TextBlob can contain runs with differing fonts | 425 // for a change in font. A TextBlob can contain runs with differing fonts |
| 406 // and the getTextBlobIntercepts method handles multiple fonts for us. For | 426 // and the getTextBlobIntercepts method handles multiple fonts for us. For |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 432 if (!numIntervals) | 452 if (!numIntervals) |
| 433 return; | 453 return; |
| 434 DCHECK_EQ(numIntervals % 2, 0); | 454 DCHECK_EQ(numIntervals % 2, 0); |
| 435 intercepts.resize(numIntervals / 2); | 455 intercepts.resize(numIntervals / 2); |
| 436 paint.getTextBlobIntercepts(runInfo.cachedTextBlob->get(), boundsArray, | 456 paint.getTextBlobIntercepts(runInfo.cachedTextBlob->get(), boundsArray, |
| 437 reinterpret_cast<SkScalar*>(intercepts.data())); | 457 reinterpret_cast<SkScalar*>(intercepts.data())); |
| 438 return; | 458 return; |
| 439 } | 459 } |
| 440 | 460 |
| 441 GlyphBuffer glyphBuffer; | 461 GlyphBuffer glyphBuffer; |
| 442 buildGlyphBuffer(runInfo, glyphBuffer); | 462 const Vector<bool>* skipGlyphs = nullptr; |
| 463 if (runInfo.run.is8Bit()) { | |
| 464 // All characters in Latin-1 should skip inks, so no skipInkExceptions. | |
| 465 buildGlyphBuffer(runInfo, glyphBuffer); | |
| 466 } else { | |
| 467 glyphBuffer.saveSkipInkExceptions(); | |
| 468 buildGlyphBuffer(runInfo, glyphBuffer); | |
| 469 skipGlyphs = &glyphBuffer.skipInkExceptions(); | |
|
drott
2017/01/02 15:07:46
Using state in the GlyphBuffer for shouldSaveSkipI
| |
| 470 } | |
| 443 | 471 |
| 444 // Get the number of intervals, without copying the actual values by | 472 // Get the number of intervals, without copying the actual values by |
| 445 // specifying nullptr for the buffer, following the Skia allocation model for | 473 // specifying nullptr for the buffer, following the Skia allocation model for |
| 446 // retrieving text intercepts. | 474 // retrieving text intercepts. |
| 447 int numIntervals = getInterceptsFromBloberizer( | 475 int numIntervals = getInterceptsFromBloberizer( |
| 448 glyphBuffer, this, paint, deviceScaleFactor, bounds, nullptr); | 476 glyphBuffer, this, paint, deviceScaleFactor, bounds, skipGlyphs, nullptr); |
| 449 if (!numIntervals) | 477 if (!numIntervals) |
| 450 return; | 478 return; |
| 451 DCHECK_EQ(numIntervals % 2, 0); | 479 DCHECK_EQ(numIntervals % 2, 0); |
| 452 intercepts.resize(numIntervals / 2); | 480 intercepts.resize(numIntervals / 2); |
| 453 | 481 |
| 454 getInterceptsFromBloberizer(glyphBuffer, this, paint, deviceScaleFactor, | 482 getInterceptsFromBloberizer(glyphBuffer, this, paint, deviceScaleFactor, |
| 455 bounds, | 483 bounds, skipGlyphs, |
| 456 reinterpret_cast<SkScalar*>(intercepts.data())); | 484 reinterpret_cast<SkScalar*>(intercepts.data())); |
| 457 } | 485 } |
| 458 | 486 |
| 459 static inline FloatRect pixelSnappedSelectionRect(FloatRect rect) { | 487 static inline FloatRect pixelSnappedSelectionRect(FloatRect rect) { |
| 460 // Using roundf() rather than ceilf() for the right edge as a compromise to | 488 // Using roundf() rather than ceilf() for the right edge as a compromise to |
| 461 // ensure correct caret positioning. | 489 // ensure correct caret positioning. |
| 462 float roundedX = roundf(rect.x()); | 490 float roundedX = roundf(rect.x()); |
| 463 return FloatRect(roundedX, rect.y(), roundf(rect.maxX() - roundedX), | 491 return FloatRect(roundedX, rect.y(), roundf(rect.maxX() - roundedX), |
| 464 rect.height()); | 492 rect.height()); |
| 465 } | 493 } |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 620 | 648 |
| 621 bool Font::loadingCustomFonts() const { | 649 bool Font::loadingCustomFonts() const { |
| 622 return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); | 650 return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); |
| 623 } | 651 } |
| 624 | 652 |
| 625 bool Font::isFallbackValid() const { | 653 bool Font::isFallbackValid() const { |
| 626 return !m_fontFallbackList || m_fontFallbackList->isValid(); | 654 return !m_fontFallbackList || m_fontFallbackList->isValid(); |
| 627 } | 655 } |
| 628 | 656 |
| 629 } // namespace blink | 657 } // namespace blink |
| OLD | NEW |